This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
参照各种官方示例程序之后编写了一段ADC12的转换程序。程序实现的功能是:通过I/O端口P6.6获取输入模拟信号,通过TA0获取取样频率10µs/sample,并触发ADC转换。时钟源取SMCLK,用DCO配置0.7MHz,采用Up-Mode和Repeat single-channel conversion,中断时将ADC12MEM0的值存入ADC_Results[index]。
为了验证程序是否正确运行,用了示例程序里的HAL_Dogs102x6.h(为了显示在LCD屏上)和HAL_Board.h(为了点亮或熄灭LED灯),但没法运行。所以问题就是:
1. ADC12这部分是不是能实现10µs/sample的功能
2.如何验证此程序按预期正确运行了
主程序附件添加了
麻烦各位了,我找不出程序的错又没有办法验证它是否正确运行
#include <msp430.h> #include "./Include/HAL_Dogs102x6.h" #include "./Include/HAL_Board.h" #define Num_Results 8 int ADC_Results[Num_Results]; /* * main.c */ int main(void) { volatile unsigned int i; WDTCTL = WDTPW + WDTHOLD; P1DIR |= BIT0; P1SEL |= BIT0; // Timer_A P2SEL |= BIT2; P2DIR |= BIT2; // Test SMCLK P6SEL |= BIT6; P6DIR &= ~BIT6; P5SEL |= BIT4 + BIT5; // Port select XT1 REFCTL0 &= ~REFMSTR; UCSCTL6 &= ~(XT1OFF); // XT1 On UCSCTL6 |= XCAP_3; // Internal load cap // Loop until XT1 fault flag is cleared do { UCSCTL7 &= ~XT1LFOFFG; // Clear XT1 fault flags }while (UCSCTL7&XT1LFOFFG); // Test XT1 fault flag // Initialize DCO to 0.7MHz __bis_SR_register(SCG0); // Disable the FLL control loop UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx UCSCTL1 = DCORSEL_1; UCSCTL2 = FLLD_1 + 21; // Set DCO Multiplier for 0.7MHz // (N + 1) * FLLRef = Fdco // (21 + 1) * 32768 = 0.7MHz // Set FLL Div = fDCOCLK/2 UCSCTL3 = SELREF_2 + FLLREFDIV_0; UCSCTL4 = SELA_0 + SELS_3 + SELM_3; UCSCTL5 = DIVPA_0 + DIVA_0 + DIVS_0 + DIVM_0; __bic_SR_register(SCG0); // Enable the FLL control loop // 32 x 32 x 0.7 MHz / 32,768 Hz = 21875 = MCLK cycles for DCO to settle __delay_cycles(21875); do { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags SFRIFG1 &= ~OFIFG; // Clear fault flags }while (SFRIFG1&OFIFG); // Test oscillator fault flag ADC12CTL0 = ADC12ON + ADC12SHT0_15 + ADC12REFON + ADC12REF2_5V; // ADC On, 1024 ADC12CLK Cycles, ADC Voltage Reference On, Voltage Reference 2.5V ADC12CTL1 = ADC12CONSEQ_2 + ADC12CSTARTADD_0 + ADC12SHS_1; // Repeat Single-Channel Conversion, Conversion memory start address ADC12CTL2 = ADC12RES_2; // ADC12 resolution 12 bits ADC12MCTL0 |= ADC12INCH_6 + ADC12SREF_1; // ADC Input select, V(R+) = VREF+ and V(R-) = AVSS while (REFCTL0 & REFGENBUSY) // If Ref generator busy, wait REFCTL0 |= REFVSEL_2 + REFON; // Select internal Ref = 2.5V, Internal Reference On TA0CTL = TASSEL_2 + MC_1 + TACLR; // Choose SMCLK, Up-Mode, Clear TAR TA0CCR0 = 6; // 0.7MHz/100KHz - 1 = 6 TA0CCTL0 = CAP + CCIE + CCIFG; for(i = 0; i < 0x30; i++) ADC12CTL0 |= ADC12ENC; while (1){ ADC12CTL0 |= ADC12SC; while(!(ADC12IFG & BIT0)); __no_operation(); } __bis_SR_register(LPM3_bits + GIE); } #pragma vector=ADC12_VECTOR __interrupt void ADC12ISR (void) { static unsigned int index = 0; 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: break; // Vector 6: ADC12IFG0 case 8: break; // Vector 8: ADC12IFG1 case 10: break; // Vector 10: ADC12IFG2 case 12: // Vector 12: ADC12IFG3 { ADC_Results[index] = ADC12MEM0; Board_ledOn(LED1); // Test by LED1 index ++; if (index == 8) { index = 0; } } 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; } }
1. 在你贴出的代码中我没找到你用于显示的代码。
2. 附件中的代码的原意是用TA0定时器产生一个周期性的定时器,并在定时器中断中触发ADC采样。TA0的周期定位10us,这样就可以实现楼主想要的10us/sample.
3. 附件中的源码没看到TA0中断的处理, 而在源码的MAIN函数中 用这句话来触发的ADC采样。ADC12CTL0 |= ADC12SC;
你不能把例程代码乱凑一起就成为自己的代码。先要理解流程,然后在整理程序结构,最后变成代码。建议你先画流程图,先把CPU处理流程搞清楚,然后在写代码。代码是最简单的事,关键是你要搞清楚程序的流程,这个比编程重要100倍。
请教:我现在的基本思路是:
1.先初始化各种引脚,P6.6用来获取输入信号;
2.为了得到想要的10µs/sample也就是100KHz,先初始化时钟,选择SMCLK= DCO = 0.7MHz;
3.接着是初始化ADC12,设置引脚P6.6来得到信号输入,设置成Repeat single-channel模式,转换值存放地址,时钟源SMCLK,以及参考电压和输入端口INCH;
4.最后初始化Timer_A,选择时钟源SMCLK,计数模式Up-Mode,和TA0周期值。
5.最后的最后,在Timer_A中断函数中,开始ADC12采样和转换。
这个思路可执行不?
1. 这样做的风险在于TIMER中断响应时间+ADC的采样时间有可能会大于10us.MSP430的中断系统不支持优先级别高的中断打断低优先级级别的中断,所以你必须确保TA的中断能及时响应。
2. 你可以直接设置ADC的触发源来之TA0-OUT0或TA0-OUT1,这样可以避免中断造成的延时。
所以我设置了ADC12CTL1 SHSx = 1,也就是TA0.1。然后我逐步运行了程序发现进不了Timer的中断,我给你看看代码,原因出在哪里呀?