2016-03-12 5 views
0

Я работаю над проектом на Arduino. Для создания цифрового синтезатора. Я буду использовать PWM для генерации выходной волны на нужной частоте нот и выборки волны на частоте 192 кГц.Как настроить прерывание для аппаратной PWM на Arduino Due?

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

Вот мой код. Я могу заставить PWM работать, но мой фиктивный код в прерывании (который включает и выключает вывод) не переключает вывод. Я проверил это с помощью осциллографа. Я знаю, что проблема с кодом заключается в том, что прерывание не запускается/выполняется должным образом, потому что выходной вывод установлен в установочном коде, и это также происходит на осциллографе. Однако контрольный контакт прерывания не переключается. Что мне не хватает?

uint32_t pwmPin = 8; // PWM output pin 
uint32_t channel = g_APinDescription[pwmPin].ulPWMChannel; 
uint32_t sampFreq = 192000ul; // sample at 192kHz 
uint32_t clkAFreq = 42000000ul; 
uint32_t pwmFreq = (clkAFreq * 2)/sampFreq; 
uint16_t dutyPercent = 50; 
uint16_t dutyAct = pwmFreq * (100-dutyPercent)/100; 

void setup() { 
    // put your setup code here, to run once: 


pinMode(5, OUTPUT); // interrupt test pin 

    pmc_enable_periph_clk(PWM_INTERFACE_ID); 
    PWMC_ConfigureClocks(clkAFreq, 0, VARIANT_MCK); 

    PIO_Configure(
    g_APinDescription[pwmPin].pPort, 
    g_APinDescription[pwmPin].ulPinType, 
    g_APinDescription[pwmPin].ulPin, 
    g_APinDescription[pwmPin].ulPinConfiguration); 

    //uint32_t 
    channel = g_APinDescription[pwmPin].ulPWMChannel; 
    PWMC_ConfigureChannel(PWM_INTERFACE, channel, clkAFreq, 0, 0); 
    PWMC_SetPeriod(PWM_INTERFACE, channel, pwmFreq); 
    PWMC_EnableChannel(PWM_INTERFACE, channel); 
    PWMC_SetDutyCycle(PWM_INTERFACE, channel, dutyAct); 
    PWMC_EnableChannelIt(PWM_INTERFACE, channel); 
    dutyPercent = 50; //square wave 

} 

void loop() { 
    // put your main code here, to run repeatedly: 

} 


void PWM_Handler()   // this is what I looked up in startup_sam4s.c 
{ 
    int i;     // 
    digitalWrite(5, HIGH); // toggle pin 
    i++;      // delay a little 
    digitalWrite(5, LOW);  // toggle pin 
} 
+0

Вы можете уточнить «попробовать волну в 192kHz»? Является ли внешнее устройство выборкой выходного сигнала Arduino? Или Arduino производит выборку внешнего входа? – mhopeng

+0

Я обычно думаю о сигналах ШИМ как квадратные волны с модулированным рабочим циклом. Что вы ожидаете от «значения ШИМ для разных типов волн (грех, пилообразный и т. Д.)»? – mhopeng

+0

В PWM_Handler() не определено значение 'i', поэтому время, в течение которого вывод 5 является высоким, очень короткий. Вместо этого попробуйте использовать 'delay (500)'. – mhopeng

ответ

2

Для тех, кто спотыкается через это, вот как я получил прерывание работы:

uint32_t totalTime = 0; // total elapsed time 

uint32_t pwmPin = 8; // PWM output pin 
uint32_t irqPin = 5; // interrupt test pin 
uint32_t channel = g_APinDescription[pwmPin].ulPWMChannel; // set channel for PWM out 
uint32_t sampFreq = 192000ul; // sampling frequency (Hz) 
uint16_t maxDutyCount = 255; 
uint32_t clkAFreq = 42000000ul; // clock frequency (Hz) 
uint32_t pwmFreq = (clkAFreq * 2)/sampFreq; // calculate PWM frequency 
uint16_t dutyPercent = 128; // starting duty percent 
uint16_t dutyAct = pwmFreq * (maxDutyCount-dutyPercent)/maxDutyCount; // 

void setup() { 
    // put your setup code here, to run once: 
    pinMode(irqPin, OUTPUT); 

    pmc_enable_periph_clk(PWM_INTERFACE_ID); 
    PWMC_ConfigureClocks(clkAFreq, 0, VARIANT_MCK); 

    PIO_Configure(
    g_APinDescription[pwmPin].pPort, 
    g_APinDescription[pwmPin].ulPinType, 
    g_APinDescription[pwmPin].ulPin, 
    g_APinDescription[pwmPin].ulPinConfiguration); 

    channel = g_APinDescription[pwmPin].ulPWMChannel; // channel 5 
    PWMC_ConfigureChannel(PWM_INTERFACE, channel, clkAFreq, 0, 0); 
    PWMC_SetPeriod(PWM_INTERFACE, channel, pwmFreq); 
    PWMC_EnableChannel(PWM_INTERFACE, channel); 
    PWMC_SetDutyCycle(PWM_INTERFACE, channel, dutyAct); 
    PWM_INTERFACE->PWM_IER1 = 0x20; //enable interrupt on channel 5 
    PWM_INTERFACE->PWM_IDR1 = 0xFFFFFFDF; //enable interrupt on channel 5 
    PWM_INTERFACE->PWM_IER2 = 0x00002001; //enable interrupt on channel 5 
    PWM_INTERFACE->PWM_IDR2 = 0xFFFFDFFE; //enable interrupt on channel 5 

    NVIC_DisableIRQ(PWM_IRQn); // set up interrupt 
    NVIC_ClearPendingIRQ(PWM_IRQn); 
    NVIC_SetPriority(PWM_IRQn, 0); 
    NVIC_EnableIRQ((IRQn_Type)36); //NVIC_EnableIRQ(PWM_IRQn); 
    PWMC_EnableChannel(PWM_INTERFACE, channel); 
    //Enable of the Interrupts (writing CHIDx and FCHIDx 
    //in PWM_IER1 register, and writing WRDYE, ENDTXE, 
    //TXBUFE, UNRE, CMPMx and CMPUx in PWM_IER2 register) 
} 

void loop() { 
} 


void PWM_Handler(void) // PWM interrupt handler 
{ 
    volatile long dummy = PWM_INTERFACE->PWM_ISR1; // clear interrupt flag 
    dummy = PWM_INTERFACE->PWM_ISR2; // clear interrupt flag 
//your code here! 
} 
Смежные вопросы