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.

Problem facing when using Timer0 of 16f877a

Status
Not open for further replies.

simpsonss

New Member
hi guys,

i'm now trying to use Timer0 of 16f877a to overflow every 6.25ms. So this is how i calculate the TMR0 value. i'm using 4Mhz XTAL. and my prescaler is set to 1:256.

4Mhz/4= 1Mhz

1Mhz/256 = 3906.25hz

1/3906.25hz = 256us

6.25ms/256us=24.41

256 - 24.41 = 231.58

so i decided to use 232 as my TMR0 value. So am i correct?

in my program, i complement my LEDs everytime interrupt occur which mean every 6.25ms. But when i measure the period from my logic analyzer i found that the period time is not correct. SO i'm wonder maybe is my calculation problem or other .

thank you.:confused:
 
If you set TMR0 to 232 then you will get an overflow every (256-232)*256 = 6144 instruction cycles.

1,000,000/6144 = 162.7 Hz

1/162.7 = 0.006114 Seconds or 6.114mS

Looks good to me. Even if it is kinda circular.:D

However, you will get better accuracy if you set the prescaler to 32 and TMR0 to 61.

<edit> Note that this time is for half a period and so a frequency meter will register 80Hz.</edit>

Mike.
 
Last edited:
Seems like my calculation is correct. The following is my picBasic code. Where am i go wrong? because the period of one logic high or logic low is wrong.:confused:


'DECLARE SYMBOLS
Symbol T0IF = INTCON.2 ' TMR0 Overflow Interrupt Flag
Symbol T0IE = INTCON.5 ' TMR0 Overflow Interrupt Enable
Symbol GIE = INTCON.7 ' Global Interrupt Enable
Symbol PS0 = OPTION_REG.0 ' Prescaler Rate Select
Symbol PS1 = OPTION_REG.1 ' Prescaler Rate Select
Symbol PS2 = OPTION_REG.2 ' Prescaler Rate Select
Symbol PSA = OPTION_REG.3 ' Prescaler Assignment
Symbol TOCS = OPTION_REG.5
symbol LED = PORTB

TRISB = 0
PORTB = 0

PS0 = 1
PS1 = 1
PS2 = 1





thank you for the reply.
 
Last edited:
I can't see anything wrong. Can you try a non-interrupt version.

Something like,
Code:
    OPTION_REG=7
    while(1)
        while(INTCON.TMR0IF=0)
        wend
        INTCON.TMR0IF=0
        TMR0=232
        LED = ~LED
    wend

Mike.
 
HI,
yeah~ the code u given works.i can get half period for 6.15ms. So what wrong with my part?

After i troubleshooting my code. i found that when i enable global interrupt, it wont work. but once i disable it. i cant get 6.20ms back for half period.

thank you.:D:confused:
 
Last edited:
I'm afraid I'm not familiar with the compiler that you are using so can't really help. I suspect it is something to do with the interrupt code. Is there a forum for your compiler?

If you state which compiler it is then maybe someone else who is familiar with it might help.

Mike.
 
i'm using PIC basic pro compiler.

anyway thanks.so instead of using the interrupt i also can use the code u write to generate the frequency i want.Am i correct?:D
 
Hi,

anything wrong with my code?

list p=16F877A
#include <p16F877A.inc>


ORG 0x00
goto Main
org 0x04
goto T0_INT

Main

bsf STATUS,RP0 ;switch 2 bank1
clrf TRISB
movlw b'00000111'
movwf OPTION_REG

bcf STATUS,RP0 ;switch 2 bank0

movlw 0xe8
movwf TMR0

movlw 0xa0
movwf INTCON

clrf PORTB ;clear PORTB

goto $

;interrupt subroutine
T0_INT
clrf T0IE
clrf T0IF
movlw 0xe8
movwf TMR0
comf PORTB
bsf INTCON,5
retfie

END

thanks.
 
You're code is very close to working, you need a config line and I changed the INTCON bits just in case.

try,
Code:
		list	p=16F877A
		#include <p16F877A.inc> 

		__config _XT_OSC & _PWRTE_OFF & _WDT_OFF &_LVP_OFF 


		org	0x00
		goto	Main
		org	0x04
		goto	T0_INT

Main
		bsf	STATUS,RP0	;switch 2 bank1
		clrf	TRISB
		movlw	b'00000111'
		movwf	OPTION_REG
		bcf	STATUS,RP0	;switch 2 bank0
		movlw	0xe8
		movwf	TMR0
		bsf	INTCON,T0IE	;enable timer interrupt
		bsf	INTCON,GIE
		clrf	PORTB		;clear PORTB
		goto	$

;interrupt subroutine 
T0_INT
		clrf	INTCON,T0IF	;clear int flag
		movlw	0xe8
		movwf	TMR0
		comf	PORTB,f
		retfie
		end

Mike.
 
hi pommie,
since the idea and concept of the code for PicBasic is same as the assmebly which both i written. How come the result is different? ehm...

regards the config line u added in. since everything is off. So why i can get the correct result without adding in the config line?

thanks for the reply.
 
As you state, the code is identical and so it must be the compiler that does something strange. I would check the manual especially the interrupt section.

With regard to the config line, the default is all ones and so,
LVP would be enabled - rb3 must be tied high.
WDT is enabled - it will reset every few mS.
Oscillator is RC - won't work with a crystal.

Actually, this could be the problem with your basic program. The watchdog timer could be reseting the processor.

Mike.
 
hi pommie,
ic..really learn alot.thanks. i would like to ask something regard programming style. if i want to read data from a table using assembly. how am i gonna do?

.data 0x01, 0x02, 0x03

some sort like dis. i want to display the data 1 by 1 to the led. how is the coding idea?

thank you.
 
You use an instruction called retlw and do a jump into the middle of the message,

Code:
Message		addwf	PCL,F
		retlw	0x01
		retlw	0x02
		retlw	0x03
To use it you put the item number in W and call Message.

You can also use dt to write a string of bytes,
Code:
		dt	0x01,0x02,0x03
OR,
		dt	"Hello world!",0

<edit> forgot to mention, these types of tables must reside in 1 page of memory.</edit>

Mike.
 
Last edited:
You can't, you have to use a sequence of retlw instructions. Tha data instruction is to place values in EEPROM.

Mike.
 
hi
Code:
		list	p=16F877A
		#include <p16F877A.inc> 

		__config _XT_OSC & _PWRTE_OFF & _WDT_OFF &_LVP_OFF 

		var1	EQU		0x0F

		org		0x00
		goto	        Main
		org		0x04
		goto	       T0_INT
		
Main
		bsf		STATUS,RP0	;switch 2 bank1
		clrf	       TRISB
		movlw	b'00000111'
		movwf	OPTION_REG
		bcf		STATUS,RP0	;switch 2 bank0
	
		movlw	0xe8
		movwf	TMR0
		bsf		INTCON,T0IE	;enable timer interrupt
		bsf		INTCON,GIE
		clrf	        PORTB		;clear PORTB
		goto	$


T0_INT
		
		bcf		INTCON,T0IF	;clear int flag		
		movlw	0xe8
		movwf	TMR0
		bsf		var1,1
		movf	        var1, PORTB

		retfie

i'm wonder why my var1 register is not working. i cant get logic 1 for PORB.0.

thank you.
 
Well, I can see a couple of things wrong with your code,

var1 EQU 0x0F

this is not good because 0x0f is the location of TMR1H. The area you should use for your variables is 0x20 onward.

movf var1, PORTB

This is not a valid instruction (and should be an error in MPLAB:mad:). What you need to do is,
Code:
	movf	var1,w		;move var1 to W
	movwf	PORTB		;move W to portb

Mike.
 
haha icic.. what a fool mistake i had made. :eek:huh~

but when i compile MPLAB doesnt show any error.haha..

thank you.

since 16f877a have an external interrupt for RB0. And it has and state change for RB7:RB4. so izzit mean that whenever there is either a low to high or vice versa state, it will set the flag bit? So after the flag is set, can i know which pin is being changed? because i'm planing to have two external interrupt button. but seems like we only have one RB0 ext interrupt pin.

thank you.
 
Last edited:
Status
Not open for further replies.

Latest threads

Back
Top