Код
/ 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);
// 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++;
}
}
...
__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);
}
}
...
__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);
}
}
...