You're welcome. Good luck on the exam.thank you for your help @EVERYONE
#include<p16f84a.inc>
DELAY 0X0G
COUNTER 0X0C
ORG 0X00
BSF STATUS,RP0
CLRF TRISB
BCF STATUS,RP0
LO:
CLRF PORTB
CALL DELAY
BSF PORTB,1
CALL DELAY
GOTO LO
DELAY:
MOVLW 0X255
MOVWF COUNTER
DECFSZ COUNTER,F
GOTO $-1
RETURN
#include<p16f84a.inc>
DELAY 0X0G
COUNTER 0X0C
org 0X00
bsf STATUS,RP0
clrf TRISB
bcf STATUS,RP0
LO:
clrf PORTB
call DELAY
bsf PORTB,1
call DELAY
GOTO LO
DELAY:
movlw 0X255
movwf COUNTER
decfsz COUNTER,F
goto $-1
return
My mistake i was want to use 2 counters but i named it wrong and i didnt use it in the programWhat is DELAY 0x0G?
Max.
Code:#include<p16f84a.inc> DELAY 0X0G COUNTER 0X0C org 0X00 bsf STATUS,RP0 clrf TRISB bcf STATUS,RP0 LO: clrf PORTB call DELAY bsf PORTB,1 call DELAY GOTO LO DELAY: movlw 0X255 movwf COUNTER decfsz COUNTER,F goto $-1 return
movlw .255 ; default radix is hex. The '.' makes it decimal.What is 0x255? You don't use the hexidecimal prefix "0x" and then write a decimal number, especially one as obvious as 255!
Just write "movlw 255"
I use online pic compilermovlw .255 ; default radix is hex. The '.' makes it decimal.
Have you punched your code into MPLAB and used MPSIM to step it? That will identify lots of problems including those syntax errors.
If you haven't flow charted your routine, do it and tweak it until you can trace the operation with your finger. When that is done, code it and debug. Done.
If you don't work along those lines you will run in circles until you run out of time. We can't help you with that. Ignore the time pressures. Slow down and think.
#include<p16f84a.inc>
ERRORLEVEL -302
cblock 0ch
COUNTER: 1
endc
ORG 0X00
BSF STATUS,RP0
CLRF TRISB
BCF STATUS,RP0
LO:
CLRF PORTB
CALL DELAY
BSF PORTB,1
CALL DELAY
GOTO LO
DELAY:
MOVLW .255
MOVWF COUNTER
DECFSZ COUNTER,F
GOTO $-1
RETURN
END
ORG 0X00
BSF STATUS,RP0
BCF OPTION_REG,T0CS
BSF OPTION_REG,3
BCF OPTION_REG,0
BCF OPTION_REG,1
BCF OPTION_REG,2
CLRF TRISB
BCF STATUS,RP0
LO:
BSF PORTB,1
CALL L
BCF PORTB,1
CALL L
GOTO LO
L:
BSF INTCON, TMR0IE
BSF INTCON, GIE
MOVLW D'240'
MOVWF TMR0
D:
BTFSS INTCON,2
GOTO D
RETURN
END
With the clock running at 4 MHz., The tmr0 can only count 256 uS with the prescaler set to 1:1.Can someone help me to solve it
Thank youWith the clock running at 4 MHz., The tmr0 can only count 256 uS with the prescaler set to 1:1.
To get 2 seconds delay, I would use prescaler set to 1:256 and PSA set to TMR0. Then each interrupt would give about 65 mS.
Then setup a counter on the main routine to count to 31 before resetting to zero. That would give you roughly 31*65ms = 2.0xx seconds.
It's too late here and I'll try to make a simple program tomorrow morning if I get some free time.
Allen
ORG 000h
GOTO InitSystem ; jump over the interrupt vector
ORG 004h
InterruptService:
;save context ; save W, STATUS and any other register that the
;service routine uses, see databook sec 6.9 for an example
;reload timer if necessary
; decrement TimerPostScaler
; if not Zero, goto to IRQdone
; 2 sec have elapsed, toggle the LED and reload the seconds timer
MOVLW TimerPostScalerValue ; reload post scaler
movwf TimerPostScaler
; handle LED output
IRQdone:
BCF INTCON,T0IF ; clear interrupt flag
;restore context ; the values of W, STATUS and other registers used in the
; service routine must be restored to their EXACT values before the interrupt occurred
RETFIE ; return and re-enable interrupts
InitSystem:
BSF STATUS,RP0
BCF OPTION_REG,T0CS
BSF OPTION_REG,3
BCF OPTION_REG,0
BCF OPTION_REG,1
BCF OPTION_REG,2
CLRF TRISB
BCF STATUS,RP0
MOVLW TimerPostScalerValue; counts enough interrupts to make 2 sec
movwf TimerPostScaler
BCF INTCON,T0IF ; clear stray interrupts
BSF INTCON, TIE ; enable timer interrupt
BSF INTCON, GIE
WaitForever:
nop ; do something while the interrupt runs the LED
nop
goto WaitForever
END
Where i can add bsf porbt,1 then delay then bcf portb,1 then delay then repeatYou are missing some important things about interrupts.
When the timer interrupt occurs, the processor CALLS a routine at 0x004. That is where your timer service code must live. You don't have a service routine but you have enabled the interrupt. The program is vectored to 0x004 but there is no service routine.
As @absf says, timer 0 isn't big enough to accumulate 2 seconds worth of clocks so you have to set it to interrupt at some rate then use an additional register to count the interrupts (TimerPostScaler below) If you set the timer to interrupt every 10ms, you would count 200 interrupts in the post-scaler. To get an exact 10ms, you might also have to reload the timer itself to some value to adjust the time between interrupts.
Interrupts are covered in 6.8 of the datasheet.
The basic code layout looks like this:
Code:ORG 000h GOTO InitSystem ; jump over the interrupt vector ORG 004h InterruptService: ;save context ; save W, STATUS and any other register that the ;service routine uses, see databook sec 6.9 for an example ;reload timer if necessary ; decrement TimerPostScaler ; if not Zero, goto to IRQdone ; 2 sec have elapsed, toggle the LED and reload the seconds timer MOVLW TimerPostScalerValue ; reload post scaler movwf TimerPostScaler ; handle LED output IRQdone: BCF INTCON,T0IF ; clear interrupt flag ;restore context ; the values of W, STATUS and other registers used in the ; service routine must be restored to their EXACT values before the interrupt occurred RETFIE ; return and re-enable interrupts InitSystem: BSF STATUS,RP0 BCF OPTION_REG,T0CS BSF OPTION_REG,3 BCF OPTION_REG,0 BCF OPTION_REG,1 BCF OPTION_REG,2 CLRF TRISB BCF STATUS,RP0 MOVLW TimerPostScalerValue; counts enough interrupts to make 2 sec movwf TimerPostScaler BCF INTCON,T0IF ; clear stray interrupts BSF INTCON, TIE ; enable timer interrupt BSF INTCON, GIE WaitForever: nop ; do something while the interrupt runs the LED nop goto WaitForever END
No place when you use interrupts. The delay is done by counting interrupts, not by using a delay loop. You change the LED output at line 18 above. That line gets executed every 2 sec so there's your flasher. An easy way to do it is:Where i can add bsf porbt,1 then delay then bcf portb,1 then delay then repeat
Oh that mean i cant use timer0 as subroutine like a 2 nested loopNo place when you use interrupts. The delay is done by counting interrupts, not by using a delay loop. You change the LED output at line 18 above. That line gets executed every 2 sec so there's your flasher. An easy way to do it is:
movlw 0b00000010 ; LED on RB1..
xorwf PORTB,F ; gets toggled by xor'ing its current value with 1
That is correct. The timer works by counting system cycles (Tcyc). The 'time' in timer comes from the fact that it takes time to count a bunch of Tcyc. Also, be very clear on the difference between a subroutine and an interrupt. You call the subroutine. The interrupt is called automatically in response to an event, in this case TMR0 rolling over from FF->00. See 5.3 in the datasheet. It is critical to realize that since the interrupt can happen at any time, the interrupt routine must save any registers it uses then restore them just before returning to the system. Failure to to that will cause endless problems.Oh that mean i cant use timer0 as subroutine like a 2 nested loop
| Thread starter | Similar threads | Forum | Replies | Date |
|---|---|---|---|---|
| N | Help Debugging PIC16F84A Code for Dual Tank System | Homework Help | 1 | |
| D | PIC16F84A TIMER0 | Microcontrollers | 8 | |
| D | PIC16F84A to PIC16F877 migration failure. | Microcontrollers | 25 | |
| D | Musical note using PIC16F84A (Assembly code) | Programming & Languages | 5 | |
| J | PIC16F84A with Matrix Keypad. | Microcontrollers | 1 |