0

我想以 10 位分辨率输出两个不同的模拟值,即 dac_value 范围为 0-1023。我正在使用带有外部晶体 4MHz 的 ATmega16。我也尝试在输出端连接 RC 滤波器,但没有任何改变。我经常得到零输出,有人可以帮忙吗?

#include <avr/io.h>
#include <avr/interrupt.h>

void initPWM()
{
  TCCR1A |= (1<<WGM11) | (1<<WGM10) | (1<<COM1A1) | (1<<COM1A0) | (1<<COM1B1) | (1<<COM1B0) ;
  TCCR1B |= (1<<WGM12) | (1<<CS10);
}


    uint16_t dac_value1 = 100, dac_value2 = 200;
int main(void)
{
    initPWM();
      while(1) {
      OCR1A = dac_value1;
      OCR1B = dac_value2;
          }
     for (;;) {}

 }
4

1 回答 1

1

您将错误的位分配给错误的寄存器。澄清一下:PWM 它不是模拟输出。它迅速改变高或低输出状态。PWM 值决定了在定时器周期内每个状态(高或低)输出将持续多长时间。

如果要进行“模拟”输出,则需要对输出信号进行滤波,例如通过 RC 滤波器,还需要尽可能快地输出,这意味着您需要选择较低的预分频器,并选择快速 PWM 模式。在您当前的配置中,您将获得带有 1024 预分频器的 pwm。即每秒少于 4 个定时器周期。

因此,如果我们将分配一个带有预分频器 1 的快速 pwm(这将为我们提供 3906 Hz 输出)和反向输出(即较高的 OCR1x 值导致较低的输出值),它将是这样的:

void initPWM()
{
    TCCR1A = (1<<WGM11) | (1<<WGM10) | (1<<COM1A1) | (1<<COM1A0) | (1<<COM1B1) | (1<<COM1B0); 
    // here bits WGM10 WGM11 (with WGM12 in TCCR1B) will select the Fast PWM mode with 10 bit resolution; 
    // COM1A1 COM1A0 COM1B1 COM1B0 select an inverted PWM output on pins OC1A OC1B
    TCCR1B = (1<<WGM12) | (1<<CS10);
    // CS10 will select  1:1 prescaler (i.e. 4000000/1024 timer periods per second)

    // Also, your PWM output will not be visible on corresponding pins, unless you will configure an DDR bits for these pins to output. Those pins are PD5 and PD4 on ATmega16
    DDRD |= (1 << 4) | (1 << 5);
}

您需要考虑的下一件事:当您的应用程序main()函数执行结束时,它将跳转到重置向量。因此,在 main() 的末尾放置一个空循环:

int main(void)
{
    uint16_t dac_value1, dac_value2;
    dac_value1 = 123; // do not forget to init variables!!!
    dac_value2 = 987; 
    initPWM();
    OCR1A = dac_value1;
    OCR1B = dac_value2;
    for(;;) {
        // main loop. Now it's empty
    } 
}
于 2015-06-04T22:14:00.357 回答