The PWM is able to generate pulses on 4 channels independantly. The period, duty-cycle, polarity and dead-time can be configured. The channels are double buffered to prevent an unexpected wave form.
Clock - The peripheral clock needs to be enabled in the PMC. PWM uses the main clock as its clock source. Clock division can be set in the REG_PWM_CLK register. *note* This clock divisor is different than the clock divisor found in REG_PWM_CMR#. REG_PWM_CLK is the clock for the peripheral and REG_PWM_CMR# is the clock for the channel. ie: REG_PWM_CMR0 is the clock for channel 0.
As with any peripheral, we must take control of the pins from GPIO and give it to the peripheral.
For the SG90 Micro Servo, it expects a 20ms period where 0 degrees = 1ms duty and 180 = 2ms and the dead time is 5us.
Channel - Enable the channel you want to output a signal on in the REG_PWM_ENA register. To disable, set the appropriate bit in REG_PWM_DIS. The status register bits, REG_PWM_SR, are set if the channel is enabled and 0 if disabled.
Period - Set the period of the signal in REG_PWM_CPRD#, where # is the channel number you wish to update. ie: channel 0 is REG_PWM_CPRD0. The period can be set using REG_PWM_CPRDUPD#. This register acts as a double buffer to the REG_PWM_CPRD# value. Using the formula (X * CPRDUPD / fperipheral clock) we can calculate the period that want.
period = (X * CPRD)/Fperipheral clock: where period is our desired time in seconds, X is MCK_DIV_X that is in REG_PWM_CMR#, Fperipheral is REG_PWM_CLK.
REG_PWM_CPRD# can be solved for:
8*CPRD/20M = 0.02s period --> CPRD = 50,000
Duty Cycle - The value in the duty cycle register is between 0 and the CPRD value for the channel. The same formula used before can be used to calculate this value.
8*CDTY/20M = 0.001s --> CDTY = 2500
Dead Time - The dead time register can be calculated using the following:
20,000,000/8*5us = 12.5~13 REG_PWM_DT0 = 13
Polarity - The SG90 servo wants high first, so we will set the bit CPOL in CMR0 Register: REG_PWM_CMR0 |= PWM_CMR_CPOL