Hi everyone!
I'm using SCTimer in LPC845 to generate a PWM signal. The behaviour is very good and very stable, but when I set the duty to 0% I see short peaks (~40ns) in the output. It's very important for my design that those spikes are not present at the output (deformation of the signal result). Of course, if I perform the PWM manually via ctimer I haven't the spikes because I have full control of the shape, but my idea is to use the HW PWM from SCTimer for all reasons and advantages it has. Surely I'm doing something wrong.
I want to use two outputs, when one of them is making the PWM the other one has to put 0 at the output (or depending the Duty activity that I choose configure to use). This is my initialization:
void Inicializar_SCTimer( void )
{
SYSCON->SYSAHBCLKCTRL0 |= (1 << 7) | (1 << 8); // 8= SCTIMER 7=SWM
SYSCON->PRESETCTRL0 |= (1 << 8); // 8= SCTIMER clear the timer reset
SYSCON->SCTCLKSEL = 1; // 1:Main clock 24MHz
SYSCON->SCTCLKDIV = 1; // divided by n
SWM0->PINASSIGN.PINASSIGN7 &= (~(0xff << (24))); // SCT_OUT0 = PWM PIO0.8 -> pin 21
SWM0->PINASSIGN.PINASSIGN7 |= (8 << (24));
SWM0->PINASSIGN.PINASSIGN8 &= (~(0xff << (0))); // SCT_OUT1 = PWM PIO0.9
SWM0->PINASSIGN.PINASSIGN8 |= (9 << (0)); // PIO0.9 OUT1 -> pin 22
SCT0->CONFIG |= (1 << 0) | (1 << 17);
SCT0->SCTMATCH[0] = FREQ_PRINCIPAL/(PWM_FREQ*1);
SCT0->SCTMATCHREL[0] = FREQ_PRINCIPAL/(PWM_FREQ*1);
SCT0->EVENT[0].STATE = 0xFFFFFFFF;
SCT0->EVENT[0].CTRL = 0 | (1 << 12);
SCT0->OUTPUT = 0xC; //Esto no tiene efecto luego
SCT0->RES = 0b01010101; //Habría que hacer pruebas
SCT0->EVEN = 1;
//SCT0->EVEN = 3;
SCT0->EVENT[1].STATE = 0xFFFFFFFF;
SCT0->EVENT[1].CTRL = 1 | (1 << 12); //Referido a Match1 Combmode 1== Match only
#ifdef DUTYaCTIVOaLTO
SCT0->OUT[0].SET = 1;
SCT0->OUT[0].CLR = (1<<1);
#else
SCT0->OUT[0].SET = (1<<1);
SCT0->OUT[0].CLR = 1;
#endif
SCT0->SCTMATCH[1] = 0; //Duty pwm1
SCT0->SCTMATCHREL[1] = 0; //Duty pwm1
//-------------------------------------------
SCT0->SCTMATCH[2] = FREQ_PRINCIPAL/(PWM_FREQ*1);
SCT0->SCTMATCHREL[2] = FREQ_PRINCIPAL/(PWM_FREQ*1);
SCT0->EVENT[2].STATE = 0xFFFFFFFF;
SCT0->EVENT[2].CTRL = 2 | (1 << 12);
SCT0->EVENT[3].STATE = 0xFFFFFFFF;
SCT0->EVENT[3].CTRL = 3 | (1 << 12); //Referido a Match3 Combmode 1== Match only
#ifdef DUTYaCTIVOaLTO
SCT0->OUT[1].SET = (1<<2); //Actua en base a evento2
SCT0->OUT[1].CLR = (1<<3); //Actua en base a evento3
#else
SCT0->OUT[1].SET = (1<<3); //Actua en base a evento3
SCT0->OUT[1].CLR = (1<<2); //Actua en base a evento2
#endif
SCT0->SCTMATCH[3] = 0; //Duty pwm2
SCT0->SCTMATCHREL[3] = 0; //Duty pwm2
NVIC->ISER[0] = (1 << 9);
SCT0->CTRL &= ~(1 << 2); //Start SCTimer
PWM1_set( 65 ); //6.5%
PWM2_set( 90 ); //9%
}
PWM1_set is from AN (with my changes), only the first if has relevance when the duty is 0:
void PWM1_set(uint32_t value)
{
if (value == 0)
{
SCT0->SCTMATCHREL[1] = 0; // check val between 0% and 100%
}
else
{
if ( value >= CINCOpORCIENTO && value <= DIEZpORCIENTO)
{
SCT0->SCTMATCHREL[1] = (value*DOScOMAcINCOmILIS)/DOCEcOMACINCOpORCIENTO;
}
else
{
SCT0->SCTMATCHREL[1] = FREQ_PRINCIPAL/(PWM_FREQ*1 - 1); // set to 100% duty cycle
}
}
}
The attached images shows the behaviour.
Any help would be appreciated!
BR
Mariano
解決済! 解決策の投稿を見る。
Hi,
I think you mean AN11538.pdf, it is a cook book about the SCTimer, a very good AN.
For the 0% and 100% duty cycle, it is special case. If you set the match1 zero, I suppose that an event still happens because counter increase from zero, so the spike is inevitable.
Hope it can help you
BR
XiangJun Rong
Hi,
I have checked your code, you use match0 register as limit to set up the period of the PWM signal. The Match0/match1 registers are used to generate event0/event1 to set/clear the OUT0 signal.
If you want to get the zero duty cycle, which means that you want to get a LOW logic in the intact PWM cycle. You want to get zero duty cycle and set the match1 reg to zero, which generates event 1 and clear the OUT0 signal, so the event1 will happen, the spike is doomed to happen, this is SCTimer mechanism drawback.
If you want to get 0% or 100% duty cycle, I suppose that this is a workaround, you can set the pin as GPIO pin and output 0. In detail, if it is a SWM output pin, you can set the SWM register bits as 0xFF, and set the pin as GPIO output mode and output 0. I suppose that 100% duty cycle also has issue, you can also set the Pin as GPIO output mode and output 1 logic. In order to keep the PWM intact cycle, you can have event0 generate interrupt, in the ISR, configure the pin as GPIO output. If you want to output PWM signal with duty cycle ranging from 1% to 99%, in the ISR, set up SWM to output PWM signal
Hope it can help you
BR
XiangJun Rong
Hi Rong, thank you for your reply.
I assumed the problem came from that side, in fact my manually PWM check for Duty 0% or 100% and in those particular cases I change the behaviour of the output.
So, you think that the AN1138 in the chapter "20. PWM with 0 - 100% duty cycle" is a solution?
I see slighty different initialization (uses MATCH0.L that I believe I haven't see in my lpc845.h) but I'll try to implement.
Thank you
BR
Mariano
Hi,
I think you mean AN11538.pdf, it is a cook book about the SCTimer, a very good AN.
For the 0% and 100% duty cycle, it is special case. If you set the match1 zero, I suppose that an event still happens because counter increase from zero, so the spike is inevitable.
Hope it can help you
BR
XiangJun Rong
Hi,
Yes, that one.
I agree, it's very good AN but in my opinion it is not correct that chapter 20 be titled "PWM with 0 - 100% duty cycle" when the actual behavior is not exactly 0%.
I saw your similar response for other similar cases, so I'm sorry for ask something that doesn't has solution (elegant).
By the way, the example in the same AN11538 "Center aligned PWM" seems to works fine in 0%, I tested with only one output and it's OK. When I add the second Output, doesn't works anymore. I have to continue investigating.
Thank you so much for your help.
Mariano