Interfacing 595 Shift Register with 7-Segment

cancel
Showing results for 
Search instead for 
Did you mean: 

Interfacing 595 Shift Register with 7-Segment

552 Views
LinkyPwns
Contributor I

Hello,

 

I am trying to interface a 595 shift register to drive a 7 segment display as part of my groups senior project.  Our goal is to cascade three shift registers together to make a 3 digit display.  We are going to take body measurements for heartrate and body temperature (and time permitting blood pressure) and display them on the 7 segments.  This means that we will have to drive four, three digit displays.  Is it possible to drive up to four displays using what I have with the dragon board? I have been working on some code for it but am very unsure of the direction I should be taking.  I have been studying the SPI port because that seems to be the way to drive it.  I am using the MC9S12DG256, hcs912 based board.  Here is the code from my main program:

 

 

/****************************************************************
*
*    Senior Project
*    Interfacing 7 segment display
*
****************************************************************/
#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */
#include "delays.h"
#include "spi0util.h"
void set24MHzClock( void );
void delay( void );
void openspi0(void);
void main(void) 
{
  char i;
  unsigned char disp_tab[8][2] = 
        {{0x80,0x7F},{0x40,0x70},{0x20,0x5F},{0x10,0x5B},
         {0x08,0x33},{0x04,0x79},{0x02,0x6D},{0x01,0x30}};
  set24MHzClock( );
  openspi0();   // configure the SPI0 module
 
 while( 1 )
 {
            
    
     DDRK |= 0x40; // configure pin PK7 as output
     while(1) 
     {
         for (i = 0; i < 8; i++) 
         {
             putcspi0(disp_tab[i][0]);  // send out digit select value
             putcspi0(disp_tab[i][1]);  // send out segment pattern 
             PORTK &= ~0x40;              // load value into latch of 74HC595s
             PORTK |= 0x40;               // " 
             delay1_6ms();             // display a digit for 1 ms
         }
     }
   }
 
 
}
/*---------------------------------------------------------------------------
- set24MHzClock
-
- Sets up phase-locked-loop and clock source, etc., for 24 MHz operation
-
- OSC = oscillator clock frequency = 8 MHz
- PLLCLK = Phase-Locked-Loop Clock frequency, which we want to be 24 MHz
- According to the Clock and Reset Generation (CRG) documentation the
-  formula for the PLLCLK based on OSC is:
- PLLCLK = OSC X 2 X (SYNR + 1) / (REFDV + 1)
-OSC (8MHz) must be multiplied by 6 to get 24 MHz, so select values
-for SYNR & REFDV so that (SYNR + 1) / (REFDV + 1) = 3/1 = 3
-This code uses SYNR = 1 & REFDV = 0
----------------------------------------------------------------------------*/
void set24MHzClock(void)
{
     CLKSEL = 0;    // Use crystal oscillator for E clock
     PLLCTL = 0;    // PLL off
     SYNR   = 2;    // Set (SYNR + 1) / (REFDV) = 3 ...
     REFDV  = 0;    // ... see equation in prologue 
     PLLCTL = 0x40; // PLL on
     while( !( CRGFLG & 8) )
     { }            // Wait for lock-up
     CLKSEL = 0x80; // Switch to PLL for system clock
}
/*---------------------------------------------------------------------------
- openspi0
-
----------------------------------------------------------------------------*/
void openspi0(void)
{
     SPI0BR  = 0;    // set baud rate to 12 MHz
     SPI0CR1 = 0x50; // disable SPI interrupt, enable SPI, SCK idle low, shift
                     //   data on rising edge, shift data msb first
     SPI0CR2 = 0x02; // disable bidirection mode, disable SPI in wait mode
     WOMS    = 0;    // enable Port S pull up
}

 

I have included a zipped file with all my work including all my functions, datasheets for the shift register and 7 segment display.  Please take a look, right now I have no guidance software wise on how to do this and will greatly appreciate any help that I can get.

Labels (1)
0 Kudos
1 Reply

34 Views
bigmac
Specialist III

Hello, and welcome to the forum.

 

Firstly, your choice of a large format, 7-segment LED display type will create considerable interface difficulties, to the extent that you would need to use special high voltage interface devices, in addition to the shift registers.  This is because the displays you have chosen have four series connected diodes for each segment, resulting in a maximum voltage drop requirement of 10 volts (8.4 volts typical).  The supply voltage to these displays will need to be considerably greater than the maximum drop, especially if using series resistors  to limit segment current.

 

To simplify the college project, I suggest that you use a smaller LED display type, with only a single LED per segment, so that a 5 volt supply may be used for the display.  If directly driving each segment from the 595 output, you would need to limit to about 5 mA per segment using a series resistor for each segment.

 

Since you would need a separate 595 device for each display, making a total of 12 packages, and 96 resistors, you may also wish to consider other approaches that result in less additional hardware.  Special multiplexed LED driver packages are available.  One that comes to mind is the Maxim MAX7219/MAX7221 type.  Each package is capable of handling up to eight digits, and is SPI compatible.  You would need two packages for the current project, and a total of two resistors to set the segment current.

 

Should you decide to stay with using the 595 devices, you will need to decide whether you handle the update data for twelve digits as a single 12-byte sequence, or as four separate 3-byte sequences (i.e. updating one 3-digit display at a time).  In the first case you would need a single strobe output to pin 12 of all packages, connected in parallel.  For the second alternative, there would need to be a separate strobe output to each 3-digit group.  The strobe pulse(s) would be generated by your code at the completion of each data sequence.

 

I am unclear as to the operation of your disp_tab[][] two-dimensional array.  Are the 595 connections to each 7-segment display identical for each digit, or do the connections differ from digit to digit?  Do the connections for each 3-digit display follow a simiar pattern?  I might have expected one of the array dimensions to have a size of at least ten, to provide an index to all the numeric characters.  You will likely also need to define a blank display state, and maybe you will also need to handle a limited range of alphabetic characters, or other symbols.  These would require further positions within the table.  I would assume that the DP state would be handled from outside the table.

 

For example, if there happened to be identical 595 connections to each digit, and you had four separate sequences of three digits, I might have expected a single dimension array to reflect the output pattern for each numeral.  You would then successively send the output pattern corresponding to each of the three digits, either LSD or MSD first, depending on the 595 daisy-chaining sequence.  Finally you would generate a short strobe pulse to update the output latches.

 

Regards,

Mac

 

0 Kudos