Pwm Using Timer Isr

Version 1

void ISR (void) __irq;
 
int main(void)
{
         PINSEL1 |= 0x00000800; 
         T3PR = 0x0000005; //Load prescaler
         T3TCR = 0x00000002; //Reset counter and prescaler
         T3MCR = 0x00000018; 
         T3MR1 = 0x00000101; 
         T3MR0 = 0; 
         T3EMR = 0x00000011; //On match clear MAT0
         T3TCR = 0x00000001; //enable timer
 
         VICVectAddr4 = (unsigned)ISR; //Set the timer ISR vector address
         VICVectCntl4 = 0x0000003b; //Set channel control
         VICIntEnable |= 0x08000000; //Enable the TIMER2 interrupt
         while(1);
}
 
void ISR (void) __irq
{
         T3MR0++;//Increment PWM Duty cycle 
         T3MR0 = T3MR0 & 0x00003FF; //Limit duty cycle
         T3EMR |= 0x00000001; //On match clear MAT0
         T3IR |= 0x00000001; //Clear match 0 interrupt
         VICVectAddr = 0x00000000; //Dummy write to signal end of interrupt
}

Note:
In VIC controller, there is a VICVectAddr register (not VICVectAddr0~31). When a interrupt is triggered (with IRQ), the corresponding ISR's address that is stored in VICVectAddrn will be copied into VICVectAddr by the microcontroller. At the same time, the ARM CPU jump to 0x0000 0018 to execute a branch instruction (the address 0x0000 0018 stores an entry in ARM's interrupt/exception vector table for IRQ. Its the original feature of ARM processor). The branch instruction will branch to the address pointed by VICVectAddr register.
For FIQ, ARM CPU directly execute the instruction stored in 0x0000 001C (it stores an entry for FIQ) without executing branch instruction.

Version 2

In this lab, I used 2 timer interrupts and designed their corresponding interrupt service routines to generate a PWM signal. These two timer interrupt will be triggered depending on the value of the system clock (The system clock signal is generated by a crystal oscillator. Each timer has a timer counter, and I let their timer counters be incremented by 1 at each system clock period). Therefore, if I want to generate a PWM wave with duty cycle 25%, the first timer interrupt will be triggered when its timer counter achieves 1000, and the second timer interrupt will be triggered when its timer counter achieves 250. The first timer interrupt service routine will set the value of an digital output pin to 1, and reset the value of "their" timer counters to be 0. The second timer interrupt service routine will set the digital output pin to 0.
In this lab, I used an oscilloscope to observe and debug the digital output signal. The goal of this lab is learning to read the spec document of the lpc2103 microcontroller, utilizing interrupt, designing ISR, and debugging with oscilloscope.

Version 3

We can generate a PWM wave using timer interrupts. I let the timer interrupt be triggered in a high frequency, and in the timer ISR, I used a static variable to count how many times the ISR is triggered. By setting a digital output port to high or low according to the value of the static variable, I can generate a PWM wave with duty cycle whatever I want. For example, if I want to generate a PWM wave with duty cycle of 25%, then, when the static vairble is 1000, I set the digital output to 1 and set the static variable to 0; when static variable is 250, I set the digital output to 0.
In the end of the ISR, I need to send a signal of end of interrupt to the interrupt vector controller, then it clear the corresponding bit of this ISR in its in-service register.
This version is much less efficient than the first one, because interrupt is triggered every time when the system timer counter is incremented by 1.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License