News:

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

Main Menu

Puzzled with 7 segment code

Started by RGV250, Oct 26, 2021, 11:08 PM

Previous topic - Next topic

RGV250

Hi,
 I have large 7 segment display that I intend to re-purpose, it had a Z80 CPU but the displays are driven by 74HC595 shift registers and ULN 2803 drivers.
I found an example from Les which sort of works , the issue is that it displays garbage. After a bit of investigation work I found the segments were not driven by the same bits so I did a bit of mapping, this is where the issue arises.
This is the defines as per Les's code.
' Individual segment values for a Common Anode 7 segment display (inverted compared to Common Cathode values)
' Original ones in Les's demo
$define Segment_A $FE                           ' The value (bin 11111110) to send to illuminate segment A on the Common Anode display
$define Segment_B $FD                           ' The value (bin 11111101) to send to illuminate segment B on the Common Anode display
$define Segment_C $FB                           ' The value (bin 11111011) to send to illuminate segment C on the Common Anode display
$define Segment_D $F7                           ' The value (bin 11110111) to send to illuminate segment D on the Common Anode display
$define Segment_E $EF                           ' The value (bin 11101111) to send to illuminate segment E on the Common Anode display
$define Segment_F $DF                           ' The value (bin 11011111) to send to illuminate segment F on the Common Anode display
$define Segment_G $BF                           ' The value (bin 10111111) to send to illuminate segment G on the Common Anode display


and this is what they are when I have mapped them out.
' Individual segment values found by trial and error as board not the same as below.
' If I use these values there is no output from the procedure.
'$define Segment_A $20                         ' The value (bin 11111110) to send to illuminate segment A on the Common Anode display
'$define Segment_B $40                         ' The value (bin 11111101) to send to illuminate segment B on the Common Anode display
'$define Segment_C $10                         ' The value (bin 11111011) to send to illuminate segment C on the Common Anode display
'$define Segment_D $01                         ' The value (bin 11110111) to send to illuminate segment D on the Common Anode display
'$define Segment_E $02                         ' The value (bin 11101111) to send to illuminate segment E on the Common Anode display
'$define Segment_F $08                         ' The value (bin 11011111) to send to illuminate segment F on the Common Anode display
'$define Segment_G $04                         ' The value (bin 10111111) to send to illuminate segment G on the Common Anode display

If I run the  code in a VSM it is clear there is no output from the procedure (Build_Displays) with the new values yet it works with the original ones.

Actual code.
    Include "Amicus18.inc"
 
        DelayMS 100
       
        Symbol SHIFT_ENABLE = PORTC.0         ' Output Enable To Pin 13 On 74HC595             
        Symbol SHIFT_LATCH = PORTC.2          ' Data Latch To Pin 12 On 74HC595     
        Symbol SHIFT_CLK = PORTC.3            ' Clock pin To Pin 11 On 74HC595
        Symbol SHIFT_DATA = PORTC.5           ' Data out pin to pin 14 on 74HC595

        SHIFT_ENABLE = 0

        TRISC.0 = 0
        TRISC.2 = 0
        TRISC.3 = 0 
        TRISC.5 = 0       
   
    Dim bOnes       As Byte                    ' The value for the 1st right LED display
    Dim bTens       As Byte                    ' The value for the 2nd right LED display
    Dim bHundreds   As Byte                    ' The value for the 3rd right LED display
    Dim bThousands  As Byte                    ' The value for the 4th right LED display

    Dim TestData As Word                       ' Sample data
       
' Individual segment values found by trial and error as board not the same as below.
' If I use these values there is no output from the procedure.
'$define Segment_A $20                         ' The value (bin 11111110) to send to illuminate segment A on the Common Anode display
'$define Segment_B $40                         ' The value (bin 11111101) to send to illuminate segment B on the Common Anode display
'$define Segment_C $10                         ' The value (bin 11111011) to send to illuminate segment C on the Common Anode display
'$define Segment_D $01                         ' The value (bin 11110111) to send to illuminate segment D on the Common Anode display
'$define Segment_E $02                         ' The value (bin 11101111) to send to illuminate segment E on the Common Anode display
'$define Segment_F $08                         ' The value (bin 11011111) to send to illuminate segment F on the Common Anode display
'$define Segment_G $04                         ' The value (bin 10111111) to send to illuminate segment G on the Common Anode display

' Individual segment values for a Common Anode 7 segment display (inverted compared to Common Cathode values)
' Original ones in Les's demo
$define Segment_A $FE                           ' The value (bin 11111110) to send to illuminate segment A on the Common Anode display
$define Segment_B $FD                           ' The value (bin 11111101) to send to illuminate segment B on the Common Anode display
$define Segment_C $FB                           ' The value (bin 11111011) to send to illuminate segment C on the Common Anode display
$define Segment_D $F7                           ' The value (bin 11110111) to send to illuminate segment D on the Common Anode display
$define Segment_E $EF                           ' The value (bin 11101111) to send to illuminate segment E on the Common Anode display
$define Segment_F $DF                           ' The value (bin 11011111) to send to illuminate segment F on the Common Anode display
$define Segment_G $BF                           ' The value (bin 10111111) to send to illuminate segment G on the Common Anode display

'
' An LED display is formatted like this:
'     A
'   ------
'   |    |
'  F|    |B
'   | G  |
'   ------
'   |    |
'  E|    |C
'   | D  |
'   ------
'
' So each segment has a letter associated with it, that is controlled by one of its pins.
'
' Seven Segment data "Anded" together to give values for the Common Anode digits
'
    Dim SevenSeg_Data As Code = Segment_A & Segment_B & Segment_C & Segment_D & Segment_E & Segment_F,_     ' The segments to illuminate a digit 0
                                Segment_B & Segment_C,_                                                     ' The segments to illuminate a digit 1
                                Segment_A & Segment_B & Segment_D & Segment_E & Segment_G,_                 ' The segments to illuminate a digit 2
                                Segment_A & Segment_B & Segment_C & Segment_D & Segment_G,_                 ' The segments to illuminate a digit 3
                                Segment_B & Segment_C & Segment_F & Segment_G,_                             ' The segments to illuminate a digit 4
                                Segment_A & Segment_C & Segment_D & Segment_F & Segment_G,_                 ' The segments to illuminate a digit 5
                                Segment_C & Segment_D & Segment_E & Segment_F & Segment_G,_                 ' The segments to illuminate a digit 6
                                Segment_A & Segment_B & Segment_C,_                                         ' The segments to illuminate a digit 7
                                Segment_A & Segment_B & Segment_C & Segment_D & Segment_E & Segment_F & Segment_G,_ ' The segments to illuminate a digit 8
                                Segment_A & Segment_B & Segment_C & Segment_D & Segment_F & Segment_G       ' The segments to illuminate a digit 9           
 
'---------------------------------------------------------------------------------------
' Build up the seperate digits of a variable
' Input     : pValue holds the value to display
' Output    : None
' Notes     : Zero suppression is implemented
'
Proc Build_Displays(pValue As Word)

    Dim bDigitValue As Byte
   
    bDigitValue = Dig pValue, 0                             ' Extract the first digit from pValue
    bOnes = CRead8 SevenSeg_Data[bDigitValue]               ' Read the data for the first digit of the value to display
    If pValue < 10 Then                                     ' Is the value to display less than 10?
        bTens = $FF                                         ' Yes. So blank the Tens Display
    Else                                                    ' Otherwise...
        bDigitValue = Dig pValue, 1                         ' Extract the second digit from pValue
        bTens = CRead8 SevenSeg_Data[bDigitValue]           ' Read the data for the second digit of the value to display
    EndIf
   
    If pValue < 100 Then                                    ' Is the value to display less than 100?
        bHundreds = $FF                                     ' Yes. So blank the Hundreds Display
    Else                                                    ' Otherwise...
        bDigitValue = Dig pValue, 2                         ' Extract the third digit from pValue
        bHundreds = CRead8 SevenSeg_Data[bDigitValue]       ' Read the data for the third digit of the value to display
    EndIf
   
    If pValue < 1000 Then                                   ' Is the value to display less than 1000?
        bThousands = $FF                                    ' Yes. So blank the Thousands Display
    Else                                                    ' Otherwise...
        bDigitValue = Dig pValue, 3                         ' Extract the fourth digit from pValue
        bThousands = CRead8 SevenSeg_Data[bDigitValue]      ' Read the data for the fourth digit of the value to display
    EndIf
EndProc

'---------------------------------------------------------------------------------------       

Do:
        Build_Displays(TestData)      ' Create the individual values to display on the 7 segment LEDs.

        SHIFT_LATCH = 0
        SHOut SHIFT_DATA, SHIFT_CLK, MsbFirst, [bOnes]   ' (Last digit in the chain)
        SHOut SHIFT_DATA, SHIFT_CLK, MsbFirst, [bTens]   
        SHOut SHIFT_DATA, SHIFT_CLK, MsbFirst, [bHundreds]   
        SHOut SHIFT_DATA, SHIFT_CLK, MsbFirst, [bThousands]   
        SHOut SHIFT_DATA, SHIFT_CLK, MsbFirst, [$7F]   
        SHOut SHIFT_DATA, SHIFT_CLK, MsbFirst, [$7F]     
        SHOut SHIFT_DATA, SHIFT_CLK, MsbFirst, [$7F]   
        SHOut SHIFT_DATA, SHIFT_CLK, MsbFirst, [$7F]           
        SHOut SHIFT_DATA, SHIFT_CLK, MsbFirst, [$7F] ' (First digit in the chain)

        SHIFT_LATCH = 1       
       
        DelayMS 500                                             ' Update the display twice a second.
       
        Inc TestData
        If TestData > 9999 Then
        TestData = 0
        EndIf
               
        Loop   
 

Regards,
Bob
 
 

See_Mos

Hi Bob, can you post the VSM and I will have a go.

RGV250

Hi,
This is the VSM but you could just use the CPU, all I do is run it and then pause it and look at the variables.
Shift test.zip

Bob

tumbleweed


RGV250

Hi Tumbleweed,
I am not sure what you mean, the values are correct. If I send them directly IE from the Shout I get the correct characters, it is when I use the procedure that is the problem.

Bob

tumbleweed

Compare your defines to the originals.
They're inverted.

RGV250

Hi Tumbleweed,
The values are correct, if I invert them I will not get the right output.
If I send this SHOut SHIFT_DATA, SHIFT_CLK, MsbFirst, [$7F] I get the right value at the display.
If I send this SHOut SHIFT_DATA, SHIFT_CLK, MsbFirst, [bOnes] using Les's values I get something at the display but not correct, if I use mine I get nothing at all. The problem appears to be the procedure not returning any value at all.

Bob

tumbleweed

SevenSeg_Data ANDS all the defines, so yours end up as 0.
Humor me and try inverting yours.

See_Mos

#8
Hi Bob,
the .PRJ would not open in my V8.0 ISIS so I used my generic 18F25K20 sim and hooked up the oscilloscope to PortC and I can see that the data output is changing as it cycles through the loop.

I added some lines after the delay to see the values change on an LCD display connected to PortB

        DelayMS 500                                            ' Update the display twice a second.
        Print At 1,1,Dec bOnes
        Print At 2,1,Dec bTens
        Print At 3,1,Dec bHundreds
        Print At 4,1,Dec bThousands

so I would need the digit drive code and the circuit to proceed further.

RGV250

#9
Hi,
I have now resolved it, Tumbleweed was partly there but inverting them gave the wrong output. I now "or" all the values and get the right output at the display.

I have V8.8 ISIS, not sure if that was the issue.

Regards,
Bob

top204

The 'Anding" is for Common Anode displays. For Common Cathode displays, the values need to be 'Ored':

'
' Individual segment values for a Common Cathode 7 segment display
'
$define cSegment_A 1                             ' The value to send to illuminate segment A on the Common Cathode 7 segment display
$define cSegment_B 2                             ' The value to send to illuminate segment B on the Common Cathode 7 segment display
$define cSegment_C 4                             ' The value to send to illuminate segment C on the Common Cathode 7 segment display
$define cSegment_D 8                             ' The value to send to illuminate segment D on the Common Cathode 7 segment display
$define cSegment_E 16                            ' The value to send to illuminate segment E on the Common Cathode 7 segment display
$define cSegment_F 32                            ' The value to send to illuminate segment F on the Common Cathode 7 segment display
$define cSegment_G 64                            ' The value to send to illuminate segment G on the Common Cathode 7 segment display
'
' An LED display is formatted like this:
'     A
'   ------
'   |    |
'  F|    |B
'   | G  |
'   ------
'   |    |
'  E|    |C
'   | D  |
'   ------
'
' So each segment has a letter associated with it, that is controlled by one of its pins.
'
' Seven Segment data Ored together to give values for the Common Cathode digits
'
    Dim SevenSeg_Data As Flash8 = {cSegment_A | cSegment_B | cSegment_C | cSegment_D | cSegment_E | cSegment_F,     ' The segments to illuminate a digit 0
                                   cSegment_B | cSegment_C,                                                         ' The segments to illuminate a digit 1
                                   cSegment_A | cSegment_B | cSegment_D | cSegment_E | cSegment_G,                  ' The segments to illuminate a digit 2
                                   cSegment_A | cSegment_B | cSegment_C | cSegment_D | cSegment_G,                  ' The segments to illuminate a digit 3
                                   cSegment_B | cSegment_C | cSegment_F | cSegment_G,                               ' The segments to illuminate a digit 4
                                   cSegment_A | cSegment_C | cSegment_D | cSegment_F | cSegment_G,                  ' The segments to illuminate a digit 5
                                   cSegment_C | cSegment_D | cSegment_E | cSegment_F | cSegment_G,                  ' The segments to illuminate a digit 6
                                   cSegment_A | cSegment_B | cSegment_C,                                            ' The segments to illuminate a digit 7
                                   cSegment_A | cSegment_B | cSegment_C | cSegment_D | cSegment_E | cSegment_F | cSegment_G, ' The segments to illuminate a digit 8
                                   cSegment_A | cSegment_B | cSegment_C | cSegment_D | cSegment_F | cSegment_G}     ' The segments to illuminate a digit 9

I think my original post on this had the code listings for Common Anode and Common Cathode displays, because I still have the listings in my "users" directory on my machine. However, for a device controlling the displays that is neither Common Anode or Cathode using standard multiplexing, the values may need to be slightly different, but the mechanism stays the same for arranging them and zero suppression.

RGV250

Hi Les,
From what limited information I can dig up they are common anode displays but I think the output is inverted by the ULN2003 which drives it.

Bob

tumbleweed

ULN2003 are open-collector drivers, so it's likely the displays are common-cathode.

RGV250

Hi,
The displays are HT-23101BSR, the closest I found were ULS-23101BSR which are common anode?? Either way it does not matter now as I have that side of it working, now having problems with setting the clock.

Bob

John Lawton

#14
Quote from: tumbleweed on Oct 27, 2021, 11:15 PMULN2003 are open-collector drivers, so it's likely the displays are common-cathode.

Err, common anode?