Мы не можем правильно генерировать синусоидальный сигнал с помощью микроконтроллера MC68HC908GP32 . Описание ШИМ начинается на стр. 349. Тактовая частота составляет 2,4 МГц, в то время как мы использовали ШИМ 7 кГц, используя прескалер и установив таймер по модулю 350 следующим образом:
T1SC = 0x60; // Prescaler: Div entre 64
//Counter modulo = 0x015E = 350
T1MODH = 0x01; // High
T1MODL = 0x5E; // Low
Выход ШИМ фильтруется следующим RLC-фильтром, а затем постоянный ток удаляется с помощью колпачка серии 1 мкФ. Частота среза намного ниже 7 кГц ШИМ.
Сначала мы попытались использовать LUT, образцы которого были сгенерированы с использованием этого сайта (100 образцов, амплитуда = 250). Это включает в себя один период.
int seno[100]={ 125, 133, 141, 148, 156, 164, 171, 178, 185, 192, 198, 205, 211, 216, 221, 226, 231, 235, 238, 241, 244, 246, 248, 249, 250, 250, 250, 249, 248, 246, 244, 241, 238, 235, 231, 226, 221, 216, 211, 205, 198, 192, 185, 178, 171, 164, 156, 148, 141, 133, 125, 117, 109, 102, 94, 86, 79, 72, 65, 58, 52, 45, 39, 34, 29, 24, 19, 15, 12, 9, 6, 4, 2, 1, 0, 0, 0, 1, 2, 4, 6, 9, 12, 15, 19, 24, 29, 34, 39, 45, 52, 58, 65, 72, 79, 86, 94, 102, 109, 117};
Ширина следующего импульса вычисляется каждый цикл ШИМ:
interrupt 4 void rsi_t1ch0 (void)
{
//-- disable interruption flag
T1SC0&=(~0x80);
//-- pwm to '0'
PTB&=0xFD;
//some sensor measures are done here.... 100 out of the 350 cycles are left for this
}
/************************************************************/
/* TIM1 overflow rutine */
/************************************************************/
interrupt 6 void rsi_ov1 (void)
{
T1SC&=(~0x80);
//-- set PWM to 1
PTB|=0x02;
T1CH0H = ((seno[fase])>>8); // high bits
T1CH0L = (seno[fase])&0xFF; // low bits
fase+=1;
if (fase >= 99)
fase=0;
}
void main(void)
{
float temp;
int i;
CONFIG1|=0x01;
DDRB=0xFF; //-- Port B is set as output
PTB=0x00;
//Timer setup
T1SC = 0x60; // Prescaler: Div by 64
T1MODH = 0x01; //Counter modulo
T1MODL = 0x5E;
T1SC0 = 0x50; //Comparator setup
//-- Initial width
T1CH0H = 0x00;
T1CH0L = 0x53;
EnableInterrupts;
T1SC&=~(0x20); //Run timer forever
for(;;);
}
Когда подключаем его в прицел, мы получаем следующий сигнал. Мы не можем избежать этого странного пика вблизи минимума.
При масштабировании вокруг этого пика мы можем видеть, как на самом деле выход ШИМ (вверх) неверен.
Итак, после недолгой разминки и неспособности избавиться от нее, мы попытались вычислить синусоидальный сигнал в MCU вместо жесткого кодирования значения для каждой выборки. Мы добавили следующий код в основную функцию непосредственно перед настройкой счетчика:
for(i=0;i<99;i++) {
temp=100*(sin(2*3.14159*i/100)+1);
seno[i]=(int)temp;
}
Но результаты даже не похожи на синусоиду:
После нескольких часов борьбы мы не смогли найти свою ошибку. Мы были бы признательны за совет.
источник
Ответы:
В нижней части страницы 350 таблицы данных по микроконтроллеру упоминается, что запись небольшого значения в регистр значений таймера во время прерывания переполнения может вызвать срабатывание следующего прерывания только на следующей итерации ШИМ, поскольку таймер продолжает считать, пока таймер процедура прерывания выполняется.
Это подтверждается тем фактом, что значение ШИМ поддерживается на высоком уровне в течение одного полного тактового периода ШИМ +, что выглядит как длина таймера (на основе окружающих длин). Значение, записываемое в регистр длины таймера, вероятно, близко к 0 во время ошибки, поэтому весьма вероятно, что счетчик прошел меньшее значение во время прерывания и будет срабатывать только в следующем цикле.
Это можно исправить, увеличив минимальный уровень синусоиды до уровня, превышающего время, необходимое для выполнения ISR, или изменив механизм, с помощью которого устанавливается новый уровень. В верхней части страницы 351 показано, как это можно сделать.
источник