1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

Working with Shift Registers and a PIC help

Discussion in 'Microcontrollers' started by Darkstar64, Sep 4, 2008.

  1. Darkstar64

    Darkstar64 New Member

    Joined:
    Apr 3, 2008
    Messages:
    112
    Likes:
    0
    Hey everyone im back once again needing some assistance school started and I brought the Idea of the LED cube to him and he liked it but he asked me to find out the theory or I guess the way it works we will be using shift registers instead of directly driving the LED's so it allows me 12 output pins instead of the 5 that the 12F509 has but im wondering how I would go about doing the pulses to the shift register ive seen a little code out there about it but not too much any help I know the shift register takes 4 inputs data,clock,latch,enable output and I will be using the 74HC595 as my shift register to start with just to see how it works right just using 8 LED's first and my PIC controlling them in a fashion that I want it doesn't have to be perfect and its just some quick testing I don't want to hear just get a better PIC bc im just starting out with them and the PIC 12F509 is good for right now maby later I will get some better ones but Thanks for all the help guys its much needed and once its in there its never going to come out haha
     
    Last edited: Sep 4, 2008
  2. Papabravo

    Papabravo Well-Known Member

    Joined:
    Mar 9, 2006
    Messages:
    2,889
    Likes:
    25
    Location:
    Michigan, USA (GMT-5)
  3. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    Here's some dead simple C demo code for 18F1320 (Junebug) and 74HC595. Being C, it's trivial to change it for any PIC.

    The code simply alternately flashes the even and odd LEDS of a row of eight LEDs driven by a single 74HC595.

    Code (text):
    #include <system.h>
    #include <boostc.h>

    #pragma CLOCK_FREQ  8000000
    #pragma DATA    _CONFIG1H, _INTIO2_OSC_1H
    #pragma DATA    _CONFIG2H, _WDT_OFF_2H
    #pragma DATA    _CONFIG3H, _MCLRE_ON_3H
    #pragma DATA    _CONFIG4L, _LVP_OFF_4L

    #define data    latb.1
    #define clock   latb.4
    #define latch   lata.3

    void main(void){
        unsigned char x;
        osccon=0x72;                //8MHz osc
        trisa=trisb=0;
        while(1){
            data=1;             //shift in alternating 1's & 0's
            for(x=0;x<8;x++){
                clock=1;clock=0;
                if(data==0)
                    data=1;
                else
                    data=0;
            }
            latch=1;latch=0;        //latch the data
            delay_ms(170);          //delay so we can see LEDs

            data=0;             //shift in alternating 0's & 1's
            for(x=0;x<8;x++){
                clock=1;clock=0;
                if(data==0)
                    data=1;
                else
                    data=0;
            }
            latch=1;latch=0;        //latch the data
            delay_ms(170);          //delay so we can see LEDs
        }
    }
     

    Here's a different main() for the above that blinks the eight LEDs as a binary byte counter:
    Code (text):
    void main(void){
        unsigned char x,y,temp1,temp2;
        osccon=0x72;                    //8MHz osc
        trisa=trisb=0;
        while(1){
            for(x=0;x<255;x++){
                for(y=0;y<8;y++){
                    temp1=x;
                    temp2=temp1>>y;
                    temp2=temp2&0b00000001;
                    data=temp2;
                    clock=1;clock=0;
                }
                latch=1;latch=0;
                delay_ms(170);
            }
        }
    }
     
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Darkstar64

    Darkstar64 New Member

    Joined:
    Apr 3, 2008
    Messages:
    112
    Likes:
    0

    ok thanks for the info but anything in assembler thats the only thing I know at the moment and understand but thanks for the quick responses also is there a way to have more then one pin on at the same time say I have 1 shiftregister that has 12 outputs and 4 inputs once again ? I'm going to be trying 64 LED's matrix that I saw and it shows me how to do it using just 4 I/0 pins but it doesn't state the assembly or any code ?
     
  6. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    That C code is super easy to port to assembly. Pretty simple stuff. It's not like C is some kind of ultra cryptic language or anything. :p Just go through it a section at a time. If you want, I can explain what each section/line does.

    You can have any shift reg outputs on or off that you want. You have 12 outputs? Simply shift in 12 bits and toggle the latch so it appears on the outputs. Then do another 12 bits.

    Shift registers can be cascaded, so for instance on your 12 bit unit, as soon as you exceed 12 bits shifted in, it starts to shift into the second shift register. If you have another or six more (or 20! or whatever you want), when each one is filled, the bits just start moving into the next one in the chain. When you're done shifting bits in, toggle the latch and it appears on the output pins.

    Breadboard one up with a PIC and some LEDs and tinker with it. Have the datasheet handy. You'll have it figured out in no time. They're very simple to use.
     
    Last edited: Sep 4, 2008
  7. Darkstar64

    Darkstar64 New Member

    Joined:
    Apr 3, 2008
    Messages:
    112
    Likes:
    0
    ty thats helped alot I also have a concern though about how the Multiplexing of a 3D LED cube works me and my teacher have spent a few days on trying to figure out how it works and stuff any help on this one as well all get converting the C or at least try too it looks soooo confusing haha it might help if you explain it like you said thanks once again and if I get it right its basically just putting lets say GP2 high, low, high, low so many times in a certain amount of time or do you have to send a string of bits bc im not sure how to do that :(
     
    Last edited: Sep 4, 2008
  8. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    Hehehe! :D You did that all in one sentence. Makes it very difficult to read. Ever hear of punctuation? :p

    And what the hell does "ty" stand for?

    On my small 3x3x3 LED cube I just treated it like three stacked 9-bit digits. I was driving it directly - no shift registers - but that doesn't change anything. I simply set the bits I wanted lit on each "digit" and every time the timer interrupted it would light up the next "digit", or level. Writing this piece of code for the first time is pretty brain-grinding, but really it's not terribly complex. :p You have to buzz through them fairly quickly to prevent flicker, but a PIC can easily handle that. Shift registers are also very quick.

    Once you figure this out, it's the same thing to do a seven-segment LED display, only they're only 8-bits per digit (7-segs and decimal-point).

    There's no amount of time involved. You can shift bits in as fast or as slow as you like. What you do is put the bit value you want (0 or 1) on the data pin. Then toggle the clock high and low quickly (or slowly if you like :p) to shift that bit in (maybe low and high for some shift registers? see your datasheet). Then shift in the next bit and the next and so on. When you've finished shifting bits in just toggle the latch pin high/low (or low/high) and the bits you've just shifted in appear on the outputs of the shift register.
     
    Last edited: Sep 4, 2008
  9. Darkstar64

    Darkstar64 New Member

    Joined:
    Apr 3, 2008
    Messages:
    112
    Likes:
    0
    I'm also making the 3x3x3 cube first before I work on the bigger version im working on but I can't drive it directly as you did. Thats why I have to use shift registers bc there easyer to work with then the other options now about the 3x3x3 cube im going to have all the grounds common for each layer so there will be 3 layers each having 9 LEDs on each layer so thats why im going to be using the 12 output shift register. Doesn't even matter how fast I do it so I won't need a delay in between each one ? But toggle the clock in between each bit then after thats all done I just toggle the latch pin high and it should do what I want o and ty is thank you by the way o also here is the data sheet but im not sure what im supose to be looking at there is a timer diagram but im not sure what it is getting at http://www.electro-tech-online.com/custompdfs/2008/09/74HC_HCT595_4.pdf

    I just thought you just outputed 8 bits from the pic like lets say I wanted just LED1 on I would output '100000000' PIC and make the clock pin high in between each bit of course. Then just make the Latch pin high like this code I just finished its not complete yet but its close too being done I might put in a call for a loop that just repeats a Low output so that I don't have to write out the whole 7 bits as low I can call a loop if I have too im not sure if there is a better way to write it ?

    Code (text):
    ;    Pin assignments:                                                 *
    ;                                                                     *
    ;           GP0 - Data input                                          *
    ;           GP1 - Clock input                                         *
    ;           GP2 - Latch input                                         *
    ;           GP3 - Used as a switch for Cycle of LED's                 *
    ;           GP4 - Forth set of LEDS                                   *
    ;           GP5 - Switch for Random effect                            *
    ;                                                                     *
    ;                                                                     *
    ;                                                                     *
    ;**********************************************************************

        list      p=12F509            ; list directive to define processor
        #include <p12F509.inc>        ; processor specific variable definitions

        __CONFIG   _MCLRE_ON & _CP_OFF & _WDT_OFF & _IntRC_OSC

    ; '__CONFIG' directive is used to embed configuration word within .asm file.
    ; The lables following the directive are located in the respective .inc file.
    ; See respective data sheet for additional information on configuration word.



        cblock  0x07
    ;***** VARIABLE DEFINITIONS
    clock
    data1
    data0
    latch
        endc



    ;**********************************************************************
    RESET_VECTOR    CODE   0x3FF      ; processor reset vector

    ; Internal RC calibration value is placed at location 0x3FF by Microchip
    ; as a movlw k, where the k is a literal value.
       
    MAIN    CODE    0x000
        movwf   OSCCAL            ; update register with factory cal value


    start  
    ;******** Main Code

    start
            movlw   b'001000'       ; Configure only GP3 as a input
            tris    GPIO
           
    loop

            call    data1           ; 1st bit High
            call    clock
            call    data0           ; 2nd bit Low
            call    clock
            call    data0           ; 3rd bit Low
            call    clock
            call    data0           ; 4th bit Low
            call    clock
            call    data0           ; 5th bit Low
            call    clock  
            call    data0           ; 6th bit Low
            call    clock
            call    data0           ; 7th bit Low
            call    clock
            call    data0           ; 8th bit Low
            call    latch


    ;******** Subroutines

    clock
            movlw   b'000010'       ; Clock set
            movwf   GPIO
            retlw   0
           
    data1   movlw   b'000001'       ; Data pin high
            movwf   GPIO
            retlw   0
           
    data0   movlw   b'000000'       ; Data pin low
            movwf   GPIO
            retlw   0
           
    latch   movlw   b'000000'
            movwf   GPIO
            retlw   0
       
        END                 ; End of Program !
     
    Last edited: Sep 4, 2008
  10. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    The shift register should be able to keep up with almost anything you throw at it (unless you're running some kind of huge clock rate). No delays necessary. You may have to put a nop in to avoid RMW (read-modify-write) problems, but definitely try it without first.

    High and back low again. Just blip it to latch the data, same as you just blip the clock to clock in bits.

    What you'll usually do for a thing like this is build sequences of patterns that each level steps through. Put them in tables and just step through them at a steady rate. So writing all 9 bits each time is simple and automated. Once you write the engine (the hard part) it's just a matter feeding it different sequences of patterns (the fun and easy part).

    For instance, here's a few of the patterns I used to make my cube do stuff:
    Code (text):
    downtb  db  0x00,0x00,0x00,0x00,0xff,0x01
        db  0x00,0x00,0xff,0x01,0x00,0x00
        db  0xff,0x01,0x00,0x00,0x00,0x00

    rolltb  db  0x24,0x01,0x00,0x00,0x00,0x00
        db  0x49,0x00,0x00,0x00,0x00,0x00
        db  0x92,0x00,0x00,0x00,0x00,0x00
        db  0x00,0x00,0x92,0x00,0x00,0x00
        db  0x00,0x00,0x00,0x00,0x92,0x00
        db  0x00,0x00,0x00,0x00,0x49,0x00
        db  0x00,0x00,0x00,0x00,0x24,0x01
        db  0x00,0x00,0x24,0x01,0x00,0x00

    floptb  db  0xe0,0x00,0xe0,0x00,0xe0,0x00
        db  0x03,0x01,0x1c,0x00,0xe0,0x00
        db  0x00,0x00,0x00,0x00,0xff,0x01
        db  0xe0,0x00,0x1c,0x00,0x03,0x01
        db  0x03,0x01,0x03,0x01,0x03,0x01
        db  0x03,0x01,0x1c,0x00,0xe0,0x00
        db  0xff,0x01,0x00,0x00,0x00,0x00
        db  0xe0,0x00,0x1c,0x00,0x03,0x01

    flshtb1 db  0x10,0x00,0x10,0x00,0x10,0x00
        db  0x02,0x00,0x10,0x00,0x80,0x00
        db  0x00,0x00,0x92,0x00,0x00,0x00
        db  0x80,0x00,0x10,0x00,0x02,0x00

        db  0x08,0x00,0x08,0x00,0x08,0x00
        db  0x01,0x00,0x08,0x00,0x40,0x00
        db  0x00,0x00,0x49,0x00,0x00,0x00
        db  0x40,0x00,0x08,0x00,0x01,0x00

        db  0x04,0x00,0x04,0x00,0x04,0x00
        db  0x00,0x01,0x04,0x00,0x20,0x00
        db  0x00,0x00,0x24,0x01,0x00,0x00
        db  0x20,0x00,0x04,0x00,0x00,0x01
     
    Last edited: Sep 4, 2008
  11. Darkstar64

    Darkstar64 New Member

    Joined:
    Apr 3, 2008
    Messages:
    112
    Likes:
    0
    Not too sure what your getting at with the whole engine thing but everything ealse makes sense If im correct you mean to make it so instead of calling like data1 data0 etc its just one call and it makes it all so like if I wanted LED1 on I would do something like this instead of what I have and im wondering is there a way to lets say just write it like this "10000000" then the pic then takes that and outputs it like that but adding the clock call in between each bite ? it might be easyer when making the cube then I won't have this long list of LED's and just be able to write it as one number and then the PIC takes it from there seperates it and then the Shift Register outputs it ? Just because its going to take alot of code and I don't think the PIC will be able to hold that much


    Code (text):
    ;**********************************************************************                                                                    
    ;    Pin assignments:                                                 *
    ;                                                                     *
    ;           GP0 - Data input                                          *
    ;           GP1 - Clock input                                         *
    ;           GP2 - Latch input                                         *
    ;           GP3 - Used as a switch for Cycle of LED's                 *
    ;           GP4 - Forth set of LEDS                                   *
    ;           GP5 - Switch for Random effect                            *
    ;                                                                     *
    ;                                                                     *
    ;                                                                     *
    ;**********************************************************************

        list      p=12F509            ; list directive to define processor
        #include <p12F509.inc>        ; processor specific variable definitions

        __CONFIG   _MCLRE_ON & _CP_OFF & _WDT_OFF & _IntRC_OSC

    ; '__CONFIG' directive is used to embed configuration word within .asm file.
    ; The lables following the directive are located in the respective .inc file.
    ; See respective data sheet for additional information on configuration word.



        cblock  0x07
    ;***** VARIABLE DEFINITIONS
    clock
    data1
    data0
    latch
        endc



    ;**********************************************************************
    RESET_VECTOR    CODE   0x3FF      ; processor reset vector

    ; Internal RC calibration value is placed at location 0x3FF by Microchip
    ; as a movlw k, where the k is a literal value.
       
    MAIN    CODE    0x000
        movwf   OSCCAL            ; update register with factory cal value


    start  
    ;******** Main Code

    start
            movlw   b'001000'       ; Configure only GP3 as a input
            tris    GPIO
           
    loop

            call    LED1
            goto    loop


    ;******** Subroutines

    clock
            movlw   b'000010'       ; Clock set 1
            movwf   GPIO
            movlw   b'000000'       ; Clock set 0
            movwf   GPIO
            retlw   0
           
    data1   movlw   b'000001'       ; Data pin high
            movwf   GPIO
            retlw   0
           
    data0   movlw   b'000000'       ; Data pin low
            movwf   GPIO
            retlw   0
           
    latch   movlw   b'000100'
            movwf   GPIO
            movlw   b'000000'
            movwf   GPIO
            retlw   0
           
    LED1    call    data1
            call    clock
            call    data0
            call    clock
            call    data0
            call    clock
            call    data0
            call    clock
            call    data0
            call    clock
            call    data0
            call    clock
            call    data0
            call    clock
            call    data0
            call    clock
            call    latch
            retlw   0
           
       
        END                 ; End of Program !
     
  12. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    What I mean by that is I built a piece of code (an engine) that takes whatever sequence of patterns that I build (that meet the requirements of the engine) and displays them. I don't have to mess with it - it just works. Feed it sequences of patterns and it makes it happen. :D

    If I want just one LED on, I just feed it a single step pattern with that one LED bit set.

    That's incredibly difficult to understand (ever heard of punctuation? try using some!), but I think I get the gist of what you're saying. Yes, that's an "engine". I just feed it a pointer to the pattern I want and it takes care of the rest.

    It is a fair bit of code. My asm program to run my cube, with seven patterns, was around 954 bytes. Your 12F509 has 1024, so even if your code isn't as tight it should fit. You might have to lose a couple patterns. So what?

    I could give you my code, but then you wouldn't learn anything. Also you'd probably have to almost completely rewrite to suit the 12F. My code is for 18F. It's an interesting and challenging piece of code for an intermediate newb to write. Makes you very happy when you finally get it to work. :D
     
    Last edited: Sep 4, 2008
  13. Darkstar64

    Darkstar64 New Member

    Joined:
    Apr 3, 2008
    Messages:
    112
    Likes:
    0
    k makes sense how would I then go about writing a engine to allow me to just give it a 8 bit sequence and it will take that and display it ? I'm srry im new to PIC's and just know some of the basic commands like changing bits to high,low and loops not too much of the other stuff srry :( like I can say it but I don't know how to write it thats the problem. Here is what im talking about for what I would like to do. Variable D is the 8 bit sequence that I want displayed

    Move '100000000' into D
    Take first bit, Change GPO to what first bit is
    Clock it
    Take second bit, Change GP0 to what second bit is
    Clock it

    etc...

    Latch

    Goto next sequence
     
    Last edited: Sep 4, 2008
  14. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    Umm... Put your brain in gear, get some scribble paper and calculator ready and start coding! :D Start small. Every time you get some section working, save that version of the source code with a different name so you can come back to it and start over if the next thing you do breaks things totally.

    This might be a bit much for you if you're still at the beginner stage. You'll need to be able to use and understand timers and interrupts to get this to work right.

    EDIT
    That's a start! :D Keep going!
     
    Last edited: Sep 4, 2008
  15. Darkstar64

    Darkstar64 New Member

    Joined:
    Apr 3, 2008
    Messages:
    112
    Likes:
    0
    haha can you atleast tell me how to take a single bit from a sequence after that everything should be simple thats the thing im stuck on :D
     
  16. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    Use RLF or RRF to rotate the high or low bit (your choice) into the carry. Then do a check of the carry flag to see if it's 1 or 0 to determine what to put on the data pin to be shifted next.

    There are other ways to do it too. Use your imagination.
     
  17. Darkstar64

    Darkstar64 New Member

    Joined:
    Apr 3, 2008
    Messages:
    112
    Likes:
    0
    Ya you lost me at RLF haha wow this may seem alot more complicated then I thought it would be there's no simple way to take a string and seperate it is there ? haha I've just looked on google with little answer's the only problem is that the 509 doesn't have a interrupt so im not sure what to do from there. I know how to place the string into a variable then read that variable im just not sure how to take each bit apart. I also know how how to write it too the pin I just can't take the bit's apart and thats the problem bc soon as I get that my code goes from a whole bunch of lines to almost half and making sequences are so much easyer as well. Also I think if I understand it right your way of doing it with RLF will only allow me to have on pin on at a time
     
    Last edited: Sep 4, 2008
  18. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    That's why I said you might be a bit too green to tackle something like this. :p

    A byte is not a string. And rotating the bit you want to test into the carry is pretty darn simple.

    Oh! This is that PIC. I really would recommend you use a bigger, more capable PIC for a job like this. Without interrupts, and with so few resources, this will be hard! Get a 16F88 or better yet, an 18F1320. Or even a bigger PIC. The little 8-pinners are tough for beginners. They're tight for resources and pins. Great for saving money if you're in production or your project is very simple, but tough to do more complex things without a lot of planning and knowhow.

    Learning how to isolate, move and test bits, nybbles and whole bytes is what it's all about when programming PICs (or any computer) in any but the most elementary way. You must understand bit operations fluently before you'll be able to complete a project like this.

    Sounds very much like you need to work up to a project like this. Start with some simpler projects (sub-sections of this project would be great!) and gradually you'll learn the things you need to know to tackle tougher projects like a LED cube.

    Not true at all. You just keep rotating bits in and checking them, and putting the results on the data line and clocking them out.
     
    Last edited: Sep 4, 2008
  19. Darkstar64

    Darkstar64 New Member

    Joined:
    Apr 3, 2008
    Messages:
    112
    Likes:
    0
    ok ya I might have to work up to it like you said can you give me a few project names or links too where I can start learning more about this ?
     
  20. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    Start by breadboarding up your 12F509 and the 74HC595 with 8 LEDs. Tinker with getting the 595 to light LEDs under your control. Learn to use rlf and rrf.

    Once you have that working, take the high nybble of one byte and use that to light the left 4 LEDs and take the low nybble of another byte and use that to light the right 4 LEDs. Have fun!
     
    Last edited: Sep 5, 2008
  21. Darkstar64

    Darkstar64 New Member

    Joined:
    Apr 3, 2008
    Messages:
    112
    Likes:
    0
    Srry im still not understanding We have the whole thing figured out other then the engine now looking at one that was made before by someone ealse who was helping me but we were not using shift regiesters at the time it looks like this using just the I/0 pins on the PIC. Also since im going to be using all the I/0 pins on the pick what do I need to do In curcuit programming. I'm not sure what pins the 509 uses to program and what I need to do to seperate the PIC from the rest of the curcuit as well. When I am programming the PIC I know it needs to be seperated from everything so that it doesn't fail in programming. Ok I get what rlf and rrf do now they move the bits left and right now from there I just write the carry bit to the data pin and move to the next bit right ? Now how do I write the carry flag im not sure what location its in ? Basically your telling me to first set what LED's I want on by something like this b'10100100'. Then I would use RLF to move the first bit into the carry flag and write that to the data pin. Then I would then use RLF again and that would take the bit in the carry flag and move it too the end so it would then be '01001001' right ? and put the new bit in then I would write that to the shift etc etc ?
     
    Last edited: Sep 5, 2008

Share This Page