简体   繁体   English

ADC 仅在 ATMEGA324PA 上工作一次

[英]ADC only working once on ATMEGA324PA

I have some code which should read the values of a couple of ADC pins, each time around the commutator loop.我有一些代码应该每次在换向器环路周围读取几个 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
}

What I see is odd: The values of adc0 and adc1 are set to the same value and never change, until the AVR chip is restarted/reflashed.我看到的很奇怪:adc0 和 adc1 的值被设置为相同的值并且永远不会改变,直到 AVR 芯片重新启动/重新刷新。

(The value is 0x00d1 at 0.71V and 0x0128 at 1.00V, which seems reasonable.) (该值在 0.71V 时为 0x00d1,在 1.00V 时为 0x0128,这似乎是合理的。)

I have tried:我试过:

  • Turning the voltage down: adc0 and adc1 stay constant and only go down when the AVR code is reflashed (and hence the chip restarted).降低电压:adc0 和 adc1 保持不变,只有在 AVR 代码重新刷新(因此芯片重新启动)时才会降低。
  • Turning the voltage up: adc0 and adc1 stay constant and only go up when the AVR code is reflashed (and hence the chip restarted).调高电压:adc0 和 adc1 保持不变,只有在重新刷新 AVR 代码(因此芯片重新启动)时才会升高。
  • Returning count from hw_read_adc() instead of the ADC value: This returns varying numbers between 0x34 and 0x38 which are different for the two ADCs and continuously vary over time.hw_read_adc()返回count而不是 ADC 值:这将返回 0x34 和 0x38 之间的变化数字,这两个 ADC 不同并且随时间不断变化。

From these tests, I infer that the ADCs are being read, but that I am missing some "clear ADCH and ADCL and get them ready to accept the new reading" step.从这些测试中,我推断正在读取 ADC,但我缺少一些“清除 ADCH 和 ADCL 并让它们准备好接受新读取”的步骤。

I have re-read section 23 of http://www.atmel.com/images/Atmel-8272-8-bit-AVR-microcontroller-ATmega164A_PA-324A_PA-644A_PA-1284_P_datasheet.pdf many times, but have obviously overlooked something vital.我已经多次重读了http://www.atmel.com/images/Atmel-8272-8-bit-AVR-microcontroller-ATmega164A_PA-324A_PA-644A_PA-1284_P_datasheet.pdf 的第 23 节,但显然忽略了一些重要的东西.

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

The problem was that return (ADCH << 8) | ADCL;问题是return (ADCH << 8) | ADCL; return (ADCH << 8) | ADCL; was compiled so that it read the high register first (as you might expect).被编译以便它首先读取高位寄存器(如您所料)。

Page 252 of the datasheet says: "Otherwise, ADCL must be read first, then ADCH".数据表的第 252 页说:“否则,必须先读取 ADCL,然后再读取 ADCH”。

Changing my code to return ADC fixed the problem.更改我的代码以return ADC解决了这个问题。

My guess as to what was happening is:我对发生的事情的猜测是:

  • The read from ADCH occurred.发生了从 ADCH 的读取。
  • The read from ADCL had the effect of locking the ADC-result, to prevent tearing.从 ADCL 读取具有锁定 ADC 结果的效果,以防止撕裂。
  • The next ADC read had nowhere to write its result, as the ADC-result was locked.下一次 ADC 读取无处可写其结果,因为 ADC 结果被锁定。
  • Repeat...重复...

The Problem with your code is you read ADCH first.您的代码的问题是您首先阅读 ADCH。

ADCL must be read first , then ADCH, to ensure that the content of the Data Registers belongs to the same conversion.必须先读取ADCL ,然后再读取ADCH,以确保Data Registers 的内容属于同一个转换。 Once ADCL is read, ADC access to Data Registers is blocked.一旦 ADCL 被读取,ADC 对数据寄存器的访问就会被阻止。 This means that if ADCL has been read, and a conversion completes before ADCH is read, neither register is updated and the result from the conversion is lost.这意味着如果已读取 ADCL,并且在读取 ADCH 之前完成转换,则两个寄存器都不会更新,并且转换结果将丢失。 When ADCH is read, ADC access to the ADCH and ADCL Registers is re-enabled.读取 ADCH 时,会重新启用对 ADCH 和 ADCL 寄存器的 ADC 访问。

So the correct code should be-所以正确的代码应该是——

return ADCL | (ADCH << 8) ;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM