STC8单片机ADC采样注意事项
最近在做一个模块,使用宏晶公司的STC8单片机开发,模块主要使用了单片机的ADC采样功能,因为需要10个以上的通道,而且模块要经常震动,所以希望使用一种耐操一点的芯片, 于是我使用了STC8系列的单片机,有16路通道的ADC,采样精度是12位,可以比较好的满足我的要求。 一开始模块做的还不错,半年之后有一次要进行改进,在程序上我加大了单片机通道切换之间的时间,然而最后却出现了采样出错的现象。
因为我要轮询所有的ADC通道,出于设计方面,我采用了特别的采样顺序,采样出错的结果不知道是怎么回事,在改了程序之后便出现了问题, 我一直认为是程序的问题,搞到最后怀疑人生了,,感觉难道这又是STC的一个bug?
不过,最后我终于在网上找到了一个线索,并且尝试按照那个方法改了一下程序,ojbk了。 贴一下那个线索的原话:
如果输入信号内阻很大(超过1K就算大了,如果10K就很大了),ADC输入端对地接一个0.01~0.1uF的电容。
切换通道后,第一次转换值丢弃。为什么会有这些要求?为什么外挂专门的ADC也一样的有这种要求?
对于没有输入缓冲的ADC(STC的ADC输入就是没有缓冲的),采样时ADC输入端通过一个电阻(r,通常是几K欧姆)给采样电容C充电(采样电容一般是10~30PF,STC的可以按30PF计算),假设信号源内阻为R0,则采样充电就是((R0+r)*C),采样时间t一般是很短的,比如STC最快时采样就是几个时钟,时间很短。
贴一下我的ADC采集函数(更改之前的):
/**
* [ADCRead description]
* @Author 叶鹏程
* @DateTime 2019-08-01T20:24:46+0800
* @discrption : ADC采样函数,
*
* @param n [要采样的通道]
* @param value_point [采样值存放地址]
*/
void ADCRead(uint8_t n,unsigned int xdata *value_point){
unsigned int adc_value = 0;
ADC_SET_CHANEL(n); //设置当前待转换的ADC通道
ADC_START_ENABLE();
while(ADC_STATE()); //等待转换
ADC_FLAG_CLEAR();
adc_value = (int)ADC_RES << 8; //读取ADC结果
adc_value |= (int)ADC_RESL;
adc_value = adc_value>>4;
*value_point = adc_value;
}
这是按照线索,更改之后的:
/**
* [ADCRead description]
* @Author 叶鹏程
* @DateTime 2019-08-01T20:24:46+0800
* @discrption : ADC采样函数,
*
* @param n [要采样的通道]
* @param value_point [采样值存放地址]
*/
void ADCRead(uint8_t n,unsigned int xdata *value_point){
unsigned int adc_value = 0;
ADC_SET_CHANEL(n); //设置当前待转换的ADC通道
ADC_START_ENABLE();
while(ADC_STATE()); //等待转换
ADC_FLAG_CLEAR();
/* 这是清除了第一次转换的值,采用第二次采样,这样在切换通道时更加稳定*/
ADC_START_ENABLE();
while(ADC_STATE()); //等待转换
ADC_FLAG_CLEAR();
adc_value = (int)ADC_RES << 8; //读取ADC结果
adc_value |= (int)ADC_RESL;
adc_value = adc_value>>4;
*value_point = adc_value;
}
总结,这是ADC电路的问题, 以后一定要注意这些东西, 看来还是自己的知识没有学扎实。 加油!