QN9080 - PWM problem

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

QN9080 - PWM problem

826 次查看
shai_b
Senior Contributor II

Hello Team,

my customer has the following issue, could you please advise the below:

I am having a problem with using the SCTimer module on QN9080.

The interrupts do not seem to work properly, the interrupts seem to take way too much time.

I am attaching sample code and follows more details.

To use the code add the file to a new project include fsl_sctimer.h and comment out "SCTIMER_EventHandleIRQ","SCT0_IRQHandler" and finally run init on main.

 

Details:

needed output:

  • PWM output of sine wave in  488Hz with over sampling of 256

What was done:

  • Using a 32MHz clock, the needed PWM frequency is 125kHz (=clock/oversampling)
  • On SCTimer, set the limit counter to 255 (clock/desired frequency -1)
  • Set match event (SCTimer) to a value taken from lookup table at index i.
  • Set actions to clear output limit event and set the output for match event.
  • Then I set an interrupt for limit event
    • On the callback, update lookup index and load a new lookup value to the corresponding MATCHREL register

The problem

  • The resulting PWM output with a low pass (22kOhm and 10nF) was supposed to be 488Hz but was much lower.
  • I assumed the interrupts were handled slowly and so I commented out the driver ISR and rewrote it. In the end I managed to get 13Hz output.

// some how i did not managed to upload .C file so I have copy paste it here for you to review:

#include "stdint.h"

#include "fsl_sctimer.h"

#include "fsl_debug_console.h"

#include "pin_mux.h"

#include "fsl_gpio.h"

static const uint8_t lookupTable[LENGTH]={128, 131, 134, 137, 140, 143, 146, 149, 152, 156, 159, 162, 165, 168, 171, 174, 176, 179, 182, 185, 188, 191, 193, 196, 199, 201, 204, 206, 209, 211, 213, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 235, 237, 239, 240, 242, 243, 244, 246, 247, 248, 249, 250, 251, 251, 252, 253, 253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 253, 252, 252, 251, 250, 249, 248, 247, 246, 245, 244, 242, 241, 239, 238, 236, 235, 233, 231, 229, 227, 225, 223, 221, 219, 217, 215, 212, 210, 207, 205, 202, 200, 197, 195, 192, 189, 186, 184, 181, 178, 175, 172, 169, 166, 163, 160, 157, 154, 151, 148, 145, 142, 138, 135, 132, 129, 126, 123, 120, 117, 113, 110, 107, 104, 101, 98, 95, 92, 89, 86, 83, 80, 77, 74, 71, 69, 66, 63, 60, 58, 55, 53, 50, 48, 45, 43, 40, 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 19, 17, 16, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 11, 12, 13, 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, 79, 81, 84, 87, 90, 93, 96, 99, 103, 106, 109, 112, 115, 118, 121, 124, 128};

static volatile uint8_t increment=1;

static volatile uint8_t oversamplingCounter=0;

static volatile uint8_t lookupIndex=0,pulsePeriod;

static volatile uint32_t periodEvent,pulseMatchReg;

void SCTIMER_EventHandleIRQ(SCT_Type *base){}

void SCT0_IRQHandler(){

if(++oversamplingCounter==0){

SCT0->SCTMATCHREL[pulseMatchReg] = (uint32_t)pulsePeriod;

pulsePeriod=lookupTable[++lookupIndex];

}

}

void init(){

sctimer_config_t sctimerInfo;

uint32_t sctimerClock = CLOCK_GetFreq(kCLOCK_BusClk);

SCTIMER_GetDefaultConfig(&sctimerInfo);

SCTIMER_Init(SCT, &sctimerInfo);

uint32_t period;

uint32_t pwmFreq_Hz=125000U;

uint32_t pulseEvent;

/* Set unify bit to operate in 32-bit counter mode */

SCT0->CONFIG |= SCT_CONFIG_UNIFY_MASK;

/* Calculate PWM period match value */

period = (sctimerClock / pwmFreq_Hz) - 1;

/* Calculate pulse width match value */

pulsePeriod = (uint32_t)lookupTable[0];

/* Schedule an event when we reach the PWM period */

SCTIMER_CreateAndScheduleEvent(SCT, kSCTIMER_MatchEventOnly, period, 0, kSCTIMER_Counter_L, &periodEvent);

/* Schedule an event when we reach the pulse width */

SCTIMER_CreateAndScheduleEvent(SCT, kSCTIMER_MatchEventOnly, pulsePeriod, 0, kSCTIMER_Counter_L, &pulseEvent);

/* Retrieve the match register number for the PWM pulse period */

pulseMatchReg = SCT->EVENT[pulseEvent].CTRL & SCT_EVENT_CTRL_MATCHSEL_MASK;

/* Reset the counter when we reach the PWM period */

SCTIMER_SetupCounterLimitAction(SCT, kSCTIMER_Counter_L, periodEvent);

/* For high-true level */

/* Set the initial output level to low which is the inactive state */

SCT0->OUTPUT &= ~(1U << kSCTIMER_Out_0);

/* Set the output when we reach the PWM period */

SCTIMER_SetupOutputSetAction(SCT, kSCTIMER_Out_0, periodEvent);

/* Clear the output when we reach the PWM pulse value */

SCTIMER_SetupOutputClearAction(SCT, kSCTIMER_Out_0, pulseEvent);

SCTIMER_EnableInterrupts(SCT,1<<pulseEvent);

PRINTF("%d",SCT->EVEN);

NVIC_SetPriority(SCT0_IRQn, 4);

NVIC_EnableIRQ(SCT0_IRQn);

SCTIMER_StartTimer(SCT, kSCTIMER_Counter_L);

PRINTF("PWM started.\r\n");

}

Thanks in advance

Best regards,

Shai Berman

标签 (2)
标记 (1)
0 项奖励
回复
3 回复数

690 次查看
Sebastian_Del_Rio
NXP Employee
NXP Employee

Hi Shai, I hope you're doing well!

 

Could you please provide a screen capture of the generated waveform?

 

Could you please clarify what you mean by "PWM output of sine wave in  488Hz with over sampling of 256?"? Do you want to generate a sine or a square PWM wave?

 

Best regards,

Sebastian

0 项奖励
回复

690 次查看
shai_b
Senior Contributor II

Hi Sebastian,
thank you for replying back, please find Attached the waveforms.

qn9080_1.jpg

qn9080_2.jpg

Figure 1 is the direct output of the PWM port and Figure 2 is the output of the  1st order RC low pass filter consists of a resistor of 22Okhm and a capacitor of 10nF.
It can be seen that the output rate is 8uSec (as designed)  and the pulse width is changing. However, after the LPF we get very low frequency which means that the PWM in not responds fast according to the required pulse width.
The output of the PWM is generated from the Sine wave lookup table which is derived through the DDS algorithm.

Please advise back, thanks in advance

BR,

Shai

0 项奖励
回复

690 次查看
Sebastian_Del_Rio
NXP Employee
NXP Employee

Hi Shai,

 

I'm sorry, but could you please clarify what the issue is a bit more?

I see that on the QN9080's side the PWM wave is being generated as it should, and, if I'm understanding correctly, the duty cycle can be changed without issue.

I believe that the problem could either be with the algorithm used, or with the hardware for the Low-Pass Filter.

 

Best regards,

Sebastian

0 项奖励
回复