历史上的今天
今天是:2025年01月26日(星期日)
2021年01月26日 | MSP430F5529 多通道ADC定时器触发+DMA传输
2021-01-26 来源:eefocus
竞赛之前学习了一下从没有使用过的MSP430单片机,使用的是MSP430F5529的demo板,这块板子应该是MSP430中比较流行的一块了。使用这块板子实现了一个双通道ADC的定时器触发DMA传输,这里记录一下给别人一点参考,同时也为以后需要用到的时候提供笔记。废话不多说直接上源码,代码如下。
#include #include int data_buf0[100]; int data_buf1[100]; /** * main.c */ int main(void) { unsigned int i; WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer P1DIR |= BIT0; // P1.0 output P1OUT &= ~BIT0; // P1.0 clear P5SEL |= BIT7; // P5.7/TB1 option select P5DIR |= BIT7; // Output direction P6SEL |= 0x03; // Enable A/D channel A0 A1 //Setup Timer B0 TBCCR0 = 0xfffe; TBCCR1 = 0x8000; TBCCTL1 = OUTMOD_3; // CCR1 set/reset mode TBEX0 = TBIDEX_7; //CLK/8 divide TBCTL = TBSSEL_2+MC_1+TBCLR + ID_3; // SMCLK, Up-Mode // Setup ADC12 ADC12CTL0 = ADC12ON+ADC12MSC+ADC12SHT0_8; // Turn on ADC12, extend sampling time // to avoid overflow of results ADC12CTL1 = ADC12SHS_3+ADC12CONSEQ_3; // Use sampling timer, repeated sequence ADC12MCTL0 = ADC12INCH_0; // ref+=AVcc, channel = A0 ADC12MCTL1 = ADC12INCH_1 + ADC12EOS; // ref+=AVcc, channel = A1 ADC12CTL0 |= ADC12ENC; // Enable conversions // Setup DMA COMMON DMACTL0 = DMA0TSEL_24 + DMA1TSEL_24; // ADC12IFGx triggered DMACTL4 = DMARMWDIS; // Read-modify-write disable // Setup DMA0 DMA0CTL &= ~DMAIFG; DMA0CTL = DMADT_4+DMAEN+DMADSTINCR_3; // Rpt single tranfer, Destination address is incremented. DMA0SZ = 100; // DMA0 size = 100 __data20_write_long((uintptr_t) &DMA0SA,(uintptr_t) &ADC12MEM0); // Source block address __data20_write_long((uintptr_t) &DMA0DA,(uintptr_t) &data_buf0[0]); // Setup DMA1 DMA1CTL &= ~DMAIFG; DMA1CTL = DMADT_4+DMAEN+DMADSTINCR_3; // Rpt single tranfer, Destination address is incremented. DMA1SZ = 100; // DMA0 size = 100 __data20_write_long((uintptr_t) &DMA1SA,(uintptr_t) &ADC12MEM1); // Source block address __data20_write_long((uintptr_t) &DMA1DA,(uintptr_t) &data_buf1[0]); while (1) { P1OUT ^= BIT0; for (i = 0; i < 50000; i++); } return 0; } 首先是IO的初始化配置,之后配置TB定时器,由于程序中没有修改单片机的主频,所以单片机的主频默认是1M的,TB定时器的时钟源SMCLK也是1M,设置TBCCR0 = 65534,并且配置了TBEX0 = TBIDEX_7;和TBCTL 的ID_3字段,所以时钟分频为8*8=64分频,相关的寄存器的位详解请参考MSP430f5529的User’s Guide。所以最终的定时器定时频率为1000000/64/65535=0.238,周期就是4.2s。 注意 所以这个ADC12定时器触发配合DMA关于转换周期的问题在实际应用中还是需要注意的。
接下是ADC配置ADC12CTL0 = ADC12ON+ADC12MSC+ADC12SHT0_8;就是开启ADC、多次采样、设置周期。ADC12CTL1 = ADC12SHS_3+ADC12CONSEQ_3;设置触发源为TB1_CCR1(ADC12SHS_3),工作在重复队列转换模式Repeat-sequence-of-channels(ADC12CONSEQ_3)。然后就是设置队列使能ADC。
之后就是DMA配置了,先是配置DMA的共同寄存器部分。DMACTL0 = DMA0TSEL_24 + DMA1TSEL_24;设置DMA0和DMA1的触发源,选择24号触发源,通过查看数据手册可以知道24号触发源对应的就是ADC_12。然后就是特定DMA的配置了,这里就介绍一下DMA0的配置,DMA1的配置都是相同的。DMA0CTL &= ~DMAIFG;清除中断标志。DMA0CTL = DMADT_4+DMAEN+DMADSTINCR_3;重复单次传输Repeated single transfer(DMADT_4),开启DMA,目标地址递增Destination address is incremented(DMADSTINCR_3)。然后设置传输的数据量、源地址、目标地址即可。
在使用过程中我发现一个问题,那就是ADC的转换周期 = 定时器周期 x ADC通道数,例如我的定时器周期为4.2s,ADC通道为2,ADC转换周期就是4.22=8.4s。开启ADC转换8.4s后DMA同时将两个通道的ADC数据传输到缓存中。为此我开启了3个ADC通道进行了实验,TB的周期还是4.2s,MCU主频1M,实验结果如下所示。

可以看出程序运行了21s后缓存中还是只有一次转换结果。使程序继续运行看一下两次转换需要多久。

28s的时候已经完成了两次转换,按照计算两次转换的时间为4.23*2=25.2s。结合上面一次转换的时间,12.6<21<25.2<28,结果是符合推论的。
史海拾趣
|
急需!!! 电子技术研发设计开发方案!!! 急需!!! 方案!!! 公司拓展,急需方案,请拥有方案或部分技术的公司和个人迅速与我联系, 邮箱 rdeasy@yahoo.cn 请注明公司全名或个人的姓,详细准确的联系方式和方案,否则不予考。 ...… 查看全部问答> |
|
我做一个232的通讯,希望传一个16进制数比如0XFE到PC,然后PC端通过DELPHI写的程序能读出这个16进制数.哪位有这个例子,PC端怎么读(是通过自己写程序,还是有现成的调试工具)我到现在还不知道呢,哪位讲下啊… 查看全部问答> |
|
控制一组红绿黄灯,通过反复检测开关S1、S2,要求由S1、S2 的“闭合”和“断开”控制红、 绿、黄3灯的点亮。 当S1断,S2断时,黄灯亮; 当S1断,S2合时,绿灯亮; 当S1合,S2断时,红灯闪亮,闪烁周期为2s; 当S1合,S2合时,红灯亮。 要求:1 ...… 查看全部问答> |
|
就我个人经历,大家在无线选型上常会有的一些误区: 1,通信速率,比如很多公司是这样宣传的NRF2401速率是1MBPS, 但,实际上这只是发射速率,而实际真正完成一次发送速率需要涉及到具体的功能,因为功能越复杂,完成一次数据采集的 ...… 查看全部问答> |
|
所有板子的大集合,现在共有40多块,全部手工焊接哦。。 相关教程将会陆续发布 [ 本帖最后由 youki12345 于 2011-12-7 21:57 编辑 ]… 查看全部问答> |




