Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Timer0 problrm "pic 16f84"

Status
Not open for further replies.

forislam

Newbie level 1
Joined
Dec 17, 2009
Messages
1
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,318
hi,

I face a problem in timer0 interrupt where it can count perfectly, but it after reach it's end it should set the timer0 interrupt flag and directly go to 004 to execute the ISR.

what it done is that it correctly count and set the flag , but it can't go to ISR cuz it can't go to 004 "interrupt vector"

here is the code where my program load values in eeprom and read it after 1 sec interrupt


list p=16F84A ; list directive to define processor
#include <p16F84A.inc> ; processor specific variable definitions

__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC

; '__CONFIG' directive is used to embed configuration data 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.




;***** VARIABLE DEFINITIONS
STATUS EQU 03h ; Address of the STATUS register
TRISA EQU 85h ; Address of the tristate register for port A
PORTA EQU 05h ; Address of Port A
EEADR EQU 09h
EEDATA EQU 08h
addressC EQU 20h
w_temp EQU 0x24 ; variable used for context saving
status_temp EQU 0x25 ; variable used for context saving
INTCON EQU 0x0B ; Interrupt Control Register // bank 0
COUNT1 EQU 22h
OPTION_REG EQU 81h
EECON1 EQU 88h
EECON2 EQU 89h
CNT EQU 24h
TMR0 EQU 01h



ORG H'2100'
DE 0x01,0x03,0x07,0x0F,0x1F,0x3F,0x3E,0x3C,0x38,0x30,0x10,0xFF ;to Enter the data in memory

;**********************************************************************
ORG 0x000 ; processor reset vector
goto main ; go to beginning of program

;============================
; INTERRUPTS
;============================
ORG 0x004 ; interrupt vector location <-------------------------- here the timer can't enter !!!
btfsc INTCON,T0IF
call intsrv
bcf INTCON,T0IF ; Clear INTCON bit 1 - i.e clear intflag -
; To be able recieve more interrupts
retfie
;===========================
main
bsf STATUS,5 ; Switch to Bank 1
movlw 00h ; Set the Port A pins with zeros
movwf TRISA ; All port A is output
bcf STATUS,5 ; Switch back to Bank 0

movlw 0x0c ; load 11 in count 1 to wait for 11 timer interrupt
movwf COUNT1
movlw 0x01
movwf addressC

; SETUP INTERRUPTS
bcf INTCON,T0IF ; Clear internal interrupt flag (INTF = bit 1)
bsf INTCON,GIE ; Enable global interrupts (GIE = bit 7)
;=========================
; Timer0
;=========================
MOVLW .96
MOVWF TMR0
bsf STATUS,5
movlw b'00010100' ; set timer0 with prescaler 1:4
movwf OPTION_REG
bcf STATUS,5

bsf INTCON,GIE ; Enable global interrupts (GIE = bit 7)
CLRF CNT
;===============================================

Start
goto Start
;===============================================
intsrv
movwf w_temp ; save off current W register contents
movf STATUS,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
;=================
; VERIFY 1 SEC
;=================
INCF CNT,F ; increament counter
MOVLW .196 ; w <--- h'c4'
SUBWF CNT,W ; cnt - w
BTFSS STATUS,Z ; if cnt = 0 we can execute read operation else return to wait more
retfie
;=================
; READ
;=================
bcf STATUS,5 ;bank0, because EEADR is at 09h
movf addressC,w ;address of location being read
movwf EEADR ;address transferred to EEADR
bsf STATUS,5 ;bank1 because EECON1 is at 88h
bsf EECON1,RD ;reading from EEPROM
bcf STATUS,5 ;bank0 because EEDATA is at 08h
movf EEDATA,W ; W <­­ EEDATA
movwf PORTA ;portA <-- data
;=================
; End Read
;=================
movf addressC,w ; increment addressc to read the next value in EEPROM
addlw 0x01
movwf addressC

exitISR movf status_temp,w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf w_temp,f
swapf w_temp,w ; restore pre-isr W register contents

DECFSZ COUNT1, 1 ; that for doing 11 interrupt only
return
;-----------------------------------------------------------
END ; directive 'end of program'
 

Hi,

Have not run your code, but just looking at it you are trying to do 2 things that cause first timers many problems, so I would suggest you separate the timer and EEprom routines and get each one working on its own before you merge them together.

The microchip code examples are good but many fail to follow the eeprom routine accurately.

On your interrupt, all your ISR code can go after the ORG 004 - no need / do not Call it. ( your ORG 00 goto Main will jump over all your isr code )
The first and last ISR instructions must be the context savings of W etc.
You have done bsfss before you called your isr / context saved.
 

Without running a simulation it looks basically OK but there are some things you can do to make it easier to debug:

1. you duplicate the register names. The names of all the PIC registers are already in the '.inc' file so there is no need to define them again. The only ones you have to define yourself are ones relating to the operation of your code (CNT, COUNT1 etc).

2. It looks like you are using the MPLAB assembler. Instead of setting the banking bits in the STATUS register, use the 'banksel' directive. It makes the program easier to read and less prone to errors. For example. where you have:

bsf STATUS,5 ; Switch to Bank 1
movlw 00h ; Set the Port A pins with zeros
movwf TRISA ; All port A is output

change it to

banksel TRISA
clrf TRISA

which achieves the same end effect but is better at showing the bank you wanted to select. MPLAB will substitute the correct banking code for the register you specify.

3. It is better practice to save the STATUS and W registers on entry to the interrupt routine, call the routine, then restore the registers before returning from it. Your code isn't technically incorrect but if you move the code in 'exitISR' so it is before the 'retfie' (just before main) it keeps all the saving and returning code together. Something like this:

ISR
save the registers
check which interrupt flag is set (if more than one interrupt is being used)
call the appropriate service routine (which clears the interrupt flag)
restore the registers
retfie

4. Nothing to do with your program but it makes it easier for others to read it and copy it into a simulator - when posting, click the box labeled 'Code' before pasting your program and click it again after it ends. This will retain the formatting so we see it the same as you do.

Brian.
 

Hi forislam,
I have fixed the problem and rewrote the program to make it shorter.
Code:
	LIST P=16F84A
	#INCLUDE <P16F84A.INC>
	__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC

	CBLOCK 0x0C ;Variable Definition
		addressC, w_temp, status_temp, COUNT1, CNT
	ENDC

	ORG 0x00
	GOTO MAIN

	ORG 0x04
	GOTO ISR

        ORG H'2100'
        DE 0x01,0x03,0x07,0x0F,0x1F,0x3F,0x3E,0x3C,0x38,0x30,0x10,0xFF ;to Enter the data in memory 
;**********************************************************************

MAIN
	BANKSEL	TRISA ;BANK1
	CLRF	TRISA ;ALL OUTPUTS
	BANKSEL	PORTA ;BANK0
	CLRF	PORTA ;CLEAR PORTA

	MOVLW	0x0C ;LOAD 11 IN COUNT 1 TO WAIT FOR 11 TIMER INTERRUPT
	MOVWF	COUNT1
	MOVLW	0x01
	MOVWF	addressC

;SET INTERRUPTS
	MOVLW	0xA0 ;GIE AND T0IE ENABLED
	MOVWF	INTCON
;TMR0
	MOVLW	.96
	MOVWF	TMR0
	BANKSEL	OPTION_REG ;BANK1
	MOVLW	0x14 ;b'00010100' SET TMR0 PRESCALER 1:4
	MOVWF	OPTION_REG
	BANKSEL	INTCON
	CLRF	CNT
WAIT
	GOTO	WAIT ;WAIT FOR INTERRUPT
;**********************************************************************
ISR
	BTFSS	INTCON, T0IF ;CHECK FOR FLAG RAISED
	CALL	INTSRV
	BCF		INTCON, T0IF ;CLEAR INT FLAG
	RETFIE
;**********************************************************************
INTSRV
	MOVWF	w_temp ;SAVE CONTENT OF W
	MOVF	STATUS, W ;SAVE CONTENT OF STATUS
	MOVWF	status_temp
;=================
; VERIFY 1 SEC
;=================
	INCF	CNT, F ;INCREMENT COUNTER
	MOVLW	.196 ;W <--- 0xC4
	SUBWF	CNT, W ;CNT - W
	BTFSS	STATUS, Z ; IF CNT = 0, READ, ELSE WAIT FOR MORE INTERRUPT
	RETFIE
;=================
; READ
;=================
	MOVF	addressC, W
	MOVWF	EEADR ;ADDRESS IS READ FROM addressC
	BANKSEL	EECON1 ;BANK1
	BSF		EECON1, RD
	BANKSEL	EEDATA ;BANK0
	MOVF	EEDATA, W ;W <-- EEDATA
	MOVWF	PORTA ;PORTA <-- DATA
;=================
; End Read
;=================
	MOVF	addressC, W ;INCREMENT addressC to read the next value in EEPROM
	ADDLW	0x01
	MOVWF	addressC

EXIT_ISR
	MOVF	status_temp, W ;RETRIEVE PREVIOUS VALUE OF STATUS
	MOVWF	STATUS ;RESTORE VALUE
	SWAPF	w_temp, F
	SWAPF	w_temp, W ;RESTORE PRE-ISR W REGISTER CONTENTS
	DECFSZ	COUNT1, 1 ;THAT FOR DOING 11 INTERRUPT ONLY
	RETURN
;**********************************************************************
	END ;END OF PROGRAM
Your problem:
Where you enabled the interrupts, you set GIE bit but forgot to set T0IE bit.
In the ISR, you are using BTFSC to check if flag is cleared. This is an error, it should be BTFSS.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top