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

我试过了:
  • 调低电压:adc0和adc1保持恒定,仅在刷新AVR代码(并因此重启芯片)时才下降。
  • 将电压调高:adc0和adc1保持恒定,仅在刷新AVR代码(并因此重新启动芯片)后才升高。
  • 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可以解决此问题。

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

  • 发生了从ADCH的读取。
  • 从ADCL读取的数据具有锁定ADC结果以防止撕裂的作用。
  • 下一次ADC读取无处可写其结果,因为ADC结果已锁定。
  • 重复...
  • 关于c - ADC在ATMEGA324PA上仅工作一次,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40653325/

    10-11 23:08