Shop OBEX P1 Docs P2 Docs Learn Events
Help with 74HC595 8-bit shift register with latch. — Parallax Forums

Help with 74HC595 8-bit shift register with latch.

mynet43mynet43 Posts: 644
edited 2009-01-08 17:53 in Propeller 1
I'm trying to help someone on the forum drive this chip from a prop.

The problem is that they have the chip and I don't have one to test with.

They're a relative newby to the prop so I wrote the following driver.

They're using it to drive a set of 8 LED's.

Apparently it almost works. It latches the values for about a second and then
drops the lights and bit 0 flickers, as best as I can understand the description from long distance.

Here's the driver code I wrote. Would someone please take a look at it and let me know if you
spot something? If you have a chip to debug it (or a working driver), that would be even better[noparse]:)[/noparse]

Thanks for your help.

Jim

'' ******************************************************************************
'' * "HC595.spin"  74HC595 SPIN Object                                          *
'' * coded by Jim -- 12/31/08 -- Happy New Year!                                *
'' * Version 1.0                                                                *
'' ******************************************************************************
''
'' Calling sequence
'' OBJ
''   SReg : "HC595"
''
'' code segment
''   SReg.InitSer595              ' to initialize driver
'' more code
''   DataByte := toSend           ' set up data to send to chip
''   SReg.WriteSer595(DataByte)   ' send data to chip
'' more code
''
 
CON
  _PinHigh        = 1
  _PinLow         = 0

  CLK           = 0             ' pin number of CLK  pin on chip (AKA SCK)
  SER           = 1             ' pin number of SER  pin on chip
  CLR           = 2             ' pin number of SCLR pin on chip
  RCK           = 3             ' pin number of RCK  pin on chip
  GPN           = 4             ' pin number of G    pin on chip

VAR
  long  bitout, databyte

PUB InitSer595                  ' initialize 74HC595 for startup

  ' set the control lines as outputs
  dira[noparse][[/noparse]CLK] ~~
  dira[noparse][[/noparse]SER] ~~
  dira[noparse][[/noparse]CLR] ~~
  dira[noparse][[/noparse]RCK] ~~
  dira[noparse][[/noparse]GPN] ~~

  outa[noparse][[/noparse]CLK] := _PinLow          ' init main  clock line to low
  outa[noparse][[/noparse]RCK] := _PinLow          ' init latch clock line to low
  

  outa[noparse][[/noparse]GPN] := _PinHigh         ' set outputs to 3-state
  outa[noparse][[/noparse]CLR] := _PinLow          ' set to clear register on chip
  outa[noparse][[/noparse]GPN] := _PinLow          ' turn on the chip and clear pins
  outa[noparse][[/noparse]CLR] := _PinHigh         ' return CLR pin to high after clear


PUB WriteSer595(Data)           ' Data is long with 8 bits of data in bits 7 - 0
  ' Write 8 bits of data.         Data byte is output MSB first.

  databyte := Data              ' transfer to working storage

  repeat 8                      ' shift out 8 bits
    bitout := databyte & %1000_0000   ' take hi bit from byte -> bitout bit 7
    bitout >>= 7                ' shift to bit zero for output

    databyte <<= 1              ' shift data left 1 bit for next loop

    outa[noparse][[/noparse]SER] := bitout         ' shift out high bit to serial pin (0 or 1)
    
    outa[noparse][[/noparse]CLK] := _PinHigh       ' toggle the clock pin to shift bit out
    
    outa[noparse][[/noparse]CLK] := _PinLow        ' high then low to cycle the clock

  outa[noparse][[/noparse]RCK] := _PinHigh         ' toggle the RCK pin to latch the output
    
  outa[noparse][[/noparse]RCK] := _PinLow          ' high then low to cycle the clock

Comments

  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2009-01-08 03:11
    You can use bitwise reverse on the low order 8-bits to simplify the code.
    No need to have a databyte variable, just work straight off the input parameter
    No need to have a bitout variable either, just use the data parameter (lsb)

    The problem sounds more like a hardware problem, a poor supply, no decoupling, glitch on the clock or something like that.

    *Peter*
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2009-01-08 03:18
    Here's a quick suggestion to improving the code although your version looks functional.

    *Peter*

    '' ******************************************************************************
    '' * "HC595.spin"  74HC595 SPIN Object                                          *
    '' * coded by Jim -- 12/31/08 -- Happy New Year!                                *
    '' * Version 1.0                                                                *
    '' ******************************************************************************
    ''
    '' Calling sequence
    '' OBJ
    ''   SReg : "HC595"
    ''
    '' code segment
    ''   SReg.InitSer595              ' to initialize driver
    '' more code
    ''   DataByte := toSend           ' set up data to send to chip
    ''   SReg.WriteSer595(DataByte)   ' send data to chip
    '' more code
    ''
     
    CON
      _PinHigh        = 1
      _PinLow         = 0
    
      CLK           = 0             ' pin number of CLK  pin on chip (AKA SCK)
      SER           = 1             ' pin number of SER  pin on chip
      CLR           = 2             ' pin number of SCLR pin on chip
      RCK           = 3             ' pin number of RCK  pin on chip
      GPN           = 4             ' pin number of G    pin on chip
    
    PUB InitSer595                  ' initialize 74HC595 for startup
    ' set output register before pin becomes an output (avoids glitches)
      outa[noparse][[/noparse]GPN] := _PinHigh         ' set outputs to 3-state
      outa[noparse][[/noparse]CLR] := _PinLow          ' set to clear register on chip
      outa[noparse][[/noparse]RCK] := _PinLow          ' init latch clock line to low
      outa[noparse][[/noparse]CLK] := _PinLow          ' init main  clock line to low
    
      ' set the control lines as outputs
      dira[noparse][[/noparse]CLK] ~~
      dira[noparse][[/noparse]SER] ~~
      dira[noparse][[/noparse]CLR] ~~
      dira[noparse][[/noparse]RCK] ~~
      dira[noparse][[/noparse]GPN] ~~
    
      outa[noparse][[/noparse]GPN]~         ' turn on the chip and clear pins
      outa[noparse][[/noparse]CLR]~~        ' return CLR pin to high after clear
    
    
    PUB WriteSer595(Data)           ' Data is long with 8 bits of data in bits 7 - 0
      ' Write 8 bits of data.         Data byte is output MSB first.
      Data ><= 8                     ' bitwise reverse the lsbs
      repeat 8                      ' shift out 8 bits
        outa[noparse][[/noparse]SER] := Data         ' shift out next bit (bit0)  to serial pin (0 or 1)
        outa[noparse][[/noparse]CLK] ~~       ' toggle the clock pin to shift bit out
        outa[noparse][[/noparse]CLK] ~        ' high then low to cycle the clock
        Data >>= 1                       'next bit
      outa[noparse][[/noparse]RCK]~~         ' toggle the RCK pin to latch the output
      outa[noparse][[/noparse]RCK]~          ' high then low to cycle the clock
    
    



    P.S. just edited the code again to use the shortform bitset operators ~~ and ~
  • mynet43mynet43 Posts: 644
    edited 2009-01-08 04:09
    Thanks for the suggestions. They look good.

    I wrote the thing in about 15 minutes, too lazy to look up a couple of things[noparse]:)[/noparse]

    It looks like you were right the first time, hardware problem...

    Either that or we were clocking the signals out too fast for the chip.

    It seems to be working now.

    Thanks for looking at it.

    Jim
  • mynet43mynet43 Posts: 644
    edited 2009-01-08 04:23
    Does anyone know off-hand what the pulse width is when you cycle a pin in SPIN?

        outa[noparse][[/noparse]CLK] ~~       ' toggle the clock pin to shift bit out
        outa[noparse][[/noparse]CLK] ~        ' high then low to cycle the clock
    
    



    I'm not sure how many clock cycles the outa[noparse][[/noparse] ] instruction takes.
  • StefanL38StefanL38 Posts: 2,292
    edited 2009-01-08 07:50
    Hello,

    take a look into the datasheet the minimum pulsewidth depends on the supply-voltage longest pulsewidth at 2V
    a little less than 0.1 microseconds on higher voltages even faster.

    I have coded a 595 in assembler with almost no delays and it is working
    so coded in SPIN the pulsewidth is far long enough for proper switching

    again in the datasheet you can see that the clocks are triggered on the LOW-HIGH-transistion
    you code does it the opposite way HIGH-LOW so as a quick guess the flickering of LED 0 is because
    bit 0 is shifted/latched if the NEXT cycle begins

    So the toogling of the clocks has to vice versa
       ' toggle the clock pin to shift bit out
        outa[noparse][[/noparse]CLK] ~       'set Pin LOW to prepare transition
        outa[noparse][[/noparse]CLK] ~~     'pin HIGH:  the LOW-HIGH-transition triggers the clock
    
    
    



    best regards

    Stefan
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2009-01-08 08:11
    @mynet43: Spin isn't very fast for this bit-bashing so expect a minimum pulse width of around several microseconds. However the edges are the same as they would be even if the pulse was much faster or slower. If the hardware is roughly made it will pay to add a 100pf capacitor to the clock line to desensitize it (and of course a 0.1uF cap across the chip's power and ground).

    @stefanl38: The toggling that mynet does changes the data bit then it takes the clock high (from previous low) and then low again. But since the clock is low-to-high sensitive it doesn't matter whether it is low then high-low or high then low-high.

    *Peter*
  • LeonLeon Posts: 7,620
    edited 2009-01-08 10:02
    It's actually SPI-compatible, so the SPI object should work (I think there is one). I use a 74HC595 on a little PCB with LEDs on the outputs to test SPI interfaces.

    Leon

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Amateur radio callsign: G1HSM
    Suzuki SV1000S motorcycle
  • LeonLeon Posts: 7,620
    edited 2009-01-08 10:04
    The 74HC595 is SPI-compatible, so the SPI object should work (I think there is one). I use one on a little PCB with LEDs on the outputs to test SPI interfaces.

    Leon

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Amateur radio callsign: G1HSM
    Suzuki SV1000S motorcycle
  • mynet43mynet43 Posts: 644
    edited 2009-01-08 14:07
    Wow!

    Thanks everyone for the great responses, they really help.

    I'm going to have to go back and read the thread again. There was a question about the direction of my clock transitions.

    I first set the data line and then set the clock high. This should cause a low to high transition, which I'm pretty sure is right. Let me know if I missed something.

    I'm glad to hear that someone coded it in assembly. That makes me think the code should work.

    Remember, I'm doing this long distance, I'm in CA and he's in PA (with the HC595). I'll have him check for caps and to make sure the lines aren't too long.

    Thanks again for the great feedback!

    Jim
  • LeonLeon Posts: 7,620
    edited 2009-01-08 14:17
    Everything you need is in the HC595 data sheet, just follow the timing diagrams. I'd buy a couple of chips and wire them up, it'll make things much easier.

    Leon

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Amateur radio callsign: G1HSM
    Suzuki SV1000S motorcycle
  • danthonydanthony Posts: 45
    edited 2009-01-08 15:37
    How do you modify jim or peter;s code to talk to many 74hc's strung in a row? I tried the obvious on the repeats, but it did not work. Any ideas?
  • StefanL38StefanL38 Posts: 2,292
    edited 2009-01-08 15:45
    hello danthony,

    take a look into the datasheet

    pin 9 of the 595 is the serial data OUTput called Qh

    you simply connect Qh of 595 no 1 with serial data INput of 595 no 2, etc, etc, etc

    shiftclock and latch are parallel
    you trigger the latch ONLY at the end of shifting ALL 32, 48, or whatever amount of bits

    that's all

    best regards

    Stefan

    Post Edited (StefanL38) : 1/8/2009 3:52:01 PM GMT
  • danthonydanthony Posts: 45
    edited 2009-01-08 17:08
    Stefan-
    This is mynets code and I can get to work with one chip. I do not see the clk~~, clk~ code to modify as in your earlier post.
    I tried what you said with the qh to serial in of #2 but nothing. Here is the code I have working for 1 chip.

    '' ******************************************************************************

    PUB WriteSer595(Data) ' Data is long with 8 bits of data in bits 7 - 0
    ' Write 8 bits of data. Data byte is output MSB first.

    databyte := Data ' transfer to working storage
    repeat 8 ' shift out 8 bits
    bitout := databyte & %1000_0000 ' take hi bit from byte -> bitout bit 7
    bitout >>= 7 ' shift to bit zero for output
    databyte <<= 1 ' shift data left 1 bit for next loop
    outa[noparse][[/noparse]SER] := bitout ' shift out high bit to serial pin (0 or 1)
    outa[noparse][[/noparse]CLK] := _PinHigh ' toggle the clock pin to shift bit out
    outa[noparse][[/noparse]CLK] := _PinLow ' high then low to cycle the clock
    outa[noparse][[/noparse]RCK] := _PinHigh ' toggle the RCK pin to latch the output
    outa[noparse][[/noparse]RCK] := _PinLow ' high then low to cycle the clock




    Thanks
    Don
  • danthonydanthony Posts: 45
    edited 2009-01-08 17:53
    forget it Stefan, I got it.

    Thanks,
    Don
Sign In or Register to comment.