Вы назначаете неправильные биты неправильным регистрам. Чтобы уточнить: ШИМ - это НЕ аналоговый выход. Быстро изменяется высокое или низкое состояние выхода. Значение PWM определяет, как долго выход будет находиться в каждом состоянии (высоком или низком) в течение периода таймера.
Если вы хотите сделать «аналоговый» выход, вам нужно отфильтровать выходной сигнал, например, пропустив его через RC-фильтр, также вам нужно сделать вывод как можно быстрее, это означает, что вам нужно выбрать нижний предделитель и выбрать Режим Fast-PWM. В вашей текущей конфигурации вы получите pwm с предварительным делителем 1024. Т.е. менее 4 периодов таймера в секунду.
Итак, если вы назначите быстрый ШИМ с предварительным делителем 1 (который даст нам выходную частоту 3906 Гц) с инвертированным выходом (т.е. более высокое значение 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
}
}
person
AterLux
schedule
04.06.2015