Pic 12F675

Thread Starter

peter_morley

Joined Mar 12, 2011
179
In this program I want to get input from GPIO2 using a momentary switch. I can get input from pin 4 which is GPIO 3 but I want to get input from both. I'm been trying to tackle this for awhile and I feel I could use a couple tips. I pasted the code below and look at the code portion where I call State3 and my condition is that GPIO2 is set high in order for that function to be called.


Rich (BB code):
	list      p=12f629            ; list directive to define processor
	#include <p12f629.inc>        ; processor specific variable definitions

	errorlevel  -302              ; suppress message 302 from list file

	__CONFIG   _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_ON & _PWRTE_ON & _INTRC_OSC_NOCLKOUT  

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

;************************** VARIABLE DEFINITIONS ******************************

      cblock	0x20			
	STATE_LED			; LED state machine counter
	STATE_DEBOUNCE			; button debounce state machine counter
      endc

;*************************** DEFINE STATEMENTS ********************************

; input and output definitions	

#define SW1		GPIO,3		; toggle switch 1
#define SW2		GPIO,2 		; toggle switch 2

; define input/output designation for LEDs (what TRISIO will equal)

#define TRIS_D0_D1	B'00001111'	; TRISIO setting for D0 and D1
#define TRIS_D2_D3	B'00101011'	; TRISIO setting for D2 and D3
#define TRIS_D4_D5	B'00011011'	; TRISIO setting for D4 and D5
#define TRIS_D6_D7	B'00111001'	; TRISIO setting for D6 and D7
#define allInputs	B'00111111'	; TRISIO setting D0-D7 as inputs

; define LED state (what GPIO will equal)

#define D0_ON	B'00010000'		; D0 LED
#define D1_ON	B'00100000'		; D1 LED
#define D2_ON	B'00010000'		; D2 LED
#define D3_ON	B'00000100'		; D3 LED
#define D4_ON	B'00100000'		; D4 LED
#define D5_ON	B'00000100'		; D5 LED
#define D6_ON	B'00000100'		; D6 LED
#define D7_ON	B'00000010'	 	; D7 LED
#define Blank	B'00000000' 	; All LEDs off

;****************************** Start of Program ******************************
	org     0x000			; processor reset vector
	goto	Initialize

;******************************************************************************
; Initialize
;	Initialize Special Function Registers     
;******************************************************************************
	org	0x005			; Start of Programm Memory Vector
Initialize
	;call    0x3FF      ; retrieve factory calibration value
						; comment instruction if using simulator, ICD2, or ICE2000
	bsf     STATUS,RP0		; Bank 1 
	movwf   OSCCAL			; update register with factory cal 
					;  value 
	movlw	B'00111111'		; Set all I/O pins as inputs
	movwf	TRISIO			
	
	movlw	B'10000100'		; Weak pullups: disabled
	movwf	OPTION_REG		; TMR0 prescaler: 1:32 (TMR0 will 
					;  overflow in 8.2ms)
	clrf	INTCON			; disable all interrupts, clear all 
					;  flags	
	bcf     STATUS,RP0		; Bank 0
	clrf	GPIO			; clear all outputs
	clrf 	TMR0			; clear Timer 0
	clrf	STATE_LED		; clear LED state machine counter
	clrf	STATE_DEBOUNCE		; clear debounce state machine counter

;******************************************************************************
; State_Machine
;	Implements a state machine that lights up the LEDs on the PICkit board
;       sequentially when SW1 is pressed.     
;******************************************************************************

StateMachine

	btfss	SW1
	call	State0			;   mented by STATE_LED in order
	btfss	SW1
	call	State1
	btfss	SW1
	call	State2
	btfss	SW2
	call	State3
	bsf	STATUS, RP0			; Bank 1
	movlw	allInputs		; make all inputs in TRISIO
	movwf	TRISIO
	btfsc	SW1
	call	Restart
	goto	StateMachine

Restart
	bcf	STATUS, RP0			; Bank 0
	movlw	Blank			; move predefined value to GPIO
	movwf	GPIO
	return 
	
State0						
; Turns on D0 LED
	bsf	STATUS, RP0		; Bank 1
	movlw	TRIS_D0_D1		; move predefined value to TRISIO
	movwf	TRISIO
	bcf	STATUS, RP0		; Bank 0
	movlw	D0_ON			; move predefined value to GPIO
	movwf	GPIO
	return

State1
; Turns on D1 LED
	bsf	STATUS, RP0		; Bank 1
	movlw	TRIS_D0_D1		; move predefined value to TRISIO
	movwf	TRISIO
	bcf	STATUS, RP0		; Bank 0
	movlw	D1_ON			; move predefined value to GPIO
	movwf	GPIO
	return 	
	
State2
; Turns on D2 LED
	bsf	STATUS, RP0		; Bank 1
	movlw	TRIS_D2_D3		; move predefined value to TRISIO
	movwf	TRISIO
	bcf	STATUS, RP0		; Bank 0
	movlw	D2_ON			; move predefined value to GPIO
	movwf	GPIO
	return
State3
; Turns on D3 LED
	bsf	STATUS, RP0		; Bank 1
	movlw	TRIS_D2_D3		; move predefined value to TRISIO
	movwf	TRISIO
	bcf	STATUS, RP0		; Bank 0
	movlw	D3_ON			; move predefined value to GPIO
	movwf	GPIO
	return
 

ErnieM

Joined Apr 24, 2011
8,377
Your state machine switch is not properly coded:

Rich (BB code):
    btfss    SW1
    call    State0            ;   mented by STATE_LED in order
    btfss    SW1
    call    State1
    btfss    SW1
    call    State2
    btfss    SW2
    call    State3
You test SW1 twice with the same test expecting 2 different destinations. Same with State2. Also, are you sure you want to return back to the middle of the switch?

Also, GP2 is configured as analog until you clear the ANSEL bit for it.
 
Last edited:

Thread Starter

peter_morley

Joined Mar 12, 2011
179
How do I clear the ANSEL bit do I do something like this...clrf ANSEL? I just started programming pics yesterday so I've got a learning curve ahead of me. I have programmed multiple microcontrollers but PICs seem to be a little different than what I'm used to.
 

Thread Starter

peter_morley

Joined Mar 12, 2011
179
I made my code to wait until user presses a momentary switch on GPIO3 or GPIO2. When GPIO3 is pressed GPIO5 should be set to high 5V.
When GPIO2 is pressed GPIO4 should be set to high 5V. I am getting voltages from the output of both GPIO 4 and 5 whenever I press a certain momentary switch. The voltages are not 5V though they are around 2-2.5 volts. I thought I made all inputs and outputs digital but I guess not. Any suggestions to fix this?

Rich (BB code):
list      p=12f675            ; list directive to define processor
#include <p12f675.inc>        ; processor specific variable definitions

	__CONFIG   _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_ON & _PWRTE_ON & _INTRC_OSC_NOCLKOUT  

;*************************** DEFINE STATEMENTS ********************************

; Register Bank Directories	

#define Bank0	banksel 0x00		; first registerr bank = Bank 0
#define Bank1	banksel 0x80		;second register bank = Bank 1

; Momentary switch inputs

#define SW1			GPIO,3			; toggle switch at GPIO 3
#define SW2			GPIO,2 			; toggle switch at GPIO 2
#define I_O			B'00001100'		; TRISIO setting makes GPIO2/3 inputs and the rest outputs
#define Digital		B'00111111'		; makes all GPIO digital pins
#define Blank		B'00000000' 	; All LEDs off

;****************************** Start of Program ******************************
	org     0x000			; processor reset vector
	goto	Initialize

;******************************************************************************
; Initialize
;	Initialize Special Function Registers     
;******************************************************************************
	org	0x005			; Start of Programm Memory Vector
Initialize

	Bank0
	clrf GPIO 			;Init GPIO
	movlw Digital 		;Set GP<2:0> to
	movwf CMCON 		;digital IO
	Bank1 				;Bank 1
	clrf ANSEL 			;Digital I/O	
	movlw 0Ch 			;Set GP<3:2> as inputs
	movwf TRISIO 		;and set GP<5:4,1:

;******************************************************************************
; State_Machine
;	Implements a state machine that lights up the LEDs on the PICkit board
;       sequentially when SW1 is pressed.     
;******************************************************************************

StateMachine

	btfss	SW1				; if GPIO 3 is pulled low then
	call	G5Set			; call G5Set to make GPIO 5 high
	btfss	SW2				; if GPIO 2 is pulled low then		
	call	G4Set			; call G4Set to make GPIO 4 high
	call	Restart
	goto	StateMachine

Restart
	bcf	STATUS, RP0			; Bank 0
	movlw	Blank			; clears pins of GPIO
	movwf	GPIO
	return 
	
G5Set						

	Bank0						; Bank 0
	movlw	B'00000001'			; set GPIO5
	movwf	GPIO
	return

G4Set

	Bank0						; Bank 0
	movlw	B'00000010'			; set GPIO4
	movwf	GPIO
	return 	

	end                     	; directive 'end of program'
 

ErnieM

Joined Apr 24, 2011
8,377
You still have not fixed the state machine code as I mentioned in post #3. Follow the call back thru the return and see you ALWAYS call Restart.
 

Markd77

Joined Sep 7, 2009
2,806
A floating input can read at about that level. Connect the pin with a 1K resistor to either 0V or 5V and measure the pin voltage again. It should now read 0V or 5V. Floating inputs aren't a good idea and can cause device resets.
 

Thread Starter

peter_morley

Joined Mar 12, 2011
179
You still have not fixed the state machine code as I mentioned in post #3. Follow the call back thru the return and see you ALWAYS call Restart.
I just changed it, i'm not sure if this will work because I am just starting to use registers and the syntax is weird for me.


movlw SW1
andlw SW2
btfsc SW1
call Restart

What I think this does is moves GPIO 3 value to register w so register w looks like this 00000001 if the GPIO is not pressed. Then I would AND w and SW2 which contains GPIO2 value 1 if not pressed. Then only when both are high will the restart function be called to reset. Otherwise we need to evaluate a key press.


Rich (BB code):
list      p=12f675            ; list directive to define processor
#include <p12f675.inc>        ; processor specific variable definitions

	__CONFIG   _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_ON & _PWRTE_ON & _INTRC_OSC_NOCLKOUT  

;*************************** DEFINE STATEMENTS ********************************

; Register Bank Directories	

#define Bank0	banksel 0x00		; first registerr bank = Bank 0
#define Bank1	banksel 0x80		;second register bank = Bank 1

; Momentary switch inputs

#define SW1			GPIO,3			; toggle switch at GPIO 3
#define SW2			GPIO,2 			; toggle switch at GPIO 2
#define I_O			B'00001100'		; TRISIO setting makes GPIO2/3 inputs and the rest outputs
#define Digital		B'00111111'		; makes all GPIO digital pins
#define Blank		B'00000000' 	; All LEDs off

;****************************** Start of Program ******************************
	org     0x000			; processor reset vector
	goto	Initialize

;******************************************************************************
; Initialize
;	Initialize Special Function Registers     
;******************************************************************************
	org	0x005			; Start of Programm Memory Vector
Initialize

	Bank0
	clrf GPIO 			;Init GPIO
	movlw Digital 		;Set GP<2:0> to
	movwf CMCON 		;digital IO
	Bank1 				;Bank 1
	clrf ANSEL 			;Digital I/O	
	movlw 0Ch 			;Set GP<3:2> as inputs
	movwf TRISIO 		;and set GP<5:4,1:

;******************************************************************************
; State_Machine
;	Implements a state machine that lights up the LEDs on the PICkit board
;       sequentially when SW1 is pressed.     
;******************************************************************************

StateMachine
	
	movlw	SW1
	andlw	SW2
	btfsc	SW1
	goto	Restart
	
	btfss	SW1				; if GPIO 3 is pulled low then
	call	G5Set			; call G5Set to make GPIO 5 high
	btfss	SW2				; if GPIO 2 is pulled low then		
	call	G4Set			; call G4Set to make GPIO 4 high
	
	goto	StateMachine

Restart
	bcf	STATUS, RP0			; Bank 0
	movlw	Blank			; clears pins of GPIO
	movwf	GPIO
	goto          StateMachine
	
G5Set						

	Bank0						; Bank 0
	movlw	B'00000001'			; set GPIO5
	movwf	GPIO
	return

G4Set

	Bank0						; Bank 0
	movlw	B'00000010'			; set GPIO4
	movwf	GPIO
	goto	StateMachine
	

	end                     	; directive 'end of program'
 
Last edited:

Thread Starter

peter_morley

Joined Mar 12, 2011
179
A floating input can read at about that level. Connect the pin with a 1K resistor to either 0V or 5V and measure the pin voltage again. It should now read 0V or 5V. Floating inputs aren't a good idea and can cause device resets.
I'm still getting 2-2.5 volts on those pins with 1k resistors attached to ground.
 

Markd77

Joined Sep 7, 2009
2,806
The first 2 instructions here aren't doing what you think they are. Most PIC instructions operate on whole bytes.


movlw SW1
andlw SW2
btfsc SW1
call Restart
Also in the config line I'd recommend _WDT_OFF otherwise the PIC will reset itself regularly and very quickly.
 

THE_RB

Joined Feb 11, 2008
5,438
Your state machine does not have any delays or debouncing!

So when you press SW1 it will perform state0, State1 etc in extremely rapid succession.

I suggest you add a debounce routine, the easiest reliable way is after any SW press is detected, you wait until the switch is released for >X amount of time.

You can do this with code like;
Rich (BB code):
; function to debounce a button (will loop here until SW1 is properly released)
debounce_SW1    
    clrf TMR0   ;  reset timer
debSW1_loop
    btfss SW1   ;   test switch again
    clrf TMR0   ;    keep clearing timer if switch still pressed!
    btfss TMR0,F7  ;exit when TMR0 >=128
    goto debSW1_loop   ;
    return   ;
So at the end of your State0 code you call "debounce_SW1" and it will wait until the SW1 button has been released for at least 128 contiguous counts of timer 0. If you set TMR0 prescaler right in the OPTION_REG register you can make that a nice debounce time of 20mS to 50mS.
 
Last edited:

Thread Starter

peter_morley

Joined Mar 12, 2011
179
In that case it is likely to be an output that is rapidly toggling between 1 and 0. A multimeter will average so you just see a value in between.
Great insight about the voltage. Ernie also told me to change that and when I got it working it was fine. And yea I need debouncing.
 

stahta01

Joined Jun 9, 2011
133
Rich (BB code):
#define SW1            GPIO,3            ; toggle switch at GPIO 3 
#define SW2            GPIO,2             ; toggle switch at GPIO 2
Did you all see how SW1 and SW2 are defined; I guessing this NOT what is normally done or expected.

Edit: The "movlw SW1" becomes "movlw GPIO,3" which, I guess, should not assemble.

This is more common in the small amount of code I have read; note putting comments after a define is not standard practice, I am not sure if it is a safe idea.
Rich (BB code):
#define SW1            GPIO3
#define SW2            GPIO2
I am far from a PIC expert; so, use my advice with a little caution.

Edit: If I recall correctly, movlw means move literal to w; so it will not work with either of above defines.

Tim S.
 
Last edited:
Top