Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: PWM на ATmega16A
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
qwerty1023
Использую PWM на базе Timer/Counter1. Инициализирую следующим образом:

Код
/ Timer 1 Fast PWM 0x3FF TOP
// TCCR1A
//   1     0      1      0      0     0     1    1
//COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10
TCCR1A = (1<<COM1A1)|(1<<COM1B1)|(1<<WGM11)|(1<<WGM10);
// TCCR1B
//   0     0    0     0     1    0     0    1
//ICNC1 ICES1   –   WGM13 WGM12 CS12 CS11 CS10
TCCR1B = (1<<WGM12)|(1<<CS10);
// разрешить прерывание
TIMSK |= (1<<TOIE1);


OCR1x обновляются в прерывании по переполнению TIMER1_OVF как то так:

Код
#pragma vector = TIMER1_OVF_vect
__interrupt void _pwm (void)
{

if (xDivCh1 < pwmSpeedDivCh1)
{
  xDivCh1++;
}
else
{
  xDivCh1 = 0;
  
  if (curPWMCh1 != OCR1A)
  {
    if (curPWMCh1 < OCR1A) OCR1A--;
    if (curPWMCh1 > OCR1A) OCR1A++;
  }
}
...


Проблема вот в чем. Если OCR1x равно 0x3FF (верхнее значение) выхода постоянно "стоят" в 1 уровне, как и положено. Если значение OCR1x < 0x3FF но > 0 то тоже все работает коректно. Но, когда OCR1x равно 0 на выходе, вместо того, чтобы держался постоянный 0, возникают коротенькие (около 100нс при частоте кварца 8МГц) пички 1-го уровня. Кто с таким сталкивался? Как побороть? Пока сделал костыль в виде проверки OCR1x на 0 и переконфигурирования либо порт либо выход ШИМа, но это имхо очень сильный костыль...

Код
#pragma vector = TIMER1_OVF_vect
__interrupt void _pwm (void)
{
uint tmpData;

if (xDivCh1 < pwmSpeedDivCh1)
{
  xDivCh1++;
}
else
{
  xDivCh1 = 0;
  
  tmpData = OCR1A;
  
  if (curPWMCh1 != tmpData)
  {
    if (curPWMCh1 < tmpData) OCR1A--;
    if (curPWMCh1 > tmpData) OCR1A++;
  }
  if (tmpData == 0)
  {
    // отключение шима от портов
    TCCR1A &= ~((1<<COM1A1)|(1<<COM1A0));
    PORTD &= ~(1<<PD5);
  }
  else
  {
    TCCR1A |= (1<<COM1A1);
  }
}
...
SergeiP
Да мне кажется, такое поведение даже в даташите описано.
Так что это не баг, а фича :-)
qwerty1023
Да, вопрос в том, как это элегантно обойти...
RabidRabbit
Используйте PWM, Phase Correct или PWM, Phase and Frequency Correct режимы. В доке всё есть, надо только прочитать...

pavel-pervomaysk
ATtiny13, Mega8, у этих точно так же, если 0 - выключал PWM.
RabidRabbit
Ну не понимаю я людей, которые даташит не читают... Если использовать Phase Correct PWM Mode, ничего выключать не надо.
Для примера, Tiny13, Phase Correct PWM Mode
The extreme values for the OCR0A Register represent special cases when generating a PWM waveform output in the phase correct PWM mode. If the OCR0A is set equal to BOTTOM, the output will be continuously low and if set equal to MAX the output will be continuously high for non-inverted PWM mode. For inverted PWM the output will have the opposite logic values.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.