Let's Make Robots! | RobotShop

Explaining the 7 segment display and 74HC595 shift register.

Shows digits on a display using a shift register(74HC595) ,a PIC and c code
7ss.c3.16 KB

I recently killed an old cd player, and one of the parts i salvaged from it was a dual digit 7 segment display. My plan is to make the Pic send data to the shift register(74hc595) to light up the 7 segment display.The reason for trying this is because i want to learn how the 595, and display work as the 595 can be useful in many areas since it can "expand" the pins on your microchip.

Jinx told me to write about it so others can learn something from my mistakes :) so here we go . I will only be using 3 pins to control 8 pins on the 7 segment display.After some reading and testing i have figured out how the display works.I also suggest reading the datasheet for the 74HC595 if you want to get a deeper understanding for how it works.

Just so you know what segments i am talking about:

First of all i need to find out which pin does what on the display. I have 10 pins on mine and its a 2 digit display, although i only want to use one digit for now.

After reading about it it seems like they are either common anode or common cathode. To figure it all out i just started by putting a 450ohm resistor from Ground on the breadboard to one of the pins then trying to light up a segment by putting a cable from +5v to one of the other legs. and i tried this till one segment lit up. But since i only could get one segment to light up i figured it must be common anode, so i switched polarity(Moving the resistor from GND to +5v) and now i could get different segments to light up by grounding different pins. Then i mapped which pin lit which segment.

As i said ,the display i have is common anode, meaning all the anodes of the digit is tied together ,meaning that i have one leg going to VCC(+5v)  and each of the other legs have a 450ohm resistor on them ,different segments are being lit by sinking the current on the leg corresponding to the segment.




And this is the shift register chip i will use . Its a serial in parallel out type of chip.


So as you can see we have Q0-Q7, thats the 8 output pins we will use to control the display.

The ST_CP is the Storage register Clock and SH_CP is the Shift Register Clock both are positive edge triggered.

DS is the pin that we send the serial data to and then when we are done the serial data will be output to pins Q0-Q7.

OE is output enable and when the output-enable (OE) input is high, the outputs are in the high-impedance state.

MR is Master Reset and it will reset when low so we tie it to the VCC pin.

Now we need to connect the chip to the display. Here we go.
A <-> Q0, B <-> Q1, etc , etc all the way to Q7.

ST_CP <-> PORTC1, SH_CP <-> PORTC0 , DS <-> PORTC2, OE(pin 13) <-> GND, MR <-> VCC and
just to be extra clear here i have routed the GND pin to the same ground as the PIC and the VCC pin to Vcc of
the chip(+5v).

Pin no 9(labelled Q7') is used for daisychaining the chip so just leave that one for now.

Now we have something looking like this.

Or as it looks IRL

(Dont forget to check the red wire....)

Ok so first lets have a look at how the chip works.This is a timing diagram.

The 74HC595 has an 8-bit storage register and an 8-bit shift register.

As you can see here we have to set pin ST_CP low to enable writing to the storage register.When we set it high it writes the 8 bits in storage to the shift register, but for now its low. Then we set the SH_CP pin low and when we set it high it will store the state of pin DS is in the storage register.

To write 11000011 to the shift register we set ST_CP low ,SH_CP low,DS high,SH_CP high,SH_CP low,DS high,SH_CP high,SH_CP low,DS low,SH_CP high,SH_CP low,DS low,SH_CP high,SH_CP low,DS low,SH_CP high,SH_CP low,DS low,SH_CP high,SH_CP low,DS high,SH_CP high,SH_CP low,DS high,SH_CP high and now all the bits are stored in the storage register now to write it to the Shift register we set ST_CP high.Until we set ST_CP high we just update the storage, its not until we set it high we see the changes.

Most of the times you would use some kind of loop to do all this so you will only have to worry about sending the right data to it.


Ok time to try and move some bits over to this chip. I'm using Mplabx for this with the Hi-tech c lite compiler, both are free and works on mac.

For now i have just posted the code here.I will go through the code step by step whenever i have time and if there is a need for it.


And after loading this up to the pic we have a little counter going from 0 to 9 over and over and over and over again.I will soon add some videos to the post here. I just wanted to share what i have done so far with you.

Thanks for reading :) / Mixmar


// ***************************************************************************
//  File Name    : 7ss.c
//  Version      : 1.2
//  Description  : 7 segment display with 74HC595
//  Author       : Mikael Frisk(Mixmar on LMR)
//  Target       : Pic 16f690 on breadboard
//  Compiler     : HITECH PICC-Lite Version 9.83
//  IDE          : Microchip MPLAB X IDE
//  Programmer   : PICKit2
//  Last Updated : 10 Nov 2012
// ***************************************************************************
#include <pic.h>
/*   PIC Configuration Bit:
**   INTIO/FOSC_INTRCIO     - Using Internal RC No Clock
**   WDTDIS/WDTE_OFF   - Wacthdog Timer Disable
**   PWRTEN/PWRTE_ON    - Power Up Timer Enable
**   MCLREN/MCLRE_ON    - Master Clear Enable
**   UNPROTECT/CP_OFF - Code Un-Protect
**   UNPROTECT/CPD_OFF - Data EEPROM Read Un-Protect
**   BORDIS/BOREN_OFF    - Brown Out Detect Disable
**   IESODIS/IESO_OFF   - Internal External Switch Over Mode Disable
**   FCMDIS/FCMEN_OFF    - Monitor Clock Fail Safe Disable

#define FOSC 8000000L // Using Internal Clock of 8 Mhz
#define DS RC2 //data on pin C2
#define ST_CP RC1 //storage register clock input on pin C1
#define SH_CP RC0 //shift register clock input on pin C0
#define testbit(data,bitno) ((data>>bitno)&0x01)

unsigned int i,x,ty;
unsigned char Digit[10] = {0x03,0x9F,0x25,0x0D,0x99,0x49,0x41,0x1F,0x01,0x09}; //Array containing all the "digits"

**0x03 hex = 0 dec = 0000 0011 bin
**0x9F hex = 1 dec = 1001 1111 bin
**0x25 hex = 2 dec = 0010 0101 bin
**0x0D hex = 3 dec = 0000 1101 bin
**0x99 hex = 4 dec = 1001 1001 bin
**0x49 hex = 5 dec = 0100 1001 bin
**0x41 hex = 6 dec = 0100 0001 bin
**0x1F hex = 7 dec = 0001 1111 bin
**0x01 hex = 8 dec = 0000 0001 bin
**0x09 hex = 9 dec = 0000 1001 bin

void init(void)
  OSCCON=0x70;         // Select 8 Mhz internal clock
  TRISC = 0x00;        // Set all as Output
  ANSEL = 0;
  ANSELH = 0;

void dirty_delay(int count){
    for(int s=0;s<count;s++){
        for(int st=0;st<count;st++){
    }//only for a bit of rough and ugly delay
void write_digit(int dig_num){

       ST_CP=0; //same as RC1=0; enable write to shift register
       SH_CP=0; //same as RC0=0; enable write to bit
       //this is the loop that sends the data bit by bit to the 74HC595 since its 8 bits to send we loop it 8 times.
       for (int i=0;i<8;i++){
           // this sends the bit to the  register and "dig_num" is the digit we want to display from the array Digit[].
           // testbit(Digit[dig_num],i) takes bit i from the char in the array "Digit[dig_num]" and puts that on pin DS
           // which is our data pin.
           DS=testbit(Digit[dig_num],i); //if you have common cathode display use "DS=testbit(Digit[dig_num],i)^1"
           SH_CP=1; //same as RC1=1; write bit
           SH_CP=0;  //same as RC1=0;move on to next bit
       ST_CP=1; //same as RC0=1; write the new bits to the register.
void main(void){
/* EOF: 7ss.c */

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

you can run two stepers from that idea or 4 motors , i could go on but get what im driving at

I also noticed that and now i see all kind of uses for it. i have a list of "must try's" here. :)

I have posted some new code to the project now. Less flow oriented than before.