3 digit 7 segment interfacing with 4094 shift register using hardware spi module

We will explore the methods of using the built in SPI module in PIC16F887 Microcontroller. According to the datasheet of the microcontroller there is built in SPI module available in the microcontroller which could make life lot of easier when it comes to the SPI Master Slave communication. There is Master Synchronous Serial Port (MSSP) module which support all 4 modes. All of these modes are explained in the following diagram taken from this official SPI getting started guide.

CD4094 Shift Registers

4094 is one of the most popular shift register after the 74HC595 Shift registers. The communication protocol is same in both of the shift registers which is SPI protocol. We already demonstrated software based shift register 7 segment example with Arduino in one of our previous articles. Here is internal structure of the shift register from the datasheet.

4094 shift register internal block diagram
cd4094 block diagram

PIC SPI example C Code PIC CCS Compiler

Let’s first of all see a very basic example of using the MSSP module in PIC CCS Compiler and create a very basic SPI example c code. This example will just write a counter on the SPI module and increment that counter.

According to the PIC CCS compiler documentation this is what they says under the SPI Section of the PIC microcontrollers.

SPI™ is a fluid standard for 3 or 4 wire, full duplex communications named by Motorola. Most PIC devices support most common SPI™ modes. CCS provides a support library for taking advantage of both hardware and software based SPI™ functionality. For software support, see #USE SPI.

PIC CCS Compiler Documentation
#include<16F887.h>
#device *=16
#fuses HS,WDT,NOPROTECT,NOLVP
#use delay(clock=8000000)

#define _4094_ENABLE    PIN_C0

void main(){
 unsigned int8 counter, temp;
   setup_comparator(NC_NC_NC_NC); 
   setup_ADC(ADC_off);                        
   setup_ADC_ports(no_analogs); 
   
   setup_CCP1(CCP_off); 
   setup_CCP2(CCP_off); 
   setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16);

   counter = 0;
   output_high(_4094_ENABLE);
    //_4094_ENABLE = 1;
   
   while(True){
      output_low(_4094_ENABLE);
      counter++;
      if(counter>99)counter=0;
      spi_write(counter);
      delay_us(50);
      output_high(_4094_ENABLE);
      output_low(_4094_ENABLE);
      delay_ms(200);
   }

}
Code language: Arduino (arduino)

Here is the proteus simulation results of the above c code.

PIC SPI 4094 Shift Register 7 segment interfacing C Code

Here is the further extended version of the above code where we interfaced three 7 segments and drive a up counter with it. Which is pretty simple once we created a seperate function to update the 4094 shift registers. Also we created a constant array of seven segment codes.

#include<16F887.h>
#device *=16
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=8000000)

#define _4094_Strobe    PIN_C0
#define strobe PIN_C0

const unsigned int8 segChar[]={
  0b00111111,  //0
  0b00000110,  //1
  0b01011011,  //2
  0b01001111,  //3
  0b01100110,  //4
  0b01101101,  //5
  0b01111101,  //6
  0b00000111,  //7
  0b01111111,  //8
  0b01101111,  //9
  0b00000000,  //10
  0b01011000,  //11,-c
};


void sendTo4094(int16 value, int8 num_of_digits){
int8 i;
    unsigned char digit1=0;
    
      
    // Iterate through digits in reverse order (least significant first)
    for (i=0;i<num_of_digits;i++) {
        // Extract the current digit using modulo and division
        
        digit1=value%10;
        output_bit(strobe,0);
        // Send the segment pattern to the corresponding shift register
        spi_write(segChar[digit1]);
        delay_us(5);
        output_bit(strobe,1);
        output_bit(strobe,0);
        delay_us(5);
        value /=10;
       
    }
   
     
 
}


unsigned int8 counter;
void main(){
 
   setup_comparator(NC_NC_NC_NC); 
   setup_ADC(ADC_off);                        
   setup_ADC_ports(no_analogs); 
   setup_CCP1(CCP_off); 
   setup_CCP2(CCP_off); 
   setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16);

   counter = 0;
   output_high(_4094_Strobe);
    //_4094_ENABLE = 1;
   
   while(True){
   
      output_low(_4094_Strobe);
      counter++;
      if(counter>99)counter=0;
      sendTo4094(counter,3);
      output_b(counter);
      delay_ms(500);
   }

}
Code language: Arduino (arduino)
PIC SPI 4094 7 segment interfacing 3 digit up counter proteus simulation

Further Readings

By Abdul Rehman

My name is Abdul Rehman and I love to do Reasearch in Embedded Systems, Artificial Intelligence, Computer Vision and Engineering related fields. With 10+ years of experience in Research and Development field in Embedded systems I touched lot of technologies including Web development, and Mobile Application development. Now with the help of Social Presence, I like to share my knowledge and to document everything I learned and still learning.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.