MSP430 ADC12 最高采样率测试

您所在的位置:网站首页 ad7705采样频率 MSP430 ADC12 最高采样率测试

MSP430 ADC12 最高采样率测试

2024-06-15 04:43| 来源: 网络整理| 查看: 265

使用的MSP430型号为MSP430F5529LP(Lauchpad)

MSP430x5xx and MSP430x6xx Family User's Guide 给出:其内置12位ADC的 最高采样率约为200ksps

下面详述ADC设置过程。

目录

1.设置ADC转换模式为Repeat-single-channel;

2.设置ADC的转换时钟sample-and-hold source (SHI)

3.设置定时器A为输出模式

4.设置输入通道

5.设置ADC12SHP位

6.设置采样保持时间

1.设置ADC转换模式为Repeat-single-channel;

  

请通过设置ADC12CONSEQx位来设置转换模式。

2.设置ADC的转换时钟sample-and-hold source (SHI)

选择为定时器A的输出;

对于ADC12SHSx位, 默认值为0h,也就是ADC12SC位控制一次转换或多次转换的开始。在这一点上,官网上给出的大部分例程都保持默认设置。比如:

https://dev.ti.com/tirex/explore/node?devices=MSP430F5529&node=ALGZRALuAjj-L1sgzhrl-Q__IOGqZri__LATEST

本例程中需要选择定时器输出控制转换的开始, MSP430x5xx and MSP430x6xx Family User's Guide 中告诉我们需要查找device-specific data sheet

在这一点上,MSP430G2553 的ADC10的寄存器说明中则直接给出了对应的定时器:

下图摘自 MSP430x2xx Family  User's Guide

 对于F5529的ADC12,我们在 MSP430F552x, MSP430F551x Mixed-Signal Microcontrollers 中可以找到答案: 

这样,设置ADC12SHS位为ADC12SHS_1,就可以通过TA0.1输出一个PWM波控制ADC转换。

注意,由于使用了TimerA控制转换,我们就不再需要控制ADC12SC位来开启转换。

也就是说官网示例中的以下语句我们不需要。

ADC12CTL0 |= ADC12SC; // Start sampling/conversion

同理,官网的给出的单通道重复转换的另一个示例中:

https://dev.ti.com/tirex/explore/node?devices=MSP430F5529&node=AF4y3ALvJIfHLG8i78B81g__IOGqZri__LATEST

 ADC12MSC位的设置我们也不再需要,因为我们是通过定时器输出的PWM波来控制转换的,ADC12MSC位被设置为1时,得到一个数据后,下一个数据将会被立即转换,并不受PWM波的控制。(见下)

3.设置定时器A为输出模式

TA0.1输出应为周期为200kHz的PWM波。

 这里选择Output Mode 3,输出PWM波的周期只受TAxCCR0控制。

如果你的MSP430 SMCLK为8MHz,且SMCLK被选为定时器的时钟源,那么TAxCCR0应该为:

\mathrm{TAxCCR0}=\frac{8MHz}{200kHz}=40

TAxCCR1的值将只影响占空比。

选择其他的输出模式请根据实际进行设置。

4.设置输入通道

上图来自:

MSP430F5529 LaunchPad™ Development Kit  (MSP‑EXP430F5529LP)  slau533d.pdf

上图仍然来自: MSP430F552x, MSP430F551x Mixed-Signal Microcontrollers

这里选择P6.0作为ADC输入引脚。

5.设置ADC12SHP位

该位控制采样的模式。

Extended Sample Mode:

Pulse Sample Mode: 

这里的理解为:SHI(已经被我们设置为定时器的输入)控制采样和转换时序。

对于 Extended Sample Mode,采样时长将与其高电平时间保持一致,这样在某些情况下可能导致转换出错。

比如,每次采样间隔完全足够完成一次转换,但由于低电平时间过短(比如占空比为99%),t_convert短于13个ADC12CLK,转换就会出错。

对于Pulse Sample Mode,SHI的上升沿触发采样开始,但采样时长由ADC12SHT位控制(见下一部分)

6.设置采样保持时间

由于需要达到最高转换速率,这里的设置需要异常谨慎。

下面稍作分析。

上图仍然来自:MSP430F552x, MSP430F551x Mixed-Signal Microcontrollers

 上图来自:MSP430x5xx and MSP430x6xx Family User's Guide

ADC12 clock source默认值为0,即ADC12OSC,其频率范围为:4.2~5.4MHz。

这里估算时按5MHz算,则其周期为:1/5M=200ns=0.2us

而我们需要达到的转换速率为200kHz,即每5us开始一次新的采样转换。

假如我们设置ADC12SHT0x位为0010b,也就是采样时间为16个ADC12CLK,则至少需要16*0.2=3.2us进行采样。

同时在当前配置下,t_convert的最小值为2.4us,那么:

\large t_{sample}+t_{convert}\geq 5.6\mu s5\mu s

无法完成任务。这里测试的情况是采样点数不够。

所以只能设置ADC12SHT0x为0001b或0000b,其他值统统不行。

另一种解决方案,通过设置ADC12SSELx位将时钟源换为SMCLK,并将主频调成25MHz(需要进行升压操作,详见PMM模块说明,这里不多说,进而实现要求.

当然当你主频过高时,不要忘记采样时间也有要求,需要大于1000ns,否则也可能出问题。

下面贴完整代码:

#include /** * main.c */ unsigned int i=0; volatile unsigned int buf[200]; int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT Clock_init(); Timer_Init(); ADC12_Init(); } #pragma vector = ADC12_VECTOR __interrupt void ADC12_ISR(void) { switch(__even_in_range(ADC12IV,34)) { case 0: break; // Vector 0: No interrupt case 2: break; // Vector 2: ADC overflow case 4: break; // Vector 4: ADC timing overflow case 6: // Vector 6: ADC12IFG0 buf[i]=ADC12MEM0;//*3.3/4096.0; 变成浮点数将会来不及采样 i++; if(i>200) i=0; break; case 8: break; // Vector 8: ADC12IFG1 case 10: break; // Vector 10: ADC12IFG2 case 12: break; // Vector 12: ADC12IFG3 case 14: break; // Vector 14: ADC12IFG4 case 16: break; // Vector 16: ADC12IFG5 case 18: break; // Vector 18: ADC12IFG6 case 20: break; // Vector 20: ADC12IFG7 case 22: break; // Vector 22: ADC12IFG8 case 24: break; // Vector 24: ADC12IFG9 case 26: break; // Vector 26: ADC12IFG10 case 28: break; // Vector 28: ADC12IFG11 case 30: break; // Vector 30: ADC12IFG12 case 32: break; // Vector 32: ADC12IFG13 case 34: break; // Vector 34: ADC12IFG14 default: break; } }

系统频率设置为25MHz (需要设置PMM升压)

void upVcc(void)//核心电压上升3级 { PMMCTL0_H = PMMPW_H; //开启PMM电源管理,即开锁 SVSMLCTL |= SVSMLRRL_1 + SVMLE; //配置SVML电压 PMMCTL0 = PMMPW +PMMCOREV_3; //配置内核电压,选择3级 while((PMMIFG & SVSMLDLYIFG)==0); //等待配置完成 PMMIFG &=~ (SVMLVLRIFG + SVMLIFG + SVSMLDLYIFG); if((PMMIFG & SVMLIFG)==1) while((PMMIFG & SVMLVLRIFG)==0); SVSMLCTL &=~ SVMLE; //关闭SVML PMMCTL0_H = 0x00; //锁存配置,即关锁 } void Clock_init() //XT2为时钟源 { upVcc(); P5SEL |= BIT2+BIT3; // Port select XT2 UCSCTL6 &= ~XT2OFF; // Enable XT2 UCSCTL3 |= SELREF_5+FLLREFDIV_2; // FLLref = XT2 4MHz divider:4 // Since LFXT1 is not used, // sourcing FLL with LFXT1 can cause // XT1OFFG flag to set UCSCTL4 |= SELA_2; // ACLK=REFO,SMCLK=DCO,MCLK=DCO UCSCTL2 = FLLD_1 + 24; //N=24 SMCLK=MCLK=DCOclkdiv:(N+1)*FFLrefclk/4=25MHz FFLD=1—>D=2为默认值 -> DCOclk=50MHz UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx UCSCTL1 = DCORSEL_7; // Set RSELx for DCO = 16 MHz // Loop until XT1,XT2 & DCO stabilizes - in this case loop until XT2 settles do { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags SFRIFG1 &= ~OFIFG; // Clear fault flags }while (SFRIFG1&OFIFG); // Test oscillator fault flag UCSCTL6 &= ~XT2DRIVE0; // Decrease XT2 Drive according to // expected frequency 4MHz }

ADC12初始化:

void ADC12_Init() { P6SEL |= BIT0; // Enable A/D channel A0 ADC12CTL0 = ADC12SHT0_1 + ADC12ON; ADC12CTL1= ADC12SHP + ADC12CONSEQ_2 + ADC12SHS_1; //SHS1: TimerA 0_1 output ADC source clk:SMLCK ADC12MCTL0 = ADC12INCH_0; //Channel 0 ADC12IE=0x01; //Enable interrupt ADC12CTL0 |= ADC12ENC; __bis_SR_register(GIE); // Enter LPM0, Enable interrupts }

定时器设置:

void Timer_Init() { P1DIR |= BIT2; //Set p1.2 as TimerA output P1SEL |= BIT2; TA0CTL= TASSEL_2 + MC_1 + TACLR; TA0CCTL1=OUTMOD_3; // CCTL1=CCIE; // Don't need Timer interrupt here TA0CCR0=125; //T=5us TA0CCR1=62; // Set the duty. Can be any value in this project }

结果:

输入10kHz正弦波测试,每周期应该采样得到20个数据点。

 TimerA的PWM波从P1.2输出:

补充DMA操作:

#include #include extern unsigned int buf[200]; void DMA_Init() { // Setup DMA0 DMACTL0 = DMA0TSEL_24; // ADC12IFGx triggered DMACTL4 = DMARMWDIS; // Read-modify-write disable // DMA0CTL &= ~DMAIFG; DMA0CTL = DMADT_4+DMAEN+DMADSTINCR_3+DMASRCINCR_0; // Rpt single tranfer DMA0SZ = 200; // DMA0 size = 200 __data20_write_long((uintptr_t) &DMA0SA,(uintptr_t) &ADC12MEM0); // Source block address DMA将存储ADC数据 __data20_write_long((uintptr_t) &DMA0DA,(uintptr_t) &buf); // Destination single address数据存至buf数组中 __bis_SR_register(LPM0_bits + GIE); __no_operation(); // used for debugging }



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3