ADC 仅在 ATMEGA324PA 上工作一次

fad*_*bee 5 c avr atmega adc

我有一些代码应该每次在换向器环路周围读取几个 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,这似乎是合理的。)

我试过了:

  • 降低电压:adc0 和 adc1 保持不变,只有在 AVR 代码重新刷新(因此芯片重新启动)时才会降低。
  • 调高电压:adc0 和 adc1 保持不变,只有在重新刷新 AVR 代码(因此芯片重新启动)时才会升高。
  • 返回counthw_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 节,但显然忽略了一些重要的东西.

fad*_*bee 5

经过多次谷歌搜索,我发现:http : //www.avrfreaks.net/forum/adc-only-happens-once-reset

问题在于它return (ADCH << 8) | ADCL;被编译为首先读取高位寄存器(如您所料)。

数据表的第 252 页说:“否则,必须先读取 ADCL,然后再读取 ADCH”。

更改我的代码以return ADC解决问题。

我对发生的事情的猜测是:

  • 发生了从 ADCH 的读取。
  • 从 ADCL 读取具有锁定 ADC 结果的效果,以防止撕裂。
  • 下一次 ADC 读取无处可写其结果,因为 ADC 结果被锁定。
  • 重复...