Xmega: Генерация синусоидального сигнала

    Если вы хотите генерировать синусоидальный сигнал с помощью микроконтроллера Xmega, самый простой способ сделать это - использовать фиксированную таблицу синусов, хранящуюся в памяти контроллера, таймер и PWM  контроллера.
    Принцип:
    Таблица синусов содержит полное синусоидальный период. Для этой цели индивидуальные значения напряжения были рассчитаны с горизонтальным фиксированным размером шага с вертикальным разрешением 256 значений. Если эти значения последовательно выводятся с фиксированной частотой через модуль ШИМ с разрешающей способностью 8 бит, то есть 256 шагов, этот рабочий цикл будет меняться в зависимости от этой синусоиды. Так как Xmega работает при напряжении 3,3 В, амплитуда синусоидальной волны составляет +/- 1,65 В, при этом 1,65 В (значение таблицы 127) является виртуальным нулем. Скорость вывода задается частотой, установленной в таймере. Чем выше эта частота, тем выше частота синусоидальной волны.
    Синусоидальная волна в таблице начинается с 127, что равно 0 (1.65 В). Затем градиент поднимается вверх, имеет максимум при 255 (3.3 В), снова идет вниз, проходит через 127 (1.65 В), затем достигает минимума 0 (0.0 В), а затем снова поднимается до начальной точки на 128 (1,65 В). После этого запуска весь процесс начинается снова с нового колебания.
    Сгенерированный синусоидальный ШИМ-сигнал затем сглаживается с помощью фильтра нижних частот, то есть RC-элемента, с помощью которого получается аналоговое синусоидальное напряжение.

    3-фазный синусоидальный генератор
    Если вы хотите генерировать 3 синусоидальных сигнала, сдвинутых по фазе, все это следует тому же основному принципу, что и при использовании простого синусоидального сигнала. Дополнительные сигналы также генерируются с помощью двух дополнительных блоков ШИМ. Преимущество Xmega  заключается в том, что с модулем PWM вы можете создавать до 4 PWM с разными рабочими циклами. Однако все эти ШИМ имеют один и тот же источник синхронизации, который заставляет их работать синхронно. Все, что вам нужно сделать, это обеспечить одновременное обновление всех трех PWM, а не только одной PWM. Сдвиг получается пуском всех трех сигналов ШИМ с другим значением в таблице синусов, см.         Исходный код в качестве примера:
#define TIMERRELOAD 256 
#define AUFLOESUNG 65536 // 16-Bit Counter 65535
const uint8_t sinustabelle[512] PROGMEM = {127,130,133,136,139,143,146,
149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,
203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,
240,242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,
254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,
240,239,238,236,234,233,231,229,227,225,223,221,219,217,215,212,210,208,205,
203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,
149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,
87,84,81,78,76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,
25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,
1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,33,35,37,39,42,
44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,
111,115,118,121,124,130,133,136,139,143,146,149,152,155,158,161,164,167,170,
173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,
221,223,225,227,229,231,233,234,236,238,239,240,242,243,244,245,247,248,249,
249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,
252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,
227,225,223,221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,
181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,
124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,76,73,70,67,64,62,59,
56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,
7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,
16,18,20,21,23,25,27,29,31,33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,
73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124};
 
volatile union {uint16_t u16; uint8_t u8[2];} counterA;
volatile uint16_t offset;
 
//######################################################### 
void sinus_setFreq(int Ausgabefrequenz)
{
 offset=((F_CPU/2+Ausgabefrequenz*TIMERRELOAD*AUFLOESUNG)/F_CPU); 
 /* F_CPU/2 fürs Runden */
}
//######################################################### 
void sinus_init(void)
{
 sbi(PORTF.DIR,0); 
 sbi(PORTF.DIR,1); 
 sbi(PORTF.DIR,2); 
 /* Modus BIT0/1=Single Slope PWM BIT4=OCA, BIT5=OCB Enable */
 TCF0.CTRLA = TC_CLKSEL_DIV1_gc; // Prescaler 1
 TCF0.CTRLB = 0b11110011; 
 TCF0.PER = 0x00ff; 
 TCF0.CNT = 0x00; 
 TCF0.INTCTRLA = 0b00000011; 
 
 TCF0.CCA = 100; 
 TCF0.CCB = 100;
 TCF0.CCC = 100;
 
 counterA.u16=0;
}
//######################################################### Int Timer F0
ISR(TCF0_OVF_vect)
{
 TCF0.CCA = pgm_read_byte(&sinustabelle[counterA.u8[1]+ 0]);
 TCF0.CCB = pgm_read_byte(&sinustabelle[counterA.u8[1]+ 85]);
 TCF0.CCC = pgm_read_byte(&sinustabelle[counterA.u8[1]+171]);
 counterA.u16 += offset; 
}
//######################################################### Main
int main (void) 
{ 
 cli(); 
 sinus_init();
 
 PMIC.CTRL |= PMIC_HILVLEN_bm |PMIC_MEDLVLEN_bm|PMIC_LOLVLEN_bm; 
 sei(); 
 
 sinus_setFreq(150); 
 
 while(1) 
 { 
 }
} 
    Blogger Comment
    Facebook Comment

0 коммент.:

Отправить комментарий