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.

MSP430FR5969 ADC模块异常 重启不恢复

现在用定时器控制ADC以32K的频率采样,采用的是序列通道单次采样模式,可是有时候ADC模块出现异常,即当busy标志位为1时,当定时器再次开启ADC模块启动采样时,ADC不再产生中断,并且看门狗发挥作用,单片机整体重启后,ADC模块依然异常,只有当按单片机的复位按键后,busy标志位才清零,单片机才能恢复正常。

void ADC_Cfg(void)
{
P1SEL1 |= BIT2|BIT3|BIT4; // A2 A3 A4
P1SEL0 |= BIT3|BIT4;
P2SEL1 |= BIT3|BIT4; // A6 A7
P2SEL0 |= BIT3|BIT4;
P3SEL1 |= BIT3; // A15
P3SEL0 |= BIT3;

PM5CTL0 &= ~LOCKLPM5;
ADC12CTL0 &=~ ADC12ENC; //初始化在ENC = 0下修改

/*************************************************************************/

ADC12CTL0 = ADC12SHT0_0 | ADC12ON|ADC12MSC; // ADC
ADC12CTL1 = ADC12SHP|ADC12CONSEQ_1|ADC12SSEL_2; // 序列通道单次采集
ADC12CTL2 = ADC12RES_2; //12位的转换精度
ADC12MCTL0 |= ADC12INCH_2 | ADC12VRSEL_4; // 
ADC12MCTL1 |= ADC12INCH_3 | ADC12VRSEL_4; // 
ADC12MCTL2 |= ADC12INCH_4 | ADC12VRSEL_4; // 

ADC12MCTL3 |= ADC12INCH_6 | ADC12VRSEL_4; // 
ADC12MCTL4 |= ADC12INCH_7 | ADC12VRSEL_4; // 
ADC12MCTL5 |= ADC12INCH_15 | ADC12VRSEL_4|ADC12EOS; /
ADC12IER0 = ADC12IE5; // Enable ADC conv complete interrupt
ADC12CTL0 &=~ ADC12ON;
ADC12CTL0 |= ADC12ENC;

}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) TIMER0_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
uchar busy_i=0;
while(ADC12CTL1&ADC12BUSY) //启动ADC
{ busy_i++; if(busy_i>>3) break; }
ADC12CTL0 &=~ (ADC12ENC);
ADC12CTL0 |= ADC12ON|ADC12SC|ADC12ENC;
}

  • 建议先参考下官网的例程。

    你的思路有点和常用的不一样

    一般是先开始转换,然后判断是否转换完毕,再之后是获得采样数值

     ADC12CTL0 |= ADC12SC;               // 开始转换
    
       while ((ADC12IFG & ADC12BUSY)==0);
    
       value=ADC12MEM0;

  • 我使用的是ADC中断,即当ADC转换完成后,触发ADC中断,在中断里读取数据。

    为了降低功耗,我采样一次完成后,把ADC模块关闭,使用时再在定时器里打开

    *******************************************************************************/
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = ADC12_VECTOR
    __interrupt void ADC12_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(ADC12_VECTOR))) ADC12_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
    //switch(__even_in_range(ADC12IV, ADC12IV_ADC12RDYIFG))
    // {
    // case ADC12IV_ADC12HIIFG: //
    // {
    // ADC12IFGR2 &= ~ADC12HIIFG; // Clear interrupt flag
    // // Exit_ULPM();
    // break;
    // }
    // case ADC12IV_ADC12IFG5: //ADC采样中断
    {

    P2OUT ^= BIT5; //测试,检测程序是否正常运行
    ADC12CTL0 &=~ ADC12ENC;
    ADC12CTL0 &=~ ADC12ON;
    ADC12CTL0 |= ADC12ENC; //关闭ADC

    Twire_AD = ADC12MEM2;
    Vin_AD = ADC12MEM0;
    Vcap_AD = ADC12MEM3;
    Vbat_AD = ADC12MEM5;
    。。。。
  • 我还想知道的是,为什么内部看门狗将单片机复位后还不能恢复正常呢?怎样才能用软件控制使其恢复正常?
  • 你的定时器的定时时间是多长?
    建议只在定时器中断服务程序使能adc转换,然后使用adc的中断服务程序完成采样数据的转移
  • void Timer_Cfg(void)
    {
    TA0CTL = TASSEL__ACLK | MC__UP; //
    TA0CCTL0 = CCIE; // TACCR0 interrupt enabled
    TA0CCR0 = 7;
    }

    定时器使用的是ACLK,外部32K的低频晶振,正常采样周期250us,运行期间会根据采样数据转换为1.25ms,采样周期的转换不小于5s

  • 看门狗不能将ADC复位很奇怪,软件清空ADC寄存器后再写入应该就能恢复正常