求助:ATtiny13A的ADC通道切换问题
需要用两个ADC通道采样不同的电压,使用了16倍过采样来得到12位的数据。现在出的状况是不管先采样哪个通道,开始的通道正确,再采样另一个通道的数据总是错的,值会受到前一个通道的影响。用AVR比较少,对比数据手册和示例代码没找到原因。代码如下求指教:
typedef enum {
ADC_CH_TEMP,
ADC_CH_LIGHT
} ADC_Channel_t;
// Read ADC with oversampling to get 12bits result
static uint16_t ADC_Read(ADC_Channel_t ch)
{
uint8_t i;
uint8_t ADC_tempL;
uint16_t ADC_var;
if (ch == ADC_CH_TEMP) {
// ADC2, VCC as reference
ADMUX = (0 << REFS0) | (1 << MUX1) | (0 << MUX0);
} else {
// ADC3, Internal reference (1.1V)
ADMUX = (1 << REFS0) | (1 << MUX1) | (1 << MUX0);
}
// Enable the ADC, 1.2MHz / 8 = 150kHz (Conversion time: 86uS)
ADCSRA = (1 << ADEN) | (1 << ADPS1) | (1 << ADPS0);
ADCSRB = 0x00;
// do a dummy readout first
ADCSRA |= (1 << ADSC); // do single conversion
while (!(ADCSRA & (1 << ADIF))); // wait for conversion done, ADIF flag active
ADCSRA &= ~(1 << ADIF); // clear ADIF flag
ADC_var = 2;
// do the ADC conversion 16 times for oversampling
for (i = 16; i != 0; i--) {
ADCSRA |= (1 << ADSC); // do single conversion
while (!(ADCSRA & (1 << ADIF))); // wait for conversion done, ADIF flag active
ADCSRA &= ~(1 << ADIF); // clear ADIF flag
ADC_tempL = ADCL; // read out ADCL register
ADC_var += (ADCH << 8) | ADC_tempL; // accumulate result
}
ADC_var >>= 2; // shift right to get extra 2 bits
ADCSRA &= ~(1 << ADEN); // disable the ADC
return ADC_var;
} 本帖最后由 qq729101414 于 2015-3-2 17:04 编辑
呃。。。这个不了解不过以前飞思卡尔的一款单片机对于AD转换 内部电容放电 有一个开关的。
就是下次采样之前 可以选择先让电容放电。{:smile:}
这个是数据手册关于 Free Running mode 的解释
编辑原因:补充回复。 30. ADC_var = 2; 初值为什么不是0 ?
28. 35. ADIF 不是写0清零,应该是写1清零,看手册。
ADC初始化放在别处,做一次就可以吧,没必要频繁开启、关闭。 zhanan 发表于 2015-3-2 17:11
30. ADC_var = 2; 初值为什么不是0 ?
28. 35. ADIF 不是写0清零,应该是写1清零,看手册。
问题解决了,非常感谢!是清标志位的地方疏忽了,改为写1解决问题。
另外2是用来“四舍五入”,因为后面除以了4。程序只是偶尔用到ADC,考虑到功耗用完就关了。
页:
[1]