LPC55S28 SCTimer two PWM outputs with different frequencies

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

LPC55S28 SCTimer two PWM outputs with different frequencies

跳至解决方案
2,530 次查看
vanska
Contributor II

Hi,

I have tried to generate 2 PWM outputs with SCT0 of LPC55S28.

The requirements:

  • No CPU load (callbacks)
  • Outputs must be synchronized
  • Output X must have a frequency of output Y times 4
  • Duty cycle of both outputs must be 50 %

No luck yet with the examples or the PWM cookbook. Is this possible in theory?

2 PWM outputs with different frequencies2 PWM outputs with different frequencies

Edit: The signal of SCTIMER_Out_X in the picture is actually 8MHz while it should be 4MHz.

标签 (2)
0 项奖励
回复
1 解答
2,508 次查看
vanska
Contributor II

Got it working. The resolution is not that good with MHz frequencies, though.

Here's one solution that might require some refactoring:

uint32_t pwmFrequency = frequency * 4;
uint32_t sctClock = CLOCK_GetFreq(kCLOCK_BusClk) / (((base->CTRL & SCT_CTRL_PRE_L_MASK) >> SCT_CTRL_PRE_L_SHIFT) + 1U);

uint32_t period = (sctClock / pwmFrequency) - 1U;	// edge aligned PWM
uint32_t pulsePeriod = (period * 50U) / 100U;		// pulse width match value

base->MATCHREL_ACCESS16BIT[0].MATCHRELL = (uint16_t)(period * 4);	// match value for 1MHz

for (uint8_t i = 1; i < 8; i++)
{
	// Match values for the rest of the events
	base->MATCHREL_ACCESS16BIT[i].MATCHRELL = (uint16_t)((uint16_t)(i/2) * period + (i%2) * pulsePeriod);
}

for (uint8_t i = 0; i < 8; i++)
{
	base->EV[i].STATE = 0xFFFFFFFF;                 // all states
	base->EV[i].CTRL = (i << 0) | (1 << 12);        // match i condition only
}

base->OUT[2].SET = (1 << 0);                        // event 0 will set SCT0_OUT2
base->OUT[2].CLR = (1 << 4);                        // event 4 will clear SCT0_OUT2
base->OUT[3].SET = 0x55;                            // even events (0, 2, 4, 6) will set SCT0_OUT3
base->OUT[3].CLR = 0xAA;                            // odd events (1, 3, 5, 7) will clear SCT0_OUT3

base->CTRL &= ~(SCT_CTRL_HALT_L_MASK);              // start/unhalt timer by clearing bit 2 of CTRL register

在原帖中查看解决方案

0 项奖励
回复
2 回复数
1,909 次查看
laugechristense
Contributor II

I realize I am late for the party but I found a more flexible solution.
I used it to generate a 1MHz 50% dutycycle signal synchronized to a kHz 20% dutycyle.
I used the peripherals perspective in mcuxpresso, so it is hard to share source code, but the setup is as follows:
SCT clock is 16 MHz, using a prescaler of 8, the counter frequency is 2 MHz.

event 0:
match event with match value 0
action: toggle sct output 1

event 1
match event with match value 400
action: clear sct output 2

event 2
match event with match value 1999
action: set sct output 2 and limit counter (restart it from zero).

in the source code, add the following line before starting the timer:
SCT0->EV[0].CTRL |= SCT_EV_CTRL_MATCHMEM(1);
This means that the event 0 fires every clock after the initial match. since the match is set to 0 it just toggles the output at 1MHz from the the timer is started.

event 1 and event 2 control the second output and are responsible for limiting the timer.
They can be set almost independently of event0.

summary:
Choose a prescaler to get a counter frequency twice as fast as the fastest signal, by using the MATCHMEM setting of event 0.
Use two indenpendent events to set the second pwm channel and limit the counter.

 

Cheers,

Lauge

 

0 项奖励
回复
2,509 次查看
vanska
Contributor II

Got it working. The resolution is not that good with MHz frequencies, though.

Here's one solution that might require some refactoring:

uint32_t pwmFrequency = frequency * 4;
uint32_t sctClock = CLOCK_GetFreq(kCLOCK_BusClk) / (((base->CTRL & SCT_CTRL_PRE_L_MASK) >> SCT_CTRL_PRE_L_SHIFT) + 1U);

uint32_t period = (sctClock / pwmFrequency) - 1U;	// edge aligned PWM
uint32_t pulsePeriod = (period * 50U) / 100U;		// pulse width match value

base->MATCHREL_ACCESS16BIT[0].MATCHRELL = (uint16_t)(period * 4);	// match value for 1MHz

for (uint8_t i = 1; i < 8; i++)
{
	// Match values for the rest of the events
	base->MATCHREL_ACCESS16BIT[i].MATCHRELL = (uint16_t)((uint16_t)(i/2) * period + (i%2) * pulsePeriod);
}

for (uint8_t i = 0; i < 8; i++)
{
	base->EV[i].STATE = 0xFFFFFFFF;                 // all states
	base->EV[i].CTRL = (i << 0) | (1 << 12);        // match i condition only
}

base->OUT[2].SET = (1 << 0);                        // event 0 will set SCT0_OUT2
base->OUT[2].CLR = (1 << 4);                        // event 4 will clear SCT0_OUT2
base->OUT[3].SET = 0x55;                            // even events (0, 2, 4, 6) will set SCT0_OUT3
base->OUT[3].CLR = 0xAA;                            // odd events (1, 3, 5, 7) will clear SCT0_OUT3

base->CTRL &= ~(SCT_CTRL_HALT_L_MASK);              // start/unhalt timer by clearing bit 2 of CTRL register
0 项奖励
回复