我正在研究Arduino上的一个项目由于制作数字合成器。我将使用PWM以所需的音频频率生成输出波,并以192kHz采样波。
我能够以所需的频率输出PWM并调整脉冲宽度(用示波器测试),但是我需要配置中断,以便我可以计算不同类型的不同类型波的下一个所需PWM值频率(罪,锯齿等)。每次中断触发(192kHz)时,函数将根据音符值(可听频率)计算下一个脉冲宽度值。
到目前为止,这是我的代码。我能够使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 :(得分:1)
对于任何偶然发现这种情况的人来说,这就是我让中断工作的方式:
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!
}