我想输出两个不同的模拟值,分辨率为10位,即dac_value范围为0-1023。我使用ATmega16与外部晶体4MHz。我也尝试在输出端连接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 (;;) {}
}
答案 0 :(得分:1)
您正在为错误的寄存器分配错误的位。 只是为了澄清:PWM它不是模拟输出。它很快改变了高或低输出状态。 PWM值决定了定时器周期内每个状态(高电平或低电平)的输出长度。
如果你想制作“模拟”输出,你需要过滤输出信号,例如,通过RC滤波器,你需要尽可能快地输出,这意味着你需要选择较低的预分频器,并选择Fast-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
}
}