The code architecture is organized into three areas, Initialization, State Machine, and Analog-to-Digital Converter (ADC) Interrupt Routine. In the next few sections, we will go into the details of these areas.
Initialization
A number of functions are called to initialize the main resources and peripherals of the chip. Specifically:
- CPU is initialized
- I/O ports are initialized
- Timer used to generate the local tick on which many functions are synchronized is initialized
- Pulse Width Modulation (PWM) 1 peripheral is initialized
- ADC pair 0 is initialized
- Variables needed by the state machine for the buck converter 1 are initialized
- PWM 2 peripheral is initialized
- ADC pair 1 is initialized
- Variables needed by the state machine for the buck converter 2 are initialized
State Machine
In the state machine section, the main loop is an endless loop that continuously calls:
- The function that tests if any button on the board has been pressed
- The function that manages the state machine of buck 1
- The function that manages the state machine of buck 2
ADC Interrupt
All the tasks performed by the routine are shown below. The routine essentially reads the new voltage value and computes the new duty cycle value.
The following slide show demonstrates the details of the ADC interrupt operations. Click on each element for the details of the operation.
Context Save
The W registers used in the local code are pushed into the stack to preserve their value at the output of the Interrupt Service Routine (ISR). Please be careful in using the instruction push.s, as there is only one level of shadow registers that can be used to momentarily store the registers. If a second interrupt uses push.s, then the first instance will be lost.
Init Pointers
Register W8 is used to point to the Proportional-Integral-Derivative (PID) coefficients buffer. W10 is used to point to the input error values buffer. The instructions initialize the two pointers to the first location of the two buffers.
Read New Voltage Value
This routine is executed when the ADC has completed the conversion of the input channel. ADCBUF1 contains the new converted value (output voltage).
Voltage Scaling
The output voltage is multiplied by the reverse of the resistor divider to increase the dynamic range.
Voltage Error Computation
The error is defined as the reference voltage less than the output voltage (from the ADC).
PID Computation
This is the core of the operation of the ISR. The PID output is computed. The result (new active period of the PWM signal) is stored in W0.
Update Voltage Error Buffer
The new error is stored in the first entry of the error buffer.
Check Duty Limits
The newly computed active period must be within meaningful limits. This piece of code tests if they are indeed within the limits, otherwise the MIN or MAX value is used. This piece of code may be considered the digital counterpart of anti-wind-up.
Update Duty Cycle
The new value is stored in the duty cycle register so that it will be used at the next PWM period.
Context Restore
Before leaving the ISR, the original values of the used W registers are popped from the stack and restored.