# PIC 16F877 timer

Status
Not open for further replies.

#### falleafd

##### New Member
h'11' = b'00010001' not b'00100001', that is rb0 and rb4 are inputs.

I don't remember exactly, but if i'm right, there is a problem that if a pin of a port is set to output, the pull up resistor will be removed. Therefore, you cannot push portB <1> if you are setting it as output.

Be careful with this.

Why don't you movlw h'ff' or you can use binary numbers for sure in this case?

scan the port is good, no problem. Because as you push, you must hold down it longer than your short program takes to re-scan. However, if you write a long program, it may causes problems. Because as you push the button, the program is still running somewhere, and you lift your finger up, the program is still running somewhere. It cannot detect the changes at the port. In this case, you must use interrupts.

#### Exo

##### Active Member
Afther the bit tests i see a GOTO B1_Routine and B2_Routine, where are these? I can only see a B1_Response and a B2_Response further down...

Did you mix them up?

Secondly how did you connect your inputs? Do remeber that the pic's inputs must always be in a known state. So just connecting an input to VDD with a switch isn't enough. When you release the button the pin will be floating (connected to nothing) wich will cause strange behaviour.

I recomment putting a pull-up resistor from about 10K from the input pin to VDD and then connecting the input pin to ground with a switch.
When the button is not pressed the input will be 5V (trough the resistor) and if you press then the input will be ground (with the resistor preventing short circuit)

#### falleafd

##### New Member
No need. PIC has internal pull up resistors. And as you set it outputs, the resistors are automatically removed, and if you set it inputs. The pull up resistors are available.

Pull up resistors are only needed for 89C51. Some modern MC such as AVR or 89C51 of Phillips have their internal pull ups.

#### Exo

##### Active Member
falleafd said:
No need. PIC has internal pull up resistors. And as you set it outputs, the resistors are automatically removed, and if you set it inputs. The pull up resistors are available.

Pull up resistors are only needed for 89C51. Some modern MC such as AVR or 89C51 of Phillips have their internal pull ups.

In his code is is testing for a set bit (BTFSC), not for a cleared bit. So i assume he has connected the switch to VDD. Eighter he doesnt use the internal pullups and has a high/floating situation. Or he uses internal/external pullups and he always has a logic '1'.

So no matter if he uses internal or external pullups, he probably connected the switch wrong. It needs to go to ground and the code must be modified to test for a cleated bit (BTFSS)

#### patricktran

##### New Member
oops, sorry. The original code was B1_routine, B2_routine. But when I pasted it into this, I feel bad as this is not a routine (I didnt use call, but goto), then I changed it to B1_response. But surely, the original code has not that conflict.

In his code is is testing for a set bit (BTFSC), not for a cleared bit. So i assume he has connected the switch to VDD. Eighter he doesnt use the internal pullups and has a high/floating situation. Or he uses internal/external pullups and he always has a logic '1'.

So no matter if he uses internal or external pullups, he probably connected the switch wrong. It needs to go to ground and the code must be modified to test for a cleated bit (BTFSS)

Ohh, I did connect the switch to a resister and then to VDD, and the pin itself to ground. So I think if I dont push the button, it is ground (bit is clear), if I push, then the button is ....still ground!!! hic hic, this is my first experience with push button.
Ok, so according to Exo, I should
I recomment putting a pull-up resistor from about 10K from the input pin to VDD and then connecting the input pin to ground with a switch.
When the button is not pressed the input will be 5V (trough the resistor) and if you press then the input will be ground (with the resistor preventing short circuit)
But like falleafd said,
No need. PIC has internal pull up resistors. And as you set it outputs, the resistors are automatically removed, and if you set it inputs. The pull up resistors are available.
So should I use a resister addtion to the button?
And if yes, I will connect it like Exo advised with a btfss in my code.
Thanks

#### Nigel Goodwin

##### Super Moderator
Try looking at my tutorials, they show how to read buttons simply - they are written for the 16F628, but it uses exactly the same 14 bit core instructions - only setting of the various extra hardware is different.

#### Exo

##### Active Member
patricktran said:
But like falleafd said,
No need. PIC has internal pull up resistors. And as you set it outputs, the resistors are automatically removed, and if you set it inputs. The pull up resistors are available.
So should I use a resister addtion to the button?
And if yes, I will connect it like Exo advised with a btfss in my code.
Thanks

The pullup resistors falleafd talked about are only available on portB. So if you want you can use them, but only on that port.

I would just use an external resistor for know. You can always play around more with the internal pullups once you better understand the pic.

#### patricktran

##### New Member
Thanks alot for your help guys.
After many days of reading, and thinking, lastly, I got some code that uses TMR1 and turns on and off the LEDs every 1 sec. But sadly, it just nothing happened.
Could someone please help me out of this trouble? I reckon something wrong with the TMR1 setting up!
Code:
; Use 4 MHz crystal frequency.
list  P=PIC16F877,  F=INHX8M,  C=160, N=80,  ST=OFF, MM=OFF, R=DEC
include "C:\MPLAB\MCHIP_Tools\p16F877.inc"
__config ( _HS_OSC & _LVP_OFF)
errorlevel -302

;----------------- Define vaiables ----------------
LBTMR1      equ	H'77'   ;
HBTMR1      equ	H'EC'   ;
reg         equ 0x20    ; ON, OFF, ON, OFF Led at bit 0
Temp_W      equ 0x21
Temp_STATUS equ 0x22
;----------------- Vectors -------------------------

org	H'000'
goto	Main
org	H'004'
goto	ISR

Main
call Initial

Loop

Initial
bcf      STATUS,RP0   ;
bcf      STATUS,RP1   ; Bank 0 selected
clrf     PORTA
bsf      STATUS,RP0   ; Bank 1 selected
movlw    H'00'        ; All pins of PORTA outputs
movwf    TRISA

bcf      STATUS,RP0   ;
bcf      STATUS,RP1   ; Bank 0 selected
movlw       b'00000001'
movwf       reg         ; first interrut of TMR1, turn LED on
call        TMR1Setup
return

TMR1Setup
bcf	    STATUS, RP0
bcf	    STATUS, RP1		; Bank 0 selected
movlw       LBTMR1  		; H'77'
movwf	    TMR1L
movlw       HBTMR1  		; H'EC'
movwf	    TMR1H
clrf	    FlagsReg

movlw       H'01'		; Timer 1 prescaler set to 1
movwf       T1CON  		; Turn on TMR1
bsf         STATUS, RP0		; Bank 1 selected
bsf         PIE1,TMR1IE
bcf	    STATUS, RP0		; Bank 0 selected
movlw       H'C0' 		; Set GIE, PEIE
movwf	    INTCON		; Interrupt controller setting
return

ISR
call        Context_saving
call        Display
call        TMR1Reset
call        Context_restoring
retfie

Context_saving
movwf 	    Temp_W
swapf       STATUS, W
movwf       Temp_STATUS
return

Context_restoring
swapf Temp_STATUS, W
movwf STATUS
swapf Temp_W, F
swapf Temp_W, W
return

TMR1Reset
movlw   LBTMR1
movwf	TMR1L
movlw   HBTMR1
movwf	TMR1H
bcf     PIR1,TMR1IF          ; clear the TMR1 interrupt flag
return

Display
btfss   reg, 0
call    Turn_On
call    Turn_Off
return

Turn_On
bsf     reg,0
movlw   b'11111111'
movwf   PORTA
return

Turn_Off
bcf     reg,0
movlw   b'00000000'
movwf   PORTA
return

Thanks

#### falleafd

##### New Member
Code:
Main
call Initial

Loop

Initial
bcf      STATUS,RP0   ;
bcf      STATUS,RP1   ; Bank 0 selected
clrf     PORTA
bsf      STATUS,RP0   ; Bank 1 selected
movlw    H'00'        ; All pins of PORTA outputs
movwf    TRISA

bcf      STATUS,RP0   ;
bcf      STATUS,RP1   ; Bank 0 selected
movlw       b'00000001'
movwf       reg         ; first interrut of TMR1, turn LED on
call        TMR1Setup
return

After you call Initialize, it will implement the next instruction which is the beginning of Initialize routine.

To the end of Initialize, a RETURN will go back to the TOS which is now 0x0000. And your program will in loop forever.

And the timer1 will never be interrupted because your loop will re-install the new value for timer1 register (TMR1L and TMR1H). It then run again and again. TMR1 never get 65535 to 0 to make interrupt.

#### Exo

##### Active Member
Yes, it needs a 'GOTO Loop' instruction between the lables 'Loop' and 'Initial' like falleafd pointed out

then, there is also a problem with your Display routine
Code:
Display
btfss   reg, 0
call    Turn_On
call    Turn_Off
return

If Reg, 0 is set then the led will be turned off like expected, no problem here. But if Reg, 0 is clear then the Turn_On routine will be called, wich turns the led on, but when it returns Turn_Off is called wich turns the led off again, this happens so fast you'll never see the led turn on...

Code:
Display
btfss    reg, 0
goto     _On

bcf      reg, 0
call     Turn_Off
return

_On

bsf      reg, 0
call     Turn_On
return

#### Matt(Pic progger)

##### Member
:idea:

The other way to record port (switch/button) changes using int's it to use 2 regisiters and a flag in the in sub.......

OLD_PORTB
SW_VALUE_B
SW_FND_FLG (flag bit)

theory for int code, generated via say timer 0 evey 10ms......

*************************************************

compare port b to OLD_PORTB

same?
Yes, exit int.....

No, Store current port B into OLD_PORTB

is SW_FND_FLG set?
Yes, exit int.....

No, Store current port B into SW_VALUE_B, set SW_FND_FLG

exit int

*************************************************

OK, so how does this help?

well, you code checks the SW_FND_FLG, if set, you know a switch has been pressed sometime between 0->10MS, look at SW_VALUE_B to see which one...... then clear SW_FND_FLG, the int code will set the flag on another change of the switch, this will debounce the switch for you....

Why use the flag?? Well this means that if the switch value changes again before you test the SW_FND_FLG, the change will be saved.....

Why bother with this when I can use int on change on portB??? Well you can use this code on any port also the int on change will pick up every "bounce" on the switch contacts, so you will need to impliment a timer/flag etc to get rid of these anyway. AND if you are using a timer anyway it's like getting extra for free (sort of!) AND it's just nice to do things a bit differnt!! :wink:

#### patricktran

##### New Member
Oh, thanks alot evryone. I am very appreciate for your helps. I realise that this forum is very useful, speacially to newbies like me.
Thanks

Status
Not open for further replies.

Replies
18
Views
4K
Replies
1
Views
1K
Replies
6
Views
9K
Replies
4
Views
1K
Replies
1
Views
2K