最近在搞ADC,把5438的ADC这章看了一遍,然后用例程去仿真了一下,发现一个问题,就是用内部参考电压的时候在寄存器CTL0设置了2.5V,REFON也置1了,然后MCTL1里的SREF为1,这都是按例程里来设置的,结果在A0输入的时候,得到的仿真结果是0X0FFF,也就是4095,这说明我的输入是超过或者是等于参考电压,但我实际测的A0的输入电压为1.1V左右,跟2.5V都差很多啊,为什么是满的值。
我把参考电压选择SREF改为0,也就是参考电压为AVCC跟AVSS,这样转换的值就正确了,3.3V的参考转换后在1453左右,误差不大,就是内部参考2.5V或者1.5V都不行,始终转换为满值4095,不知道问题出在哪
程序我贴下:
#include <msp430.h>
volatile long temp;
void AD_Init(void)
{
int i;
P6SEL |= 0x01; // Enable A/D channel A0
ADC12CTL0 = ADC12ON+ADC12SHT0_4+ADC12REFON+ADC12REF2_5V; // Turn on ADC12, set sampling time,选用内部参考2.5V
ADC12CTL1 = ADC12SHP; // Use sampling timer, set mode
ADC12MCTL0 = ADC12SREF_1+ADC12INCH_0; // Vr+=Vref+ and Vr-=AVss
for ( i=0; i<0x30; i++); // Delay for reference start-up
ADC12CTL0 |= ADC12ENC; // Enable conversions
}
void AD_Start(void)
{
ADC12CTL0 |= ADC12SC; // Start conversion
}
int main(void)
{
WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer
AD_Init(); //AD初始化
while(1)
{
AD_Start(); //开始AD转换
while (!(ADC12IFG & BIT0)); //判断转换完成与否
temp = ADC12MEM0; //读取转换数据,IFG自动清零
__no_operation(); // For debugger
}
}
在修改ADCMCTL0中的ADC12SREF_1这个参数,当为0时,转换数据正常,当为1时,得到的结果就是4095,而不管CTL0中的REF_2.5V置1与否。
Ken Wang:
Better,
由于你使用的MSP430F5438A, 它里面有专门用于定义ADC reference voltage的REF模块。
关于参考电压的设置,你可以通过ADC12_A, 也可以通过REFCTL0. 在MSP430F5438A默认的情况下REF模块是使能的,所以你需要通过REF模块来配置参考电压。相关设置可以参考类似下面的语句:
·········· REFCTL0 |= REFMSTR+REFVSEL_2+REFON+REFTCOFF;
当然你也可以通过设置ADC12_A来设置,但前提是REF模块必须是disable 状态下的。
在我们的数据手册SLAU208M的28.2.3里面关于这个有很详细的介绍,你可以看看。
Ken
BETTER ZHU:
回复 Ken Wang:
参考电压的问题是解决了,但是不知道问什么每次测量外部电池电压时,在电池在位时测出的电压与实际相符,但把电池拿掉时,AD转化的值只是小了一些,过了一段时间又变小了一些,但不会变为0?这是为什么
f g:
回复 Ken Wang:
我也遇到上述类似的问题。在基准电源选择为AVCC之外的电压都不行。我打算,选择REF电压,采集通道 为(AVCC-AVSS)/2这个。不知道电路连接有什么要求的?我的解法:AVSS接电池正极(1.5到3V可调)。VREF+接10UF;100nf的电容并悬空。程序上也加上 REFCTL0 |= REFMSTR+REFVSEL_2+REFON+REFTCOFF;这样就应该设置为内部2.5V啊.怎么用AD采集AVSS的电压都是4095.后来在VREF+接3V的电压后可以采集到电压值,但是不是正确的结果。不知道哪里出了问题。对了。我主频晶振用的20M不知道有啥影响不。
程序如下:
void ADC_init(void)//{ int i; P6SEL |= 0x01; //P60,单通道; REFCTL0 |= REFMSTR+REFTCOFF+REFVSEL_2+REFON+REFOUT;////开启REF模块+选2.5V+选择内部参考电压+关闭温度传感器
ADC12CTL0&= ~ADC12ENC;//ENC=0;
ADC12CTL0 = ADC12ON+ADC12SHT0_4+ADC12MSC+ADC12REFON+ADC12REF2_5V;//;+ADC12SHT1_8 $$$ //开ADC12+采样保持时间+自动采样 //ADC12REFON+ADC12REF2_5V:基准开启,用2.5V ADC12CTL1 = ADC12SHP+ADC12CONSEQ_2; //;ADC12采样/保持脉冲模式:选择信号从“采样定时器”+ ADC12转换顺序选择:2 ADC12MCTL0 =ADC12SREF0+ADC12INCH_11;//
for ( i=0; i<0x30; i++); // ADC12IE =ADC12IE0;// 0x01; // //A0转换结束允许中断。 ADC12CTL0 |= ADC12ENC; //ADC12-A;使能转换。 ADC12CTL0 |= ADC12SC; //ADC12-A启动采样
}
#pragma vector=ADC12_VECTOR//ADC GFY __interrupt void ADC12ISR (void){ unsigned int voltage; switch(__even_in_range(ADC12IV,34)) { case 6: // ADC12IFG0 voltage=ADC12MEM0; LCD_PutChar(voltage);//显示转换值 default: break;
} }