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.

为什么我的MSP430F5438A ADC12 采样出来的结果老是0XFFF?

Other Parts Discussed in Thread: MSP430F5438A

各位好:

我现在在用430的5438A做一款控制器,使用的板子为自己设计的电路板,编译器采用IAR5.30在XP的操作系统上面,

板子XT1的晶振为16M,目前在调试中发现的问题是:

我在使用ADC12时候觉得是不是自己的ADC设置有问题,使用中断方法读出ADC采样结果老是0XFFF,所以想请大家帮忙解答,谢谢。

现在把ADC设置程序贴出来:

void ADC_Convern(void)
{
  
  uchar i=0;
  P6SEL |= BIT4+BIT5;      //Enable A/D channel A4  A5
  ADC12CTL0 |=       ADC12ON+ADC12SHT02+ADC12REFON+ADC12REF2_5V+ADC12MSC;
                                           
  ADC12CTL1 |= ADC12SHP+ADC12CONSEQ_3;                     
  //ADC12CTL1 |= ADC12CSTARTADD2;//通道4采样的值存入到ADC12MEM4里面
  ADC12CTL2 |= ADC12RES_2;                               //12-bit conversion results
  ADC12MCTL4 |= ADC12SREF_1+ADC12INCH_4;                 // Vr+=Vref+ and Vr-=AVss
  ADC12MCTL5 |= ADC12SREF_1+ADC12INCH_5+ADC12EOS;;                 // Vr+=Vref+ and Vr-=AVss
  
  ADC12IE = 0xFF;                           // Enable interrupt
  for ( i=0; i<0x30; i++);                  // Delay for reference start-up

  ADC12CTL0 |= ADC12ENC;                    // Enable conversions
  ADC12CTL0 |= ADC12SC;                     // Start sampling/conversion

  
  
}
  • yezi,

      你对ADC12IE的寄存器配置为什么会设置成0xff呢,是不是可以改成0x20,也就是使能ADC12IFG.5.

    因为你这里选择的是序列转换的模式,所以一半都是使能最后的那个channel的中断,然后在中断响应程序中去读取ADC12MEM4和ADC12MEM5的值。

    谢谢

  • 我改了,但是ADC采集的结果如图

  • yezi,

      你ADC选择的内部电压参考源是吧,2.5V 还是1.5V呢?另外你测量的两个AD管脚的电压大概有多少呢?如果采样结果一直是0XFFF的话,应该是待测的电压大于你的测试量程了。

    谢谢

  • ken wang

    我选的是内部参考2.5V,我现在给A4管脚上加的电压大概是1.6V,A5没有加输入信号。

    我觉得是不是我ADC初始化没有设置好,因为我用单通道测试时候结果也是0XFFF,所以想知道我的设置哪块有问题。还有就是我如果使用多通道多次采样使用A4,A5,之前的A0 A1 A2 A3都没有用,怎么看寄存器值时这些寄存器却有值且不是0XFFF,而我要使用的A4 A5却是0XFFF?

    谢谢

  • yezi,

      我用你的代码在我们的MSP430F5438A上面测试了一下,channel4和5上面都能得到相应的数值,不是0xfff啊。

    你能把你的中断程序贴出来我看看吗?

    另外关于A0, A1,A2,A3有数值的问题,应该是和你的设置有关,你可以按下面的设置

    ADC12MCTL0 |= ADC12SREF_1+ADC12INCH_4; // Vr+=Vref+ and Vr-=AVss
    ADC12MCTL1 |= ADC12SREF_1+ADC12INCH_5+ADC12EOS;; // Vr+=Vref+ and Vr-=AVss

    把channel4,5的值保存在ADC12MEM0和ADC12MEM1里面就行了。

    谢谢

  • ken wang

        我的中断程序我没有完善,我是在程序进入ADC中断时读中断ADC12IV源是哪个,然后读取寄存器ADC12MEM4的值,(因为A5没有外接信号所以就不用读了)。程序如下,是不是跟我的中断程序还有关系,能否看看您用我的初始化程序写的代码。

    #pragma vector = ADC12_VECTOR
    __interrupt void ADC12_ISR(void)
    {

    static unsigned char index = 0;
    uchar i=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: break; // Vector 12: ADC12IFG3
    case 14: break; // Vector 14: ADC12IFG4
    case 16: //break; // Vector 16: ADC12IFG5
    data[index]=ADC12MEM4;
    index=index+1;
    if(index==5)
    {
    ADC12IE &= ~BIT4;
    ADC12IE &= ~BIT5;
    ADC12CTL0&=~BIT1;//guan ENC
    for(i=0;i<5;i++)
    {
    Current+=data[i];

    }
    Current=Current/5;

    }
    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;
    }
    }

  • yezi,

       你的程序看上去应该没什么大的问题,只是case语句后面没加break;

    这样还是得不到相应的数据吗?那你能不能尝试使用外部的电压参考源试试呢?

    谢谢

     

  • ken  wang

           那我能不能看看你的完整ADC程序,因为我用的TI例程还有我自己写的程序得到的都是0XFFF,所以想再试试。

    谢谢

  • yezi,

     没问题,你可以参考一下。另外建议你还是试试外部的参考电压。你可以简单的把ADC的VCC和VSS分别和你芯片的电地相连。然后再去测试一下你的ADC管脚的电压。

       

    #include <msp430.h>
    
    volatile unsigned int results[2];           // Needs to be global in this example
                                                // Otherwise, the compiler removes it
                                                // because it is not used for anything.
    
    int main(void)
    {
      WDTCTL = WDTPW+WDTHOLD;                   // Stop watchdog timer
      unsigned char i=0;
      P6SEL |= BIT4+BIT5;      //Enable A/D channel A4  A5
      ADC12CTL0 |=       ADC12ON+ADC12SHT02+ADC12REFON+ADC12REF2_5V+ADC12MSC;
    
      ADC12CTL1 |= ADC12SHP+ADC12CONSEQ_3;
      //ADC12CTL1 |= ADC12CSTARTADD2;//通道4采样的值存入到ADC12MEM4里面
      ADC12CTL2 |= ADC12RES_2;                               //12-bit conversion results
      ADC12MCTL0 |= ADC12SREF_1+ADC12INCH_4;                 // Vr+=Vref+ and Vr-=AVss
      ADC12MCTL1 |= ADC12SREF_1+ADC12INCH_5+ADC12EOS;;                 // Vr+=Vref+ and Vr-=AVss
      
      ADC12IE = 0x02;                           // Enable interrupt
      for ( i=0; i<0x30; i++);                  // Delay for reference start-up
    
      ADC12CTL0 |= ADC12ENC;                    // Enable conversions
      ADC12CTL0 |= ADC12SC;                     // Start sampling/conversion
     // while(1)
     // {
    //    ADC12CTL0 |= ADC12SC;                   // Start convn - software trigger
        
        __bis_SR_register(LPM4_bits + GIE);     // Enter LPM4, Enable interrupts
        __no_operation();                       // For debugger    
    //  }
    }
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=ADC12_VECTOR
    __interrupt void ADC12ISR (void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(ADC12_VECTOR))) ADC12ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      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:
    	  results[0] = ADC12MEM4;                 // Move results, IFG is cleared
    	  results[1] = ADC12MEM5;                 // Move results, IFG is cleared
    	//    results[2] = ADC12MEM2;                 // Move results, IFG is cleared
    	//    results[3] = ADC12MEM3;                 // Move results, IFG is cleared
    	  __bic_SR_register_on_exit(LPM4_bits);   // Exit active CPU, SET BREAKPOINT HEREbreak;                           // Vector  8:  ADC12IFG1
      case 10: break;                           // Vector 10:  ADC12IFG2
      case 12:                                  // Vector 12:  ADC12IFG3
      case 14: break;                           // Vector 14:  ADC12IFG4
      case 16:                          // Vector 16:  ADC12IFG5
    
      break;
      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; 
      }
    }

    谢谢

  • ken  wang

    你的程序我试了,程序没有进ADC中断,我就单独把你的中断函数和ADC初始化放到我自己的程序中替换,还是0XFFF。我想问下测内部参考电压是不是直接测P5.0与P5.1之间的电压,我测了下为0.

    我再试试外部参考。

    谢谢

  • ken  wang

    我用外部参考电压试可以。但是就是采用单通道单次采样和单通道多次采样模式下,采样回来的值误差很大,差0.3V左右,但是我用序列通道多次转换模式时采样回来的值很准确,就是没有外接信号的通道也出现了值。

     

    谢谢

  • 中断没进去,我的也是这样。

    程序里面的BIT用法改成十六进制赋值就可以解决,比如bit0改成0x01;就可以。

    祝顺利

  • 内部REF没有打开,你把这句加上去就好了:

    REFCTL0 |= REFMSTR+REFVSEL_2; //使能REF管理,内部参考电压选择2.5v、打开内部参考电压
    REFCTL0 |= REFON;