News:

Let's find out together what makes a PIC Tick!

Main Menu

LED indicator for 74HC595

Started by tolyan249, Today at 03:14 AM

Previous topic - Next topic

tolyan249

There's this LED indicator based on the 74HC595 — has anyone worked with them?
I just don't know how to work with them.
I have a PIC16F628; they say you can use it via SPI.
Maybe someone has some experience with it?
Thank you.

ken_k

The chips are 8 bit serial input shift registers.The data sheet explains how they work.
My guess is you will clock in a bit for each 7 segments and then enable the output.
I did something similar years ago and it worked very well.

ken_k

Here is a link to the PCB.

https://aqtronic.com/product/static-drive-3-bit-7-segment-led-display-module-with-74hc595/

The link below shows how the displays may be connected to the IC. Although written for Arduino the description may help you.

https://wiki.geeetech.com/index.php/Arduino_7_segment_LED_timer_with_74HC595_module

A friend of mine made a very long PCB with a lot of 7 segment displays on it (side by side) with a 74HC595 for each display. If a certain number of 7 seg displays were required the PCB could be broken off at the required spot.
 
These displays don't strobe so they look good when taking a video of them.

I guess you will have to write your own code.
I once drive 45 relays using this method using similar IC's. I simply bit bashed three pins to the relay PCB.
 


Frizie

Very easy to use with Positron's SHOUT instruction ;D
Ohm sweet Ohm | www.picbasic.nl

tolyan249

Thank you all for your help; I'll try to write a program for it.

Pepe

demo proteus

;-------------------------------------------------------------------------------
;**** Added by Fuse Configurator ****
; Use the Fuse Configurator plug-in to change these settings

Device = 16F648A

Config FOSC_HS, WDTE_OFF, PWRTE_OFF, MCLRE_OFF, BOREN_ON, LVP_OFF, CPD_OFF, CP_OFF

;**** End of Fuse Configurator Settings ****
;-------------------------------------------------------------------------------


Declare Xtal = 16
Declare Optimiser_Level = 3
Declare Reminders Off
Declare Watchdog = Off
Declare Create_Coff On
'-----------------------------------------
' Pines
'-----------------------------------------
Symbol DATA_PIN  = PORTB.3
Symbol CLOCK_PIN = PORTB.4
Symbol LATCH_PIN = PORTB.5

'-----------------------------------------
' Variables
'-----------------------------------------
Dim Numero As Word
Dim Centenas As Byte
Dim Decenas As Byte
Dim Unidades As Byte

Dim SegDisp[10] As Byte

'-----------------------------------------
' Tabla de segmentos
'-----------------------------------------
SegDisp[0] = 3
SegDisp[1] = 159
SegDisp[2] = 37
SegDisp[3] = 13
SegDisp[4] = 153
SegDisp[5] = 73
SegDisp[6] = 65
SegDisp[7] = 27
SegDisp[8] = 1
SegDisp[9] = 9

'-----------------------------------------
' Configuración
'-----------------------------------------
TRISB = %00000000
Clear PORTB

'-----------------------------------------
' Programa
'-----------------------------------------
Do

    For Numero = 0 To 999

        Centenas = Dig Numero,2
        Decenas = Dig Numero,1
        Unidades = Dig Numero,0

        LATCH_PIN = 0

        SHOut  DATA_PIN, CLOCK_PIN,0,[ SegDisp[Unidades] ]
        SHOut  DATA_PIN, CLOCK_PIN,0,[ SegDisp[Decenas] ]
        SHOut  DATA_PIN, CLOCK_PIN,0,[ SegDisp[Centenas] ]

        LATCH_PIN = 1

        DelayMS 200

    Next Numero

    DelayMS 200

    For Numero = 999 To 0 Step -1

        Centenas = Dig Numero,2
        Decenas = Dig Numero,1
        Unidades = Dig Numero,0

        LATCH_PIN = 0

        HRSOut 0, DATA_PIN, CLOCK_PIN, SegDisp[Unidades]
        HRSOut 0, DATA_PIN, CLOCK_PIN, SegDisp[Decenas]
        HRSOut 0, DATA_PIN, CLOCK_PIN, SegDisp[Centenas]

        LATCH_PIN = 1

        DelayMS 200

    Next Numero

    DelayMS 200

Loop

top204

You beat me too it Pepe, and nice coding.

The initial question intrigued me, and I have seen some C code that is rather cumbersome (to say the least), and actually not working correctly, so I created some code myself for the task, using a PIC16F628A device running at 20MHz, but it will operate on any 14-bit core (enhanced or not enhanced) device, or 18F device.

It's been a while since I created code for an old 14-bit core device, so it ticked the nostalgia box as well, but they are "very" inflexible and "very" out of date now, so it will be a rare occurance. :-)

The code below is for five, Common Anode or Common Cathode, seven segment LEDs, displaying a 16-bit value passed to the 'Display' procedure. It has zero blanking implemented as well:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Interface to 5 Common Anode seven segment LED displays using 74HC595 shift registers.
'
' Written by Les Johnson for the Positron8 BASIC compiler.
' https://sites.google.com/view/rosetta-tech/positron-compilers-experimenters-notebook.
'
    Device = 16F628A                                                                        ' Tell the compiler what device to compile for
    Declare Xtal = 20                                                                       ' Tell the compiler what frequency the device is operating at (in MHz)
    Declare Auto_Variable_Bank_Cross = On                                                   ' Make sure all multi-byte variables remain within a single RAM bank
'
' Setup the USART for any debugging required
'
    Declare Hserial_Baud  = 9600
    Declare HSerout_Pin   = PORTB.2
    Declare HSerin_Pin    = PORTB.1
    Declare Hserial_Clear = On                                                              ' Enable Error clearing on received bytes
'
' Setup the pins to the 74HC595 Shift Registers
'
$define SR_Latch_Pin PORTB.4                                                                ' Connects to pin 12 of the 74595 (named ST_CP or RCLK), and is the Storage Latch input
$define SR_Clock_Pin PORTB.5                                                                ' Connects to pin 11 of the 74595 (named SH_CP or SRCLK), and is the Clock input
$define SR_Data_Pin  PORTB.3                                                                ' Connects to pin 14 of the 74595 (named DS or SER), and is the Serial Data input

'$define CC_Display                                                                         ' Tell the program to use the lookup values for Common Cathode displays (comment out for Common Anode)
'
' Create variables for the demo here
'
    Dim wCountValue As Word                                                                 ' Holds the main count value

'---------------------------------------------------------------------------------------------------------
' The main program starts here
' Display an incrementing value on the seven segment displays
'
Main:
    Setup()                                                                                 ' Setup the program and any peripherals
    Do                                                                                      ' Create a loop
        For wCountValue = 1 To 65535 Step 2                                                 ' Create a counting loop
            Display(wCountValue)                                                            ' Display the value on the seven segment displays
            DelayMs 100                                                                     ' A delay, so that the LEDs are not a blur
        Next                                                                                ' Close the counting loop
    Loop                                                                                    ' Loop forever

'---------------------------------------------------------------------------------------------------------
' Display a 16-bit value on the seven segment LEDs
' Input     : pValue holds the value to display on the LEDs
' Output    : None
' Notes     : The routine has zero blanking for the value displayed
'
Proc Display(pValue As Word)
    Dim Digit10000s As Byte = Dig(pValue, 4)                                                ' Holds the fifth digit value (to the right of the 16-bit value)
    Dim Digit1000s  As Byte = Dig(pValue, 3)                                                ' Holds the fourth digit value (to the right of the 16-bit value)
    Dim Digit100s   As Byte = Dig(pValue, 2)                                                ' Holds the third digit value (to the right of the 16-bit value)
    Dim Digit10s    As Byte = Dig(pValue, 1)                                                ' Holds the second digit value (to the right of the 16-bit value)
    Dim Digit1s     As Byte = Dig(pValue, 0)                                                ' Holds the first digit value (to the right of the 16-bit value)
$ifdef CC_Display                                                                           ' Are the LED displays Common Cathode?
    Symbol cBlankVal = 0                                                                    ' Yes. So a 0 blanks them
$else                                                                                       ' Otherwise... They are Common Anode displays...
    Symbol cBlankVal = 255                                                                  ' So 255 blanks them
$endif
'
' Convert the digit values from pValue
'
    Digit1s     = FindSegments(Digit1s)                                                     ' \
    Digit10s    = FindSegments(Digit10s)                                                    ' |
    Digit100s   = FindSegments(Digit100s)                                                   ' | Convert the digits into their 7 segment patterns
    Digit1000s  = FindSegments(Digit1000s)                                                  ' |
    Digit10000s = FindSegments(Digit10000s)                                                 ' /

    PinClear SR_Latch_Pin                                                                   ' Clear the latch, so differences are not seen
    If pValue < 10 Then                                                                     ' Is the value a single digit?
        Digit10s    = cBlankVal                                                             ' Yes. So blank out the second digit
        Digit100s   = cBlankVal                                                             ' Blank out the third digit
        Digit1000s  = cBlankVal                                                             ' Blank out the fourth digit
        Digit10000s = cBlankVal                                                             ' Blank out the fifth digit
    ElseIf pValue < 100 Then                                                                ' Is the value 2 digits?
        Digit100s   = cBlankVal                                                             ' Yes. So blank out the third digit
        Digit1000s  = cBlankVal                                                             ' Blank out the fourth digit
        Digit10000s = cBlankVal                                                             ' Blank out the fifth digit
    ElseIf pValue < 1000 Then                                                               ' Is the value 3 digits?
        Digit1000s  = cBlankVal                                                             ' Yes. So blank out the fourth digit
        Digit10000s = cBlankVal                                                             ' Blank out the fifth digit
    ElseIf pValue < 10000 Then                                                              ' Is the value 4 digits?
        Digit10000s = cBlankVal                                                             ' Yes. So blank out the fifth digit
    EndIf
    SR_Write(Digit1s)                                                                       ' \
    SR_Write(Digit10s)                                                                      ' |
    SR_Write(Digit100s)                                                                     ' | Write the five digits to the shift registers
    SR_Write(Digit1000s)                                                                    ' |
    SR_Write(Digit10000s)                                                                   ' /
    PinSet SR_Latch_Pin                                                                     ' Latch the values on the outputs of the shift registers
EndProc

'---------------------------------------------------------------------------------------------------------
' Lookup the segment data for LED displays
' Input     : pValue holds the value to lookup
' Output    : Returns the segment value for a display
' Notes     : If the $define CC_Display is uncommented, the table is for Common Cathode displays, else it is for Common Anode displays.
'           : It is much more efficient in a procedure, than using multiple LookUp commands.
'
Proc FindSegments(pValue As Byte), Byte
$ifdef CC_Display                                                                           ' Are the LED displays Common Cathode?
    Result = Lookup pValue,[%11111100, %01100000, %11011010, %11110010, %01100110, %10110110, %10111110, %11100100, %11111110, %11110110]
$else                                                                                       ' Otherwise... They are Common Anode displays...
    Result = Lookup pValue,[%00000011, %10011111, %00100101, %00001101, %10011001, %01001001, %01000001, %00011011, %00000001, %00001001]
$endif
EndProc

'---------------------------------------------------------------------------------------------------------
' Write a byte to the shift register
' Input     : pData holds the 8-bit data to send
' Output    : None
' Notes     : Sends Most Significant Bit first
'           : Alter the DelayUS values for a faster or slower write
'
Proc SR_Write(pData As Byte)
    Dim bBits As Byte Access

    PinClear SR_Clock_Pin
    For bBits = 7 DownTo 0                                                                  ' Create a loop to send out the bits
        Ror pData                                                                           ' Rotate the Most Significant Bit into the Carry flag
        PinClear SR_Data_Pin                                                                ' \
        If STATUSbits_C = 1 Then                                                            ' | Transfer the state of the Carry flag to the Data pin
            PinSet SR_Data_Pin                                                              ' |
        EndIf                                                                               ' /
        DelayUs 7                                                                           ' \
        PinSet SR_Clock_Pin                                                                 ' | Clock the bit out
        DelayUs 7                                                                           ' |
        PinClear SR_Clock_Pin                                                               ' /
    Next
EndProc

'---------------------------------------------------------------------------------------------------------
' Setup the program and any peripherals
' Input     : None
' Output    : None
' Notes     : None
'
Proc Setup()
    PinLow SR_Latch_Pin                                                                     ' Make the shift register's Latch pin an output low
    PinLow SR_Clock_Pin                                                                     ' Make the shift register's Clock pin an output low
    PinLow SR_Data_Pin                                                                      ' Make the shift register's Data pin an output low
EndProc

'---------------------------------------------------------------------------------------------------------
' Setup the config fuses for the PIC16F628 device, to operate with an external crystal
'
    Config HS_OSC, WDT_OFF, PWRTE_ON, BODEN_OFF, LVP_OFF, CP_OFF, MCLRE_ON, DATA_CP_OFF

To reduce it to 3 LED displays is simplicity with the commented source code telling the user what is happening within it.

Below is a screenshot of the program operating in Proteus with Common Anode LEDs.

Seven_Segments_74HC595.jpg

The Positron8 source codes, and proteus project files are attached below.

Regards
Les