Pulse Width Modulation (PWM) is an important function in many embedded designs, since PWM channels make it possible to use the microcontroller's digital outputs to control analog circuits. Many 32-bit microcontrollers are equipped with a set of dedicated PWM channels, or include timer/counter combinations that can also be used as PWM channels, but there aren't always enough to go around. Depending on the situation, getting enough PWM channels may mean adding software-based workarounds to the design.
One of the more common software workarounds, known as "bit-banging," involves using software to set and sample the state of the microcontroller's pins, and using software controls to set parameters like timing, levels, and synchronization so the system can emulate a PWM channel.
Bit-banging may not be the most elegant way to add a PWM channel, but it's a relatively quick, easy, and low-cost solution that has helped many designers meet tight deadlines. The downside, though, is that bit-banging is a CPU-intensive operation that will impact system performance. The software emulation involved can consume a significant amount processing power, since the CPU needs to spend time communicating with the I/O pin, and that can have an impact on the CPU's ability to perform other tasks. Also, the PWM signal that bit-banging produces may be noisier, with more jitter or glitches, especially if the CPU is busy with other tasks when the signal is being generated.
When our design teams created the dual-core Cortex-M4/M0-based LPC4300 series of MCUs, they added a special feature, called the serial GPIO (SGPIO) interface. This unique digital peripheral lets you add up to sixteen 5-bit hardware-based PWM channels to a design -- with very little CPU load -- so you don't have to resort to bit-banging.
The rest of this article looks at the structure of the SGPIO interface and gives an example PWM implementation using the SGPIO.
The SGPIO architecture
Figure 1 gives a block diagram of the SGPIO's basic building block, which is called a slice. Each slice provides the necessary hardware to handle data processing when sending or receiving data. There are a total of 16 SGPIO slices and 16 SGPIO pins in the SGPIO interface.
Figure 1. Block diagram of a single SGPIO slice.
The slice basically consists of a 32-bit FIFO (REG), used to clock data in or out, a shadow register (REG_SS) for staging output data or receiving input data, a 12-bit down counter (COUNT) to generate the shift clock, and an 8-bit down counter (POS) to control the number of bits shifted in or out. The slice's shift clock can be sourced from the SGPIO peripheral clock (SGPIO_CLOCK).
At every SGPIO_CLOCK, the COUNT counts down by one. When COUNT reaches zero, a data bit is shifted in or out of REG and the POS register decrements by one. When the POS register reaches zero, it is reloaded with the value in POS_PRESET and the contents of REG and REG_SS are exchanged.
For an output slice, new data is written to REG_SS, and when the slice is done sending the data in the main buffer, the two buffers are exchanged. For an input slice, new data is clocked in the main buffer, and when the slice is done collecting the data in the main buffer, the two buffers are exchanged.
Each slice connects to an SGPIO pin using a pin mux (multiplexer). The pin mux makes it possible to connect one slice to more than one pin, and to concatenate multiple slices to one SGPIO pin. A given SGPIO slice can be connected to 1, 2, 4, or 8 SGPIO pins, and up to eight slices can be concatenated to input or output through a single SGPIO pin. Having the ability to direct an SGPIO slice to more than one pin can have significant advantages in PCB design, since the I/O ports can be configured for the best possible layout.
To Page 2 >