如何为Arduino Due上的硬件PWM配置中断?

时间:2016-03-12 20:27:37

标签: arduino interrupt pwm

我正在研究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
}

1 个答案:

答案 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!
}