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.

Needing a little help on inputs into PICS and the Limitations

Status
Not open for further replies.

Darkstar64

New Member
Hey Ive been working on some interesting code well interesting to me that is haha anyways it invloves the use of 4 12F509's using all the Pins from GP0 - GP5
but GP3 and GP5 are the inputs im currently looking for a way to have it scan the pins to see if the button is pressed or not and if its pressed I want to it loop a certain code untill the other button is pressed witch will do a different code here is what I have now

Code:
    	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  
dc1		; Delay Loop Counters
dc2		
dc3
shadow	; Shadow variable used in rain to keep all top leds on or for cycle to resest all bits to 0
delaytime	; Adjustable delay variable		
		endc


;************************************************* *********************  
; Internal RC calibration value is placed at location 0x3FF by Microchip  
; as a movlw k, where the k is a literal value.  

		org	0
MAIN		
		movwf	OSCCAL		; update register with factory cal value 


;******** Main Code

start
		movlw	b'101000'	; Configure only GP3 and GP5 as a input
		tris	GPIO
		
loop

waitdn	btfsc	GPIO,3		; Wait untill button is pressed on GP3 ( GP3 low )
		goto	waitdn

		call	Cycle

		movlw	.2
		pagesel delay10
		call	delay10		; Delay of 20ms to debounce GP3 ( GP3 low )
		pagesel $

waitdn2	btfsc	GPIO,5		; Wait untill button is pressed on GP5 ( GP5 low )
		goto	waitdn2

		call	Rain

		movlw	.2
		pagesel delay10
		call	delay10		; Delay of 20ms to debounce GP5 ( GP5 low )
		pagesel $

		goto	loop





;******** Main Subroutine's / Effects

Cycle
		movlw	.5
		movwf	delaytime
		movlw	b'000000'
		movwf	shadow
		call	lightledA
		call	lightledB
		call	lightledC
		call	lightledD
		call	lightledE
		call	lightledF
		call	lightledG
		call	lightledH
		call	lightledI
		call	lightledJ
		call	lightledK
		call	lightledL
		goto	Cycle

Rain

		movlw	b'000000'
		movwf	shadow
		movlw	.2
		movwf	delaytime
		call	lightledA
		call	lightledD
		call	lightledG
		call	lightledJ
		movlw	.9
		call	delay10
		movlw	.3
		movwf	delaytime
		call	lightledC
		call	lightledF
		call	lightledI
		call	lightledL
		movlw	.9
		call	delay10
		movlw	.9
		call	delay10
		movlw	.9
		movwf	delaytime
		call	lightledA
		call	lightledD
		call	lightledG
		call	lightledJ
		movlw	.9
		call	delay10
		movlw	.9
		call	delay10
		movlw	.9
		call	delay10
		movlw	.4
		movlw	delaytime
		call	lightledB
		call	lightledE
		call	lightledH
		call	lightledK
		goto	Rain

Randomeffect

		movlw	b'000000'
		movwf	shadow
		movlw	.2
		movwf	delaytime
		call	lightledE
		call	lightledH
		call	lightledA
		call	lightledB
		call	lightledC
		call	lightledF
		call	lightledI
		call	lightledL
		call	lightledK
		call	lightledJ
		call	lightledG
		call	lightledD
		call	lightledE
		call	lightledH
		call	lightledA
		call	lightledB
		call	lightledC
		call	lightledF
		call	lightledI
		call	lightledL
		call	lightledK
		call	lightledJ
		call	lightledG
		call	lightledD
		call	lightledE
		call	lightledH
		call	lightledA
		call	lightledB
		call	lightledC
		call	lightledF
		call	lightledI
		call	lightledL
		call	lightledK
		call	lightledJ
		call	lightledG
		call	lightledD
		goto	Randomeffect
		

	
		
		

;************* Subroutines

;****************** LED Subroutines 

lightledA
		movlw	b'111010'	; Configure GP4 and GP1 as input
		tris	GPIO
		movlw	b'000001'	; Change corresponding bit of GP0 to 1
		movwf	GPIO		; Writes 1 to GP0
		movlw	delaytime		; Get from dealytime variable
		call	delay10		; Delay of 50 x 10ms = 500ms or .5s
		movlw	shadow	; Change corresponding bit of GP0 to 0
		movwf	GPIO
		movlw	b'101000'	; Configure GP0,GP1,GP2,GP4 to outputs
		tris	GPIO			; Write 0 to GP0
		retlw	0

lightledB
		movlw	b'001110'	; Configure GP1 and GP2 as inputs
		tris	GPIO
		movlw	b'000001'	; Change corresponding bit of GP0 to 1
		movwf	GPIO		; Writes 1 to GP0
		movlw	delaytime		; Get from dealytime variable
		call	delay10		; Delay of 50 x 10ms = 500ms or .5s
		movlw	shadow	; Change correspoding bit of GP1 to 0
		movwf	GPIO
		movlw	b'101000'	; Configure GP0,GP1,GP2,GP4 to outputs
		tris	GPIO
		retlw	0

lightledC
		movlw	b'001110'	; Configure pins GP1 and GP2 to inputs
		tris	GPIO
		movlw	b'010000'	; Change corresponding bit of GP4 to 1
		movwf	GPIO		; Writes 1 to GP4
		movlw	delaytime		; Get from dealytime variable
		call	delay10		; Delay of 50 x 10ms = 500ms or .5s
		movlw	shadow	; Change correspoding bit of GP4 to 0
		movwf	GPIO
		movlw	b'101000'	; Configure GP0,GP1,GP2,GP4 to outputs
		tris	GPIO
		retlw	0

lightledD
		movlw	b'011001'	; Configure pins GP1 and GP4 to inputs
		tris	GPIO
		movlw	b'000100'	; Change corresponding bit of GP2 to 1
		movwf	GPIO		; Writes 1 to GP2
		movlw	delaytime		; Get from dealytime variable
		call	delay10		; Delay of 50 x 10ms = 500ms or .5s
		movlw	shadow	; Change correspoding bit of GP2 to 0
		movwf	GPIO
		movlw	b'101000'	; Configure GP0,GP1,GP2,GP4 to outputs
		tris	GPIO
		retlw	0

lightledE
		movlw	b'011001'	; Configure pins GP0 and GP4 to inputs
		tris	GPIO
		movlw	b'000010'	; Change corresponding bit of GP1 to 1
		movwf	GPIO		; Writes 1 to GP1
		movlw	delaytime		; Get from dealytime variable
		call	delay10		; Delay of 50 x 10ms = 500ms or .5s
		movlw	shadow	; Change correspoding bit of GP2 to 0
		movwf	GPIO
		movlw	b'101000'	; Configure GP0,GP1,GP2,GP4 to outputs
		tris	GPIO
		retlw	0

lightledF
		movlw	b'001101'	; Configure pins GP0 and GP2 to inputs
		tris	GPIO
		movlw	b'010000'	; Change corresponding bit of GP4 to 1
		movwf	GPIO		; Writes 1 to GP4
		movlw	delaytime		; Get from dealytime variable
		call	delay10		; Delay of 50 x 10ms = 500ms or .5s
		movlw	shadow	; Change correspoding bit of GP4 to 0
		movwf	GPIO
		movlw	b'101000'	; Configure GP0,GP1,GP2,GP4 to outputs
		tris	GPIO
		retlw	0

lightledG
		movlw	b'011100'	; Configure pins GP2 and GP4 to inputs
		tris	GPIO
		movlw	b'000010'	; Change corresponding bit of GP1 to 1
		movwf	GPIO		; Writes 1 to GP1
		movlw	delaytime		; Get from dealytime variable
		call	delay10		; Delay of 50 x 10ms = 500ms or .5s
		movlw	shadow	; Change correspoding bit of GP0 to 0
		movwf	GPIO
		movlw	b'101000'	; Configure GP0,GP1,GP2,GP4 to outputs
		tris	GPIO
		retlw	0

lightledH
		movlw	b'011001'	; Configure pins GP0 and GP4 to inputs
		tris	GPIO
		movlw	b'000100'	; Change corresponding bit of GP2 to 1
		movwf	GPIO		; Writes 1 to GP2
		movlw	delaytime		; Get from dealytime variable
		call	delay10		; Delay of 50 x 10ms = 500ms or .5s
		movlw	shadow	; Change correspoding bit of GP2 to 0
		movwf	GPIO
		movlw	b'101000'	; Configure GP0,GP1,GP2,GP4 to outputs
		tris	GPIO
		retlw	0

lightledI
		movlw	b'001011'	; Configure pins GP0 and GP1 to inputs
		tris	GPIO
		movlw	b'000110'	; Change corresponding bit of GP1 to 1
		movwf	GPIO		; Writes 1 to GP1
		movlw	delaytime		; Get from dealytime variable
		call	delay10		; Delay of 50 x 10ms = 500ms or .5s
		movlw	shadow	; Change correspoding bit of GP1 to 0
		movwf	GPIO
		movlw	b'101000'	; Configure GP0,GP1,GP2,GP4 to outputs
		tris	GPIO
		retlw	0

lightledJ
		movlw	b'011100'	; Configure pins GP2 and GP4 to inputs
		tris	GPIO
		movlw	b'001001'	; Change corresponding bit of GP0 to 1
		movwf	GPIO		; Writes 1 to GP0
		movlw	delaytime		; Get from dealytime variable
		call	delay10		; Delay of 50 x 10ms = 500ms or .5s
		movlw	shadow	; Change correspoding bit of GP1 to 0
		movwf	GPIO
		movlw	b'101000'	; Configure GP0,GP1,GP2,GP4 to outputs
		tris	GPIO
		retlw	0

lightledK
		movlw	b'011001'	; Configure pins GP0 and GP4 to inputs
		tris	GPIO
		movlw	b'000010'	; Change corresponding bit of GP1 to 1
		movwf	GPIO		; Writes 1 to GP1
		movlw	delaytime		; Get from dealytime variable
		call	delay10		; Delay of 50 x 10ms = 500ms or .5s
		movlw	shadow	; Change correspoding bit of GP0 to 0
		movwf	GPIO
		movlw	b'101000'	; Configure GP0,GP1,GP2,GP4 to outputs
		tris	GPIO
		retlw	0

lightledL
		movlw	b'001110'	; Configure pins GP0 and GP1 to inputs
		tris	GPIO
		movlw	b'010000'	; Change corresponding bit of GP4 to 1
		movwf	GPIO		; Writes 1 to GP4
		movlw	delaytime		; Get from dealytime variable
		call	delay10		; Delay of 50 x 10ms = 500ms or .5s
		movlw	shadow	; Change correspoding bit of GP0 to 0
		movwf	GPIO
		movlw	b'101000'	; Configure GP0,GP1,GP2,GP4 to outputs
		tris	GPIO
		retlw	0

;****************** Delay Subroutine ( 10 ms )

delay10					; Delay W x 10ms 
		movwf	dc3		; Delay = 1 + W x (3 + 10009 + 3) - 1 + 4 -> W x 10.015ms
dly2		movlw	.13		; Repeat inner loop 13 times
		movwf	dc2		; -> 13 x (767 + 3) - 1 = 10009 cycles
		clrf	dc1		; Inner loop = 256 x 3 - 1 = 767 cycles
dly1		decfsz	dc1,f
		goto	dly1
		decfsz	dc2,f		; End middle loop
		goto	dly1
		decfsz	dc3,f		; End outer loop
		goto	dly2
		retlw	0

		end
 
Hey Ive been working on some interesting code well interesting to me that is haha anyways it invloves the use of 4 12F509's using all the Pins from GP0 - GP5
but GP3 and GP5 are the inputs im currently looking for a way to have it scan the pins to see if the button is pressed or not and if its pressed I want to it loop a certain code untill the other button is pressed witch will do a different code
12F509's have no interrupts!?!?!!! That makes things somewhat more difficult for you. You have no choice but to poll, which can make response to button presses lag or even get missed if you're trying to get other things done at the same time.

Switch to the 12F683 (only a little more $$) and all GPIO pins have interrupt-on-change ability. Makes what you're trying to do trivially easy.
 
Yes but currently im working with the 509's as a starter even if I can't use Intrrupts can I at least do this useing the Multiplex thoery have 4 switchs 2 on GP3 and 2 on GP5 then when these are pressed they then exect a call of a certain subroutine?
 
Yes but currently im working with the 509's as a starter even if I can't use Intrrupts can I at least do this useing the Multiplex thoery have 4 switchs 2 on GP3 and 2 on GP5 then when these are pressed they then exect a call of a certain subroutine?
OK then, I'm not clear on what you mean by "you're using four 12F509's" and "you have two switches on one GP3 pin???" and "two switches on one GP5 pin???"

How about a rough schematic? Just scratch something out quick with Paint or something.
 
Do you mean you want to connect four switches to two pins? Sounds like you do. I did some schematic scratching and, unless I'm mistaken (could be), it can't be done. You need four pins for four switches.

If the 12F509 had A/D (it doesn't) you could do four switches with one pin. Again, the 12F683 would work fine for this. The 509 is pretty lame.
 
nvm I was thinking for a sec the 509 had A/D haha so nvm about that just 2 simple switches then connected to all 4 PIC's so that once one switch is pressed it calls the one program and all the PIC's and when the other switch is pressed it calls another program on all the PIC's ya was a little tired last night haha just got of work and such so so to make it a little easyer to understand its like this all 4 PIC's will have the same program on it now lets say I want the Rain effect so LED's lighting from the top down I would hit switch one that would then call the program on all the PIC's because the switch is hooked on to all the GP3 pins on the 4 PIC's and the same thing with the other switch but this one will cycle the LED's in some way but it will be attached to all the GP5 pins so that I don't have to exec each PIC manually with 4 seperate switchs one for each PIC I can hit one switch and it does it
 
Last edited:
One way to look at it, is just use one button for however many programs you wish to implement. As mentioned, you will be polling your pin, just include a counter and a call to your program based on the counter. As Futz mentioned, it can be a little sketchy, depends on how long it takes to cycle thru your code.
 
Um ok so then how would I go about implenting the code though for some reason the code I have now is not working correctly
 
In psuedo code, sorry not into assembler, so hopefully you catch the drift?

Code:
Press = 0
Main:
If GPIO.3 On
    Press = Press + 1
    If Press = 2 Then  Press = 0
End If
If Press = 1 Then goto Rain
Cycle
....
Rain
...
 
one possible solution

This is what I have done in the past it's pretty crude but you got a lot of unused memory to play with in a small program like this. Make your three main loops "cycle" "randomeffect" and "rain" then insert these little codes every once in a while. If you do it often enough you don't miss very often. This way you are poling one switch which frees up a pin to do more lights.

Code:
btfss	GPIO,1		;test to see if button is pressed
goto	$+2			;if pressed skip goto $+2 and do goto cycle
goto	cycle 		;if not pressed goto $+2 will skip calling the next 
				;lighting effect and continue the program
btfss	GPIO,1		
goto	$+2			
goto	randomeffect

btfss	GPIO,1
goto	$+2
goto	rain


(atferrari-NVM means "never mind" it's a chat room way of writing things not common in a scientific forum but you will see it)
 
ok thanks is there a way to cycle though them I know im picky and all so like if I hit it once it plays cycle then if I hit it again within lets say 5 s of the first hit it will play Randomeffect and again if I hit it again within 5 s of the second hit it will play Rain Im not too sure the 509 can do this without inturrups just a idea and if that doesnt work then im just going to have it so one switch does one effect and the other another effect but I need help with the code for both if the first isn't possible then the second is ok
 
What else is your pic doing, for example when you say "play", is it working hard doing something?

Basically you'd start another counter, which, experimentally, you'd adjust for your 5 second requirement.

You might also be able to read a timer and store it, then when the button is pressed again, read the timer and compare, but I'm not sure that has the resolution you need (check your data sheets).

SO for example, you receive button 1.

set counter5 (the 5 second counter) to some value, then within your program, decrement counter 5, and when it is zero stop decrementing it.

That way, when you see a button push, you can say "is my 5-second count-down timer zero? If so, this is NOT a button push within 5 seconds".

Now, since PICs can execute millions of instructions per second, you will have to scale this 5 second counter some how - because a 1-byte i.e. 8-bit counter will count down in milliseconds if not microseconds. But if you count down ANOTHER byte (whose value you may not even have to set), and every time it "passes" zero, you count down your 5-secon counter, then possibly add a 3rd byte
Lets say the counters are at c5, c5+1, and c5+2, where only c5 really needs to be "calibrated" because you need no precision.

if c5 = 0 then go to where you are saying no, this is not a 2nd button push
decrement c5+2, and if it crosses 0, decrement c5+1, and if it crosses 0, decrement c5.

This gives you a loop of 3 bytes = 12 bits = up to 4096 counts. If you have something that your computer is doing that takes some time, just call this decrement loop every now and then (like, if your other part has a 200 instruction loop, you call this every 200 instructions)...

I'm sure there are other ways. This way is extensible, in that if you add a 4th byte to count down, you now have a 16-bit word and 65536 counts to zero it...

If you need more details, let me know. Others feel free to jump in with any answers should I not be back in time.
 
BTW, I am very good at pseudo random number generators. I mean as a simple hobbyist / hacker.

Waaaaay back teaching myself digital electronics, I played with a shift register chip, and I exclusive Or'ed bits from the end and say 3 from the end, and fed that back in.

As long as you have at least one bit on, you get a "pseudo random" pattern in the shift register.

years later, I used this trick to write a program called "scramble", in which a huge shift register was initialized with a "key" (password), I'd then run this shift-and-xor software register a few (thousand?) loops, then start pulling out a byte at a time, and XORing DATA with it to "scramble it" in a known way, writing it back upon the original data.

To unscramble the file you'd just run the exact same program with the exact same key and it would make pseudo-random numbers but exactly the same as last time, and thus since xor twice "un-does" the changes.

THEN I played - with another means, division remainder.

If you take a number, and multiply by X and take remainder divided by Y, giving you a new number, this, given carefully chosen numbers, will "randomly" go through the 0-y or maybe 1 to y-1 or etc range.

ex: start with 1, then each new random number is defined as remainder of (93 * prev) when divided by 71. This produces 70 numbers, in the pseudorandom sequence of 1 22 58 69 27 26 4 17 19 63 37 33 16 68 5 39 6 61 64 59 20 14 24 31 43 23 9 56 25 53 30 21 36 11 29 70 49 13 2 44 45 67 54 52 8 34 38 55 3 66 32 65 10 7 12 51 57 47 40 28 48 62 15 46 18 41 50 35 60 42 then back to 1.

Needless to say since the pic doesn't have multiply or divide, tho you can do them in routines via adding and subtracting, the xor shift register trick works well.

Here is the code - I use a 10-byte shift register, and xor the last and 3rd last bits back into the beginning.

My main routine is "wloop" which ends in this random number generator (get next random number) and then loops back to wloop.

Of course, somewhere in wloop, is a routine that takes one of the bytes or bits or whatever you want out of the 10-byte shift register, and "uses it" as a random number.

Specifically I was creating a random blink of a 5 x 7 bi-color LED matrix, and when done, doggone it (my age is showing) if it didn't look like the nuclear reactor in the SeaView!

Code:
        movlw   d'10'        ; # of bytes (in0 -in9) to shift
        movwf   wardscount   ; in in0-in9, my 10-byte shift register
                             ;
        movlw   in0          ; trying to "get address of" see if this works
        movwf   FSR          ; FSR points to in0
                             ;
        bcf     STATUS,C     ; don't want carry etc to shift into first byte
wlp2    rlf     INDF,F       ; Rotate one of the bytes in0 through in9
        incf    FSR,F        ;      then point to the next byte to continue
        decfsz  wardscount,F ; are we done with 10 bytes?
        goto    wlp2         ;      no, continue shifting 10 bytes
                             ;
                             ;
        btfss   in9,7        ; Test the 80 bits for 1xxxx....xxxxx
        goto    win97z       ; Test the 80 bits for xxx1x....xxxxx
        btfsc   in9,4        ;
        goto    wloop        ; Loop if BOTH set (Exclusive or - exclusive of both 1)
        goto    wbit         ; set the bit
                             ;
win97z                       ;
        btfss   in9,4        ;
        goto    wloop        ;      just loop
wbit                         ;
        movlw   1            ; otherwise 'or' on low bit again
        iorwf   in0,f        ;      in in0
        goto    wloop        ;

Ah, I just remembered - in this 5 x 7 LED matrix, the in0..inX - were the bytes actually displayed, so it was displaying my random number.

I hope no one minds my long rambling appends!
 
Last edited:
Waaaaay back teaching myself digital electronics...

I hope no one minds my long rambling appends!
Not at all. Are you really the real Ward Christensen? If so, I am in awe! :eek: You're famous! I remember using xmodem and all those other protocols in the old dial-up days. I started out with a 300 baud acoustic coupled modem. Horrible thing, but it got me "online" to the BBS's and various nets that existed at the time (no internet yet).
 
Hmm sounds interesting the Ideas im getting from the help here ahaha I will work with some of these Ward with your code will I be able to execute a subroutine or just numbers with your pseudo random generater based on the numbers ? Just a quick question before I start implementing any of it and also with your count down idea thats a very interesting Idea im going to have to look more into that it seems like it may be the way im going to implment this since I want the ablilty to execute the different effects im making but only have the 2 input pins avaliable
 
Yep, that's me. I think I burned myself out on Xmodem, BBSs, all that CP/M stuff, and never 'graduated' to the PC (assembler, etc) very much. Some C etc.

PICs catch my fancy now
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top