Hello Jeremy,
Thanks for your reply. I made a simple demo to show my problem. I call Run_Burst_Sequence() with 10 pulses every time but with different duty-cycle each time (50%, 50%, 0%, 50%, 100%, 50%), and as you can see the correct output depends on the previous state.
The Stop_Burst_Sequence() is a routine which sets match registers in a particular way to ensure that the first pulse is started immediately, otherwise it would wait one period before starting and skip the first pulse output which is unacceptable.
Reset_PWM() routine is called with value 1 for the first pulse if DC > 0 so that first pulse has correct width. Otherwise first pulse would be 1 timer tick wider.
#include "LPC17xx.h"
#define BIT0 (1ul<< 0)
#define BIT1 (1ul<< 1)
#define BIT3 (1ul<< 3)
#define BIT6 (1ul<< 6)
#define BIT9 (1ul<< 9)
uint16_t NumberOfPulses;
uint8_t SequenceRunning_Flag = 0;
volatile uint16_t Match_Counter = 0;
volatile uint8_t DrivePwmLow_Flag = 0;
/* Used for incrementing counter on match register interrupt to count number of pulses */
void PWM1_IRQHandler()
{
Match_Counter += (LPC_PWM1->IR & BIT0);
if (Match_Counter >= NumberOfPulses)
{
LPC_PWM1->MCR &= ~(BIT0); /* disable interrupts on match 0 */
Match_Counter = 0;
DrivePwmLow_Flag = 1;
}
LPC_PWM1->IR = 0x70F; /* clear all interrupt channels */
}
void Reset_PWM(uint8_t tcVal)
{
uint32_t TempTCR;
TempTCR = LPC_PWM1->TCR;
LPC_PWM1->TCR |= BIT1;
LPC_PWM1->TCR = 0;
LPC_PWM1->TC = tcVal;
LPC_PWM1->TCR |= BIT3;
LPC_PWM1->TCR = TempTCR;
}
void Initialize_PWM()
{
LPC_SC->PCONP |= BIT6;
LPC_SC->PCLKSEL |= 1; /* divide clock by 1 */
LPC_PWM1->MCR |= BIT1; /* enable reset on match 0 */
Reset_PWM(0);
LPC_PWM1->TCR |= BIT0;
LPC_PWM1->TCR |= BIT3;
NVIC_EnableIRQ(PWM1_IRQn);
LPC_IOCON->P2_0 = 0x21; /* Pin func = PWM, no pull up/down, hysteresis on(default) */
LPC_PWM1->PR = 480000; /* Set prescale to 10 ms, depends on the clock, clk = 48Mhz */
}
void Stop_Burst_Sequence()
{
LPC_PWM1->MR1 = 0;
LPC_PWM1->LER |= BIT1;
Reset_PWM(0);
LPC_PWM1->PCR &= ~BIT9; /* Disable output for channel 1, pin 2.0 */
LPC_PWM1->MR0 = 1;
LPC_PWM1->MR1 = 1;
LPC_PWM1->LER |= BIT0;
LPC_PWM1->LER |= BIT1; /* Latch match registers */
Reset_PWM(0);
LPC_PWM1->MR1 = 0;
LPC_PWM1->LER |= BIT1;
Reset_PWM(0);
}
void Run_Burst_Sequence(uint16_t Pulses, uint16_t DutyCycle)
{
NumberOfPulses = Pulses;
LPC_PWM1->MR0 = 100; /* 100 ms fixed period for demo purposes */
LPC_PWM1->MR1 = DutyCycle;
LPC_PWM1->LER |= BIT0;
LPC_PWM1->LER |= BIT1; /* Latch match registers */
LPC_PWM1->PCR |= BIT9; /* Enable output for channel 1, pin 2.0 */
if (DutyCycle == 0)
{
Reset_PWM(0);
}
else
{
Reset_PWM(1);
}
LPC_PWM1->MCR |= BIT0; /* enable interrupts on match 0 */
SequenceRunning_Flag = 1;
}
void Burst_Stop_Capture()
{
uint32_t i;
if (DrivePwmLow_Flag)
{
Stop_Burst_Sequence();
for (i = 0; i < 9000000; i++); /* delay */
DrivePwmLow_Flag = 0;
SequenceRunning_Flag = 0;
}
}
/*** main ***/
int main( void )
{
int cnt = 0;
uint16_t DCycleVals[] = {50, 50, 0, 50, 100, 50};
Initialize_PWM();
while(1)
{
if (!SequenceRunning_Flag)
{
Run_Burst_Sequence(10, DCycleVals[cnt]);
cnt++;
}
Burst_Stop_Capture();
if (cnt > sizeof(DCycleVals) / sizeof(uint16_t))
break;
}
return 0;
}