Needing more I/Os than available on a MCU is a common issue. Sometimes, switching to another higher pin-count device is not an option, especially when you already use a smaller model in high quantities. Whatever are your reasons, one possible choice is to expand the I/O capacity with an external chip. On this article I will show how to add 8 (or more) outputs by using the MSSP module inside of most PIC18 devices. We are going to use a CD4094, a very cheap CMOS serial-in parallel-out 8-bit shift-register that uses only three lines to operate: clock, data and a strobe line.
Interfacing the CD4094 to a PIC18 is very straightforward and can be achieved by a software bit-bang or by using dedicated hardware such as the MSSP module. By using the MSSP module, it is possible to achieve higher transfer speeds and lower CPU usage.
Using the MSSP is also very simple, all you need to do it is the initial setup, drive high the 4094’s strobe line, write the desired data into tje SSPBUF register and after the transmission is completed, drive low the 4094’s strobe line! Further improvements can be done by using the end-of-transmission interrupt available on the MSSP and drive the strobe line low inside the ISR!
The following example demonstrates how to use the PIC18F4520’s MSSP module to drive an external 4094 chip. It continually writes a value into the SSPBUF register which then appears on the outputs of the 4094. This is a very simple example which can be further worked to more complex real-life usage.
#include <p18f4520.h> #include "pic_simb.h" #pragma config OSC = XT, WDT = OFF, MCLRE = ON #pragma config DEBUG = ON, LVP = OFF, PWRT = ON, BOREN = OFF #define _4094_ENABLE PORTCbits.RC0 void MCU_init(void) { TRISC = 0; // all port C pins as outputs SSPSTAT = 0; SSPCON1 = bSSPEN | bSPI_MST_4; // SPI master, clock = FOSC/4 = 1MHz } void main(void) { unsigned char counter, temp; MCU_init(); counter = 0; _4094_ENABLE = 1; while(1) { SSPBUF = counter++; for (temp=200; temp; temp--); } }