我有一些代码应该读取几个ADC引脚的值,每次都在换向器环路周围。
static uint16_t adc0;
static uint16_t adc1;
void init(void) {
...
hw_configure_adcs();
...
}
void loop(void) {
...
adc0 = hw_read_adc(0);
adc1 = hw_read_adc(1);
...
}
void hw_configure_adcs(void) {
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0);
}
uint16_t hw_read_adc(uint8_t n) {
ADMUX = (1<<REFS0) | (n & 0x07);
ADCSRA |= (1<<ADSC); // start conversion
uint16_t count;
for (count = 0; !(ADCSRA & (1<<ADIF)); count++); // wait for conversion to complete
// ADCSRA |= (1<<ADIF); // tried with and without this
return (ADCH << 8) | ADCL; // return ADC value
}
我看到的是奇怪的:adc0和adc1的值设置为相同的值,并且永远不会改变,直到AVR芯片重新启动/重新显示。
(该值在0.71V时为0x00d1,在1.00V时为0x0128,这似乎是合理的。)
我试过了:
count
返回hw_read_adc()
而不是ADC值:这会返回0x34和0x38之间的变化数字,这两个数字不同,并且会随着时间的推移而不断变化。 从这些测试中,我推断出ADC正在被读取,但是我错过了一些&#34;清除ADCH和ADCL并让它们准备接受新的读数&#34;步骤
我多次重读http://www.atmel.com/images/Atmel-8272-8-bit-AVR-microcontroller-ATmega164A_PA-324A_PA-644A_PA-1284_P_datasheet.pdf第23节,但显然忽略了一些重要的事情。
答案 0 :(得分:1)
经过大量的谷歌搜索后,我发现:code
问题在于return (ADCH << 8) | ADCL;
已编译,因此它首先读取高位寄存器(如您所料)。
数据表的第252页说:“否则,必须先读取ADCL,然后再读取ADCH”。
将我的代码更改为return ADC
解决了问题。
我对发生的事情的猜测是:
答案 1 :(得分:1)
代码的问题是您首先阅读ADCH。
必须先阅读ADCL ,然后阅读ADCH,以确保数据寄存器的内容属于同一转换。读取ADCL后,ADC对数据寄存器的访问将被阻止。这意味着,如果已读取ADCL,并且在读取ADCH之前完成转换,则不会更新任何寄存器,并且转换结果将丢失。读取ADCH时,将重新启用对ADCH和ADCL寄存器的ADC访问。
因此正确的代码应为-
return ADCL | (ADCH << 8) ;