eleqian 发表于 2015-3-2 15:20:19

求助:ATtiny13A的ADC通道切换问题

需要用两个ADC通道采样不同的电压,使用了16倍过采样来得到12位的数据。现在出的状况是不管先采样哪个通道,开始的通道正确,再采样另一个通道的数据总是错的,值会受到前一个通道的影响。
用AVR比较少,对比数据手册和示例代码没找到原因。代码如下求指教:
typedef enum {
    ADC_CH_TEMP,
    ADC_CH_LIGHT
} ADC_Channel_t;

// Read ADC with oversampling to get 12bits result
static uint16_t ADC_Read(ADC_Channel_t ch)
{
    uint8_t i;
    uint8_t ADC_tempL;
    uint16_t ADC_var;

    if (ch == ADC_CH_TEMP) {
      // ADC2, VCC as reference
      ADMUX = (0 << REFS0) | (1 << MUX1) | (0 << MUX0);
    } else {
      // ADC3, Internal reference (1.1V)
      ADMUX = (1 << REFS0) | (1 << MUX1) | (1 << MUX0);
    }

    // Enable the ADC, 1.2MHz / 8 = 150kHz (Conversion time: 86uS)
    ADCSRA = (1 << ADEN) | (1 << ADPS1) | (1 << ADPS0);
    ADCSRB = 0x00;

    // do a dummy readout first
    ADCSRA |= (1 << ADSC);      // do single conversion
    while (!(ADCSRA & (1 << ADIF)));   // wait for conversion done, ADIF flag active
    ADCSRA &= ~(1 << ADIF);   // clear ADIF flag

    ADC_var = 2;
    // do the ADC conversion 16 times for oversampling
    for (i = 16; i != 0; i--) {
      ADCSRA |= (1 << ADSC);      // do single conversion
      while (!(ADCSRA & (1 << ADIF)));    // wait for conversion done, ADIF flag active
      ADCSRA &= ~(1 << ADIF);   // clear ADIF flag
      ADC_tempL = ADCL;         // read out ADCL register
      ADC_var += (ADCH << 8) | ADC_tempL; // accumulate result
    }
    ADC_var >>= 2;   // shift right to get extra 2 bits

    ADCSRA &= ~(1 << ADEN);   // disable the ADC

    return ADC_var;
}

qq729101414 发表于 2015-3-2 16:52:54

本帖最后由 qq729101414 于 2015-3-2 17:04 编辑

呃。。。这个不了解不过以前飞思卡尔的一款单片机对于AD转换   内部电容放电 有一个开关的。
就是下次采样之前 可以选择先让电容放电。{:smile:}

这个是数据手册关于 Free Running mode 的解释

编辑原因:补充回复。

zhanan 发表于 2015-3-2 17:11:41

30. ADC_var = 2;       初值为什么不是0 ?

28. 35.   ADIF 不是写0清零,应该是写1清零,看手册。

ADC初始化放在别处,做一次就可以吧,没必要频繁开启、关闭。

eleqian 发表于 2015-3-2 19:06:00

zhanan 发表于 2015-3-2 17:11
30. ADC_var = 2;       初值为什么不是0 ?

28. 35.   ADIF 不是写0清零,应该是写1清零,看手册。


问题解决了,非常感谢!是清标志位的地方疏忽了,改为写1解决问题。
另外2是用来“四舍五入”,因为后面除以了4。程序只是偶尔用到ADC,考虑到功耗用完就关了。
页: [1]
查看完整版本: 求助:ATtiny13A的ADC通道切换问题