TMS320F28377D库函数操作(DMA+DAC)

作为MCU的深度用户最近想学习学习DSP了,可以明显感觉到DSP的软件和硬件与MCU的差别。不过老实说,其实DSP与MCU的区别对于纯写软件角度来说区别并不大,无非就是寄存器或是库函数的操作,至于说内核的区别,其实真的感受不到因为这年头还有谁会去写汇编呢(巨佬,或是碰到玄学问题除外。。)毕竟各个大厂都积极拥抱各种通用库甚至是图形化初始化芯片。。。那我为啥还说软件和硬件有明显区别呢?诸君且坐,听我细细道来。

说回这块DSP——TMS320F28377D,虽然网上的资料多,但是功能一旦高级一点点,做的人是真的少,比如说这次的这个功能,我翻遍全网都没找到任何一点资料,官方倒是给了一份例程,是库函数和寄存器混合编程,着实头疼,正因如此我做完后才想分享出来。如果有小白读到这篇文章,我建议还是老老实实学先学STM32F103全网资料漫天飞,这能让你对数字或是模拟系统有一个总览的概念。

目录

1.模块介绍

1.1 EPWM

1.2 DAC

1.3 DMA

2.程序

2.1 DAC及EPWM11初始化

 2.2 DMA初始化

 2.3 DMA中断服务函数

3. 效果


1.模块介绍

如果,首先我们先看一下需要用到的各个模块

1.1 EPWM

如果是第一次接触DSP或是MCU转DSP朋友肯定很好奇为啥要用到这个模块?在MCU里是用timer触发DAC然后相当于DAC呼起一次DMA传输(不太了解的盆友,出门右转,我以前做了一份关于STM32F407的DAC+DMA的过程,也在我的博客下)在28377中EPWM几乎代替了timer在MCU的地位,很多的外设由EPWM来触发,这里我选用EPWM11来触发。

1.2 DAC

TMS320F28377D库函数操作(DMA+DAC)_第1张图片

这是官方关于DAC的介绍,原本我想的传输数据与EPWM同步,但是翻遍各个能找的地方,都没能找到如何用EPWM来触发DAC,最后只能让DAC变为一直开启,即影子寄存器一有数据就立刻转移到DAC寄存器里。不过我转换了一下思路,最终实现效果。

1.3 DMA

TMS320F28377D库函数操作(DMA+DAC)_第2张图片

这是关于DMA的介绍可以看到触发源其中有EPWM信号,在官方的例程中有一份例程,可用EPEM触发DMA搬运到EPWM寄存器里从而改变EPWM的值,我灵光乍现把目标改为DAC发现是可以的。

最后我们理一下思路,DAC其实是一直从影子寄存器想数据寄存器搬运数据,由EPWM触发一次DMA的搬运。当DMA搬运后DAC就会更新(这个速率我不知多快,但是更新速度非常快即使EPWM的速度达到巅峰也没有延迟)所以EPWM的翻转速率决定了DAC输出波形速率。

2.程序

2.1 DAC及EPWM11初始化

#ifndef KEY_MYDAC_H_
#define KEY_MYDAC_H_

#include "dac.h"
#include "epwm.h"
#include "device.h"

#define EPWM_TIMER_TBPRD    50UL //EPWM速率
#define SinLength 42UL //数组长度

void configureDACA(void);
void initEPWM_for_dac(uint32_t base);
#include "MyDac.h"


void initEPWM_for_dac(uint32_t base)
{
    EPWM_setEmulationMode(base, EPWM_EMULATION_STOP_AFTER_FULL_CYCLE);

    //
    // Set-up TBCLK
    //
    EPWM_setTimeBasePeriod(base, EPWM_TIMER_TBPRD);
    EPWM_setPhaseShift(base, 0U);
    EPWM_setTimeBaseCounter(base, 0U);

    //
    // Set Compare values
    //
    EPWM_setCounterCompareValue(base,
                                EPWM_COUNTER_COMPARE_A,
                                EPWM_TIMER_TBPRD/2);

    //
    // Set up counter mode
    //
    EPWM_setTimeBaseCounterMode(base, EPWM_COUNTER_MODE_UP);
    EPWM_disablePhaseShiftLoad(base);
    EPWM_setClockPrescaler(base,
                           EPWM_CLOCK_DIVIDER_64,
                           EPWM_HSCLOCK_DIVIDER_1);

    //
    // Set up shadowing
    //
    EPWM_setCounterCompareShadowLoadMode(base,
                                         EPWM_COUNTER_COMPARE_A,
                                         EPWM_COMP_LOAD_ON_CNTR_ZERO);



    //
    // Interrupt where we will change the Compare Values
    // Select INT on Time base counter zero event,
    // Enable INT, generate INT on 1st event


    //
    EPWM_setInterruptSource(base, EPWM_INT_TBCTR_ZERO);
    EPWM_enableInterrupt(base);
    EPWM_setInterruptEventCount(base, 1U);

    EPWM_enableADCTrigger(base, EPWM_SOC_A);
    EPWM_setADCTriggerSource(base,
                             EPWM_SOC_A,
                             EPWM_SOC_TBCTR_ZERO);
    EPWM_setADCTriggerEventPrescale(base,
                                    EPWM_SOC_A,
                                       1);
    EPWM_clearADCTriggerFlag(base,
                             EPWM_SOC_A);
}



void configureDACA(void)
{

    //
    // 当选择DAC_REF_VDAC是需要外接电源到ADCINB0上同时注意PCB设计
    // 当选择DAC_REF_ADC_VREFHI时为内部电源
    //
    DAC_setReferenceVoltage(DACA_BASE, DAC_REF_ADC_VREFHI);


    DAC_setLoadMode(DACA_BASE,DAC_LOAD_PWMSYNC);

    DAC_setPWMSyncSignal(DACA_BASE,1);

    //
    // Enable the DAC output
    //
    DAC_enableOutput(DACA_BASE);

    //
    // Set the DAC shadow output to 0
    //
    DAC_setShadowValue(DACA_BASE, 1000);

    //
    // Delay for buffered DAC to power up
    //
    DEVICE_DELAY_US(10);


}

 2.2 DMA初始化

#include "MyDma.h"

#pragma DATA_SECTION(FMSin, "ramgs0");  // map the TX data to memory

unsigned short FMSin[SinLength+3] =
{
    2149,2295,2434,2563,2680,
    2782,2866,2931,2975,2997,
    2997,2975,2931,2866,2782,
    2680,2563,2434,2295,2149,
    2000,1851,1705,1566,1437,
    1320,1218,1134,1069,1025,
    1003,1003,1025,1069,1134,
    1218,1320,1437,1566,1705,
    1851,2000,2149
//     0,1000,2000,3000,1000,500,200
};

//
// DMA setup channels.
//
void initDMA6_DAC()
{
    //
    // Initialize DMA
    //
    DMA_initController();

    //
    // DMA CH6
    //
    DMA_configAddresses(DMA_CH6_BASE, (uint16_t *)(DACA_BASE+DAC_O_VALS),
                        FMSin);

    //第一位:指定DMA
    //第二位:单次传输的量
    //第三位:一次突发传输后发送地址的增量
    //第四位:一次突发传输后目标地址的增量
    DMA_configBurst(DMA_CH6_BASE,21,2,0);

    //第一位:指定DMA
    //第二位:突发传输次数
    //第三位:一次传输后发送目标地址的增量
    //第四位:一次传输后发送接收地址的增量
    DMA_configTransfer(DMA_CH6_BASE,21,-42,0);

    DMA_configMode(DMA_CH6_BASE, DMA_TRIGGER_EPWM8SOCA, DMA_CFG_ONESHOT_DISABLE |
                   DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);

    //
    // Configure DMA Ch6 interrupts
    //
    DMA_setInterruptMode(DMA_CH6_BASE, DMA_INT_AT_END);
    DMA_enableInterrupt(DMA_CH6_BASE);
    DMA_enableTrigger(DMA_CH6_BASE);

}

在程序中由一段

DMA_configBurst(DMA_CH6_BASE,21,2,0);
DMA_configTransfer(DMA_CH6_BASE,21,-42,0);

这是传输的核心,它配置了传输数据量,两个函数的第一参数是那个DMA,在第一个函数第二位是指单次突发传输的次数而第二位只的是每次突发传输后原数组指针的增量,最后一个参数是指目标地址的增量,所以每次传输时对于原来的数组来说FMSin[0],FMSin[2],FMSin[4] 。。。FMSin[42]但是目标地址即DACA来说,地址是不变的所以最后一位是0。

对于第二个函数是指当完成上述的突发传输后就会执行传输,21依旧是传输个数,即21次,-42指的是单次突发传输完成后进行源地址指针操作,就是说单次突发操作后指针指向了数组的第42位,这是指针减42,也就是回归到0然后再进行下一次突发传输,一直执行21次。

这里的21也是有讲究的,如果传输个数小于或等于突发传输的次数,就会一直执行形成连贯的函数,但是若是大于突发传输次数就会在执行完成后停止传输,等待DMA重新初始化,这无疑会进入中断在高频下波形会有点失真,可惜的是突发传输的次数最大就是32,这样一来对于后端的滤波会增加负担,但是波形能连贯一点,当然这看个人的取舍吧。

 2.3 DMA中断服务函数

__interrupt void dmaCh6ISR(void)
{
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);
    //ESTOP0;
    return;
}

2.4 主函数

void main(void)
{

    init_CPU1();                //初始化CPU1
    SysCtl_selectSecMaster(1, 1);

    initDMA6_DAC();
    initEPWM_for_dac(EPWM8_BASE);
    Interrupt_register(INT_DMA_CH6, &dmaCh6ISR);

    ENINT;                      //启用全局中断和实时中断
    configureDACA();            //开启DACA
    Interrupt_enable(INT_DMA_CH6);
    DMA_startChannel(DMA_CH6_BASE);

    while(1)
    {
        ;
    }
}

3. 效果

这是28377d传输出方波的效果

TMS320F28377D库函数操作(DMA+DAC)_第3张图片

这是安富莱用H743做出方波的效果,对比可以看出28377对比743的DAC还有好,不仅频率更高1.6倍,波形还更好看。

 最后是输出正弦波,当然也是轻轻松松。

你可能感兴趣的:(TMS320F28377,嵌入式硬件,dsp开发)