Continue to Site

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.

  • 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.

Working with Shift Registers and a PIC help

Status
Not open for further replies.

Darkstar64

New Member
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:
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:
#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:
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);
		}
	}
}
 
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 ?
 
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 ?
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:
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:
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 :(
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?

I also have a concern though about how the Multiplexing of a 3D LED cube works
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).

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
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:
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 https://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:
;    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:
Doesn't even matter how fast I do it so I won't need a delay in between each one?
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.

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
High and back low again. Just blip it to latch the data, same as you just blip the clock to clock in bits.

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 to. I'm not sure if there is a better way to write it ?
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:
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:
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:
;**********************************************************************                                                                     
;    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 !
 
Not too sure what your getting at with the whole engine thing
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.

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?
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.

Just because its going to take alot of code and I don't think the PIC will be able to hold that much
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:
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:
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?
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.

I'm sorry. I'm 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. Sorry. :(
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
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
That's a start! :D Keep going!
 
Last edited:
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
 
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
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.
 
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:
Ya you lost me at RLF haha wow this may seem alot more complicated then I thought it would be
That's why I said you might be a bit too green to tackle something like this. :p

there's no simple way to take a string and seperate it is there?
A byte is not a string. And rotating the bit you want to test into the carry is pretty darn simple.

the only problem is that the 509 doesn't have a interrupt so im not sure what to do from there.
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.

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 easier as well.
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.

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
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:
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 ?
 
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 ?
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:
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:
Status
Not open for further replies.

Latest threads

Back
Top