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

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

1.3 DMA

这是关于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传输出方波的效果

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

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

  • 5
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: tms320f2837xd技术手册是一本详细介绍了TMS320F2837xD系列数字信号处理器的技术手册。这个系列的数字信号处理器是基于C28x内核的,旨在满足高性能控制应用的需要。本手册详细介绍了该系列DSP的主要性能参数、内部体系结构、编程模型、外部接口、以及各种应用场景和应用案例等方面。 在该手册中,读者可以学习如何使用TMS320F2837xD进行高精度AD和DA的控制、运动控制、电源控制、以及各种复杂控制应用等。手册中包含了丰富的代码示例和应用案例,以帮助读者深入理解该系列DSP的编程特点,学习如何灵活使用它来应对各种实际应用场景。 此外,技术手册还详细介绍了该系列DSP与其他外围器件和接口的配合使用,以及支持的开发环境、软件工具和调试接口等方面。这些内容为使用者提供了全面的技术支持,帮助开发者更加容易地使用TMS320F2837xD系列数字信号处理器。 综上所述,tms320f2837xd技术手册对于学习和使用该系列数字信号处理器的开发人员来说是一份非常重要的参考资料,它为开发人员提供了全方位的技术支持,帮助开发者更好地应对各种复杂控制应用场景的需求,具有非常广泛的应用前景。 ### 回答2: tms320f2837xd是德州仪器(TI)推出的一款数字信号处理器(DSP)芯片,该芯片基于TI公司的C2000系列DSP架构。该芯片提供了高性能、低功耗和多功能的特点,能够满足各种应用领域的需求。 该芯片集成了两个DSP核心,每个核心都有一个浮点单元(FPU),能够支持高速运算和复杂计算。芯片还包括多达15个12位模数转换器(ADC)和2个12位数模转换器(DAC),以及多个通用IO端口和协议接口,如SPI、I2C、CAN和串口等,可方便地连接各种外围设备和通信接口。此外,该芯片还具备多种安全保护机制和故障保护功能,可提供可靠性和稳定性保障。 tms320f2837xd技术手册提供了该芯片详细的技术参数和功能说明,包括DSP核心、ADC和DAC、IO端口和通信接口、调试和编程接口、安全保护和故障保护等方面的内容。其中,手册还提供了丰富的应用案例和实验,可以帮助工程师深入了解和掌握该芯片的应用技巧和实现方法,快速完成产品开发和测试。 总之,tms320f2837xd技术手册是研发人员在进行DSP控制和应用开发时的重要参考资料,可帮助各种终端产品加速上市,提供更加完善和优异的性能和功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值