Генерация синусоидального сигнала с использованием ШИМ

16

Мы не можем правильно генерировать синусоидальный сигнал с помощью микроконтроллера 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;
 }

Но результаты даже не похожи на синусоиду:

введите описание изображения здесь

После нескольких часов борьбы мы не смогли найти свою ошибку. Мы были бы признательны за совет.

саржа
источник
Не могли бы вы опубликовать весь список значений ШИМ?
pjc50
@ pjc50 Вот оно: pastebin.com/sNyA0Hki . Большое спасибо.
Серж
Попробуйте заменить все значения «0» в середине на «1»; Я подозреваю, что 0 дает вам этот широкий высокий сигнал, а не низкий, который вы хотите.
pjc50
@ Serge - Пожалуйста, укажите данные. Паста может исчезнуть, и было бы плохо потерять часть вопроса. Но, пожалуйста, отформатируйте его, чтобы он не занимал так много места. Благодарю.
Trygve Laugstøl
Это явно не фильтр - удачи - похоже, ваша таблица испортилась или вы потеряли указатель на нее.
Энди ака

Ответы:

16

В нижней части страницы 350 таблицы данных по микроконтроллеру упоминается, что запись небольшого значения в регистр значений таймера во время прерывания переполнения может вызвать срабатывание следующего прерывания только на следующей итерации ШИМ, поскольку таймер продолжает считать, пока таймер процедура прерывания выполняется.

Несинхронизированная запись в регистры канала TIM для изменения значения ширины импульса может привести к некорректной работе до двух периодов ШИМ. Например, запись нового значения до того, как счетчик достигнет старого значения, но после того, как счетчик достигнет нового значения, предотвращает любое сравнение в течение этого периода ШИМ. Кроме того, использование процедуры прерывания по переполнению TIM для записи нового, меньшего значения ширины импульса может привести к пропуску сравнения. TIM может передать новое значение до того, как оно будет записано.

Это подтверждается тем фактом, что значение ШИМ поддерживается на высоком уровне в течение одного полного тактового периода ШИМ +, что выглядит как длина таймера (на основе окружающих длин). Значение, записываемое в регистр длины таймера, вероятно, близко к 0 во время ошибки, поэтому весьма вероятно, что счетчик прошел меньшее значение во время прерывания и будет срабатывать только в следующем цикле.

Это можно исправить, увеличив минимальный уровень синусоиды до уровня, превышающего время, необходимое для выполнения ISR, или изменив механизм, с помощью которого устанавливается новый уровень. В верхней части страницы 351 показано, как это можно сделать.

stanri
источник
1
Я не знаю, как я мог пропустить это при чтении таблицы. Спасибо!
Серж