我有一些代码应该每次在换向器环路周围读取几个 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
}
Run Code Online (Sandbox Code Playgroud)
我看到的很奇怪:adc0 和 adc1 的值被设置为相同的值并且永远不会改变,直到 AVR 芯片重新启动/重新刷新。
(该值在 0.71V 时为 0x00d1,在 1.00V 时为 0x0128,这似乎是合理的。)
我试过了:
count从hw_read_adc()代替ADC值:该返回变化0x34和0x38之间的数字,其是用于两个ADC不同并随时间连续变化。 从这些测试中,我推断正在读取 ADC,但我缺少一些“清除 ADCH 和 ADCL 并让它们准备好接受新读数”的步骤。
我已经多次重读了http://www.atmel.com/images/Atmel-8272-8-bit-AVR-microcontroller-ATmega164A_PA-324A_PA-644A_PA-1284_P_datasheet.pdf 的第 23 节,但显然忽略了一些重要的东西.
经过多次谷歌搜索,我发现:http : //www.avrfreaks.net/forum/adc-only-happens-once-reset
问题在于它return (ADCH << 8) | ADCL;被编译为首先读取高位寄存器(如您所料)。
数据表的第 252 页说:“否则,必须先读取 ADCL,然后再读取 ADCH”。
更改我的代码以return ADC解决问题。
我对发生的事情的猜测是: