TIMER_A: Producing PWM using timer32

Suppose we had a 3 MHz system clock, and we wanted to light a blue LED at 40% of its maximum brightness. In order to achieve the dimming effect, a reasonable period to use for the signal driving the LED would be 1 millisecond. Multiplying the period by the duty cycle will give us the amount of time the LED should be on (and subtracting this value from the period will tell us how long the LED should be off). So the LED should be on for 0.4 milliseconds and off for 0.6 milliseconds. However, these times are in milliseconds; the Timer32 module needs to be configured using counter cycles. For this example, we will use a prescaler of 1. Applying the formula to convert from seconds to load cycles gives us 1200 cycles for time on and 1800 cycles for time off.

In order to generate the PWM waveform, we will have to switch between active-high and active-low while keeping track of how much time has passed. To do this, we can start by setting the output high and then starting a one-shot timer with a load value of 1200 (the time the LED is on). Then, we check to see if the timer has expired. Upon expiration, we set the output low and then start a timer with a load value of 1800 (the time the LED is off). Then, we check if that timer has expired, and if it has, we start the process all over again by setting the output high and starting another timer. A simple but effective process. However, it has its pitfalls. 

This loop of switching the output between on and off requires that the code checks to see if the timer has expired. What if the timer has expired, but the processor makes the check one second after the expiration? This could happen if there is a large amount of code in between every line where you check the timer’s expiration status. The primary consequence of this happening is that the LED would be on for a longer time than it should be (and off for longer than intended, too), thus increasing the period and possibly ruining the dimming effect. This particular implementation of PWM is susceptible to blocking functions, which are functions that can prevent other tasks within the code from being performed until the function is terminated. Fortunately, we can circumvent this issue by using a different module to accomplish the task: Timer_A.