ADC仅在ATMEGA324PA上工作一次

时间:2016-11-17 11:09:16

标签: 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
}

我看到的是奇怪的:adc0和adc1的值设置为相同的值,并且永远不会改变,直到AVR芯片重新启动/重新显示。

(该值在0.71V时为0x00d1,在1.00V时为0x0128,这似乎是合理的。)

我试过了:

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

2 个答案:

答案 0 :(得分:1)

经过大量的谷歌搜索后,我发现:code

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

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

将我的代码更改为return ADC解决了问题。

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

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

答案 1 :(得分:1)

代码的问题是您首先阅读ADCH。

必须先阅读ADCL ,然后阅读ADCH,以确保数据寄存器的内容属于同一转换。读取ADCL后,ADC对数据寄存器的访问将被阻止。这意味着,如果已读取ADCL,并且在读取ADCH之前完成转换,则不会更新任何寄存器,并且转换结果将丢失。读取ADCH时,将重新启用对ADCH和ADCL寄存器的ADC访问。

因此正确的代码应为-

return ADCL | (ADCH << 8) ;