PDA

View Full Version : PIC16F877A - Timer0 won't interrupt



WishMaster^
- 13th April 2007, 14:52
Hello all,

I've been struggling with a, for a not-picbasic-newbie (which I am! :( ), simple problem. I'm trying to let a LED blink on the overflow rate of timer0. Unfortunately I wasn't very succesfull.

When I run the following code (I know the LED won't blink with this, but that's step 2)



define loader_used 1
define osc 20

led var portc.1 ;LED is connected on PortC.1

wsave var byte $20 system
ssave var byte bank0 system
psave var byte bank0 system

Goto main

define INTHAND tmroverflow

asm
tmroverflow movwf wsave
swapf STATUS, W
clrf STATUS
movwf ssave ;Interrupt
movf PCLATH, W ;Routine
movwf psave ;with Save function

bsf _led ;Put on LED

movf psave, W
movwf PCLATH
swapf ssave, W
movwf STATUS
swapf wsave, F
swapf wsave, W

bcf intcon,2 ;Clear Interrupt Flag

retfie
ENDASM

main:
INTCON = %10100000 ;GIE enabled, T0IE enabled
OPTION_REG = %00000101 ;Prescaler on TMR0 rate 1:32
goto loop

loop:
goto loop ;Wait here for interrupt


When I run it in debug mode, the compiler goes insane and gives me mismatched address errors after the timer didn't respond for some time (the watchdog timer is off, so it isn't him who's complaining :) )
I think that my mistake is in the INTCON and/or the OPTION_REG, but experimenting with this values didn't helped me further neither.
The "save" function is O.K asfar as I can see, since it's straight out of the manual!! ;)

All it need to do for step 1 is to light the LED...

So if someone sees the problem right away, and I'm sure there will be many, please help this desperate newbie! I will be very gratefull!

Cheers,

William

skimask
- 13th April 2007, 15:17
I don't see anything for a TRISC.1 = 0

skimask
- 13th April 2007, 15:23
define loader_used 1
define osc 20

led var portc.1 ;LED is connected on PortC.1
ledcnt var word

wsave var byte $20 system
ssave var byte bank0 system
psave var byte bank0 system

Goto main

define INTHAND tmroverflow

asm
tmroverflow movwf wsave
swapf STATUS, W
clrf STATUS
movwf ssave ;Interrupt
movf PCLATH, W ;Routine
movwf psave ;with Save function

inc _ledcnt ;increment the counter

movf psave, W
movwf PCLATH
swapf ssave, W
movwf STATUS
swapf wsave, F
swapf wsave, W

bcf intcon,2 ;Clear Interrupt Flag

retfie
ENDASM

main:
INTCON = %10100000 ;GIE enabled, T0IE enabled
OPTION_REG = %00000101 ;Prescaler on TMR0 rate 1:32
Output LED

loop:
led = ledcnt.7 ;make the led follow bit 7 of ledcounter
goto loop ;Wait here for interrupt


A couple of changes. If you don't see the LED blink, turn up the prescaler and/or use a slower oscillator for test. At least you should see it work.

sougata
- 13th April 2007, 15:31
[code]


incf _ledcnt ;increment the counter



Hi,

Skimask I think it should be incf and is a simple typo.

skimask
- 13th April 2007, 15:39
Hi,

Skimask I think it should be incf and is a simple typo.

Yep, should be, and is......then again, it is Friday the 13th....maybe my keyboard is playing em no skcirt

Darrel Taylor
- 13th April 2007, 19:07
Interrupts and the MSC Debugger don't get along very well together.

You must DISABLE debugging in any interrupt routines.
DISABLE DEBUG
asm
tmroverflow movwf wsave
...
...
retfie
ENDASM
ENABLE DEBUG

For an 877, you should use $70 for the wsave address.

OPTION_REG = %00000101 sets the prescaler to 1:64. (comment says 32)

and, like skimask said ... set the LED's pin to output.

paul borgmeier
- 13th April 2007, 20:18
Also a working example on MELABs website
http://www.melabs.com/resources/samples/pbp/asmint.bas
(maybe you got your start for yours there? I did not check if they are similar)

WishMaster^
- 14th April 2007, 09:57
Thanks all for your responds, will try them out on monday, it's weekend now. But thank you all very very much :)!!!

WishMaster^
- 16th April 2007, 07:34
It's working perfectly!!! Thanks for the help! :)

Cheers,

William

WishMaster^
- 17th April 2007, 08:36
Hello all!!
An update and help request on my program:



define loader_used 1
define osc 20

;---Defining Variables---
wsave var byte $70 system
ssave var byte bank0 system
psave var byte bank0 system

count0 var byte bank0 system
count1 var byte bank0 system
count2 var byte bank0 system
count3 var byte bank0 system
count4 var byte bank0 system
count5 var byte bank0 system
hulp0 var byte bank0 system
hulp1 var byte bank0 system
hulp2 var byte bank0 system
whulp var byte bank0 system
pclhulp var byte bank0 system
sthulp var byte bank0 system

;---Zeroing registers---
count0 = 0
count1 = 0
count2 = 0
count3 = 0
count4 = 0
count5 = 0
hulp0 = 0
hulp1 = 0
hulp2 = 0
whulp = 0
pclhulp = 0
sthulp = 0
STATUS.0 = 0

Goto main ;Skip interrupt routine

define INTHAND int

DISABLE DEBUG

asm
;---Save W, STATUS and PCLATH---
int movwf whulp
swapf STATUS, W
clrf STATUS
movwf sthulp
movf PCLATH, W
movwf pclhulp

;---Clock program---
incf count0, F
movwf count0
call check
movf count0, W
btfss STATUS,0
goto eindafwerking
incf count1, F
movwf count1
call check
movf count1, W
btfss STATUS,0
goto eindafwerking
incf count2, F
movwf count2
call check
movf count2, W
btfss STATUS,0
goto eindafwerking
incf count3, F
movwf count3
call check
movf count3, W
btfss STATUS,0
goto eindafwerking
incf count4, F
movwf count4
call check
movf count4, W
btfss STATUS,0
goto eindafwerking
incf count5, F
movwf count5
call check
movf count5, W
btfss STATUS,0
goto eindafwerking

;---Restore W, STATUS and PCLATH---
eindafwerking movf pclhulp, W
movwf PCLATH
swapf sthulp, W
movwf STATUS
swapf whulp, F
swapf whulp, W
bcf intcon,2
retfie

;---Check function for counts to be 99h maximum (NOT USED YET)---
check return
ENDASM

ENABLE DEBUG

main:
INTCON = %10100000 ;GIE enabled, T0IE enabled
OPTION_REG = %00000111
goto loop

loop: goto loop ;Wait here for interrupt


The program before (with the LED) was to time it on 1 millisecond, the final program (which isn't this one ofcourse ;) ) is for measurement purposes.

Test step 2:
What I try to do here is to make a counter, that increments count0 when the timer overflows, then when count0 is full, it increments count1 etc etc. Atleast... it should do that....

The things i tried to make it work:
- Reset the C flag of STATUS, only this made only count0 to run.
- Switched , W with , F and vice versa (example: STATUS, W becomes STATUS, F)

A colleague told me to make some own save location (pclhulp, whulp and sthulp). I'm not sure if this is okay...

If someone could help me out again, I will be very gratefull (again!!). :)

Cheers,

William

(Excuse me for the dutch labeling, it shouldn't be be much of a problem i guess :) )

/EDIT:

Allrightey I fixed the problem myself! Yay ^^!



define loader_used 1
define osc 20

;---Defining Variables---
wsave var byte $70 system
ssave var byte bank0 system
psave var byte bank0 system

count0 var byte bank0 system
count1 var byte bank0 system
count2 var byte bank0 system
count3 var byte bank0 system
count4 var byte bank0 system
count5 var byte bank0 system
hulp0 var byte bank0 system
hulp1 var byte bank0 system
hulp2 var byte bank0 system
whulp var byte bank0 system
pclhulp var byte bank0 system
sthulp var byte bank0 system

;---Zeroing registers---
count0 = 0
count1 = 0
count2 = 0
count3 = 0
count4 = 0
count5 = 0
hulp0 = 0
hulp1 = 0
hulp2 = 0
whulp = 0
pclhulp = 0
sthulp = 0
STATUS.2 = 0

Goto main ;Skip interrupt routine

define INTHAND int

DISABLE DEBUG

asm
;---Save W, STATUS and PCLATH---
int movwf whulp
swapf STATUS, W
clrf STATUS
movwf sthulp
movf PCLATH, W
movwf pclhulp

;---Clock program---
incf count0, F
movf count0, W
call check
movwf count0
btfss STATUS,2
goto eindafwerking
bcf STATUS,2
incf count1, F
movf count1, W
call check
movwf count1
btfss STATUS,2
goto eindafwerking
bcf STATUS,2
incf count2, F
movf count2, W
call check
movwf count2
btfss STATUS,2
goto eindafwerking
bcf STATUS,2
incf count3, F
movf count3, W
call check
movwf count3
btfss STATUS,2
goto eindafwerking
bcf STATUS,2
incf count4, F
movf count4, W
call check
movwf count4
btfss STATUS,2
goto eindafwerking
bcf STATUS,2
incf count5, F
movf count5, W
call check
movwf count5
bcf STATUS,2
goto eindafwerking


;---Restore W, STATUS and PCLATH---
eindafwerking movf pclhulp, W
movwf PCLATH
swapf sthulp, W
movwf STATUS
swapf whulp, F
swapf whulp, W
bcf intcon,2
retfie

;---Check function for counts to be 99h maximum (NOT USED YET)---
check return
ENDASM

ENABLE DEBUG

main:
INTCON = %10100000 ;GIE enabled, T0IE enabled
OPTION_REG = %00000111
goto loop

loop: goto loop ;Wait here for interrupt


What I did wrong:
- I switched the movf and the movwf instructions!
- Checked the wrong bit, it checked the carry flag (Status.0) instead of the Zero flag (Status.2)

I feel so noobish >)

skimask
- 17th April 2007, 11:16
I feel so noobish >)

Really? Well...how many 'noob's' can say they fixed a problem on their own.
I do believe you've done graduated out of the noob class...
Now go let all the smoke out of a PIC to celebrate! :D

WishMaster^
- 19th April 2007, 10:15
Really? Well...how many 'noob's' can say they fixed a problem on their own.
I do believe you've done graduated out of the noob class...
Now go let all the smoke out of a PIC to celebrate! :D

I can count myself as a real rookie now!! :D

Now that my program is growing, I encountered a new problem.
The program is now some sort of stopwatch with 1 control button on portb.4.
The problem is, that when I press the button, the timer won't start and it goes straight to "The time is: 00,00"

What do I miss here?


anyone? ^^

Cheers,

William

/EDIT While I studied the behaviour of the program, I saw something odd... When i press RB4, INTCON.0 is set, BUT the interrupt enable bit is cleared on the same time. That's why it doesn't interrupt.

Now I have forced the enable bit to stay set, only when I run it then it gives me an adress missmatch error. So that isn't the solution... :)

Anyone with a clue what might reset INTCON.3?

WishMaster^
- 23rd April 2007, 08:29
Okay, in debug mode all works fine now, but, when I compile and load the program without the debugger, then it goes bananas. What I suspect now, is that there is a signal in PortB what is resonating when I press the button. This will cause many interrupts, making the microcontroller think that I press the stop button right away.

That will explain why it skips the interrupt routine without the debugger on...

Before I order any parts to solve this, I want to know if I'm close or not. So is this a problem that might occure while making something like this?



Cheers,

William

Darrel Taylor
- 23rd April 2007, 09:56
A colleague told me to make some own save location (pclhulp, whulp and sthulp). I'm not sure if this is okay...

I don't think I'd be listening to that guy too much.

If you are using a chip with more than 2K of program memory,PBP automatically inserts code to do the context saving. It uses the wsave, ssave and psave variables. Why? I don't know. But it does.

In the process of saving the context, it also changes the W and STATUS registers. So if you try to save and restore it with different variables, you're only saving the changed values. Then the real values never get restored.

This will send PBP to the Funny Farm. Or at least the person trying to figure it out.

So, lose the saving portion of the interrupt handler, then change the restore section to what's shown in the manual.

HTH,

WishMaster^
- 23rd April 2007, 11:24
I don't think I'd be listening to that guy too much.

If you are using a chip with more than 2K of program memory,PBP automatically inserts code to do the context saving. It uses the wsave, ssave and psave variables. Why? I don't know. But it does.

In the process of saving the context, it also changes the W and STATUS registers. So if you try to save and restore it with different variables, you're only saving the changed values. Then the real values never get restored.

This will send PBP to the Funny Farm. Or at least the person trying to figure it out.

So, lose the saving portion of the interrupt handler, then change the restore section to what's shown in the manual.

HTH,


Allright! I already had my doubts about that! I changed it back right away and it works just as great! Thanks! :)

I fixed the problem with the "resonating signal". Turned out I used a wrong capacitor so the signal sticked in the forbidden area too long...
Back to newbie class for me I guess, haha.

Now comes the real challenge, 3 time measurements at the same time with 3 different start/stop buttons. All working on interrupts... Wish me luck! :D

Cheers,

William

WishMaster^
- 24th April 2007, 10:15
For those who want to make a Stopwatch, here is my code for it. You will have to tune Timer0 for exact readouts since it is not perfect yet. By 30 seconds it will be 1,5 seconds off (28,5 sec)

It counts from 100 uS

Have fun building your stopwatch :)

Thanks to all who helped me to make the code as it is now!


Cheers,

William

P.S, I'll keep you all informed about the 3-stopwatch-at-the-same-time-based-on-interrupts-program ;)

skimask
- 24th April 2007, 14:06
For those who want to make a Stopwatch, here is my code for it. You will have to tune Timer0 for exact readouts since it is not perfect yet. By 30 seconds it will be 1,5 seconds off (28,5 sec)
It counts from 100 uS
Have fun building your stopwatch :)
Thanks to all who helped me to make the code as it is now!
Cheers,
William
P.S, I'll keep you all informed about the 3-stopwatch-at-the-same-time-based-on-interrupts-program ;)

I almost hate to point this out to you since you've already got all this work into your project/code...but...
Do a search on 'Olympic Timer'...
You'll find a timer that Melanie did awhile back, and it's very accurate...well, at least as accuracte as your oscillator is.

Darrel Taylor
- 24th April 2007, 23:08
Right! There's ...



Olympic Timer (Melanie)
http://www.picbasic.co.uk/forum/showthread.php?t=632
&nbsp; &nbsp;Uses ON INTERRUPT<br>

Easy and Accurate Clocks without RTC IC (paul borgmeier)
http://www.picbasic.co.uk/forum/showthread.php?t=2129
&nbsp; &nbsp;No Interrupts<br>

Elapsed Timer Demo (Darrel Taylor)
http://www.picbasic.co.uk/forum/showthread.php?t=190
&nbsp; &nbsp;ASM Interrupts<br>

Elapsed Timer for Instant Interrupts (Darrel Taylor)
http://www.picbasic.co.uk/forum/showthread.php?p=17473
&nbsp; &nbsp;Instant Interrupts<br>

Here's one based on Roman Black's routines (shahidali55)
http://www.picbasic.co.uk/forum/showthread.php?p=22173
&nbsp; &nbsp;No Interrupts

And now there's...

Working code (Stopwatch) (WishMaster^)
http://www.picbasic.co.uk/forum/showthread.php?p=36939
&nbsp; &nbsp;ASM Interrupts


Now all we need is ...

_ _ _ _ _ _ _ _ _ _ _ (skimask)
http://www.picbasic.co.uk/forum/showthread.php?p=dontknowyet
&nbsp; &nbsp;???? Interrupts

skimask
- 24th April 2007, 23:31
Right! There's ...
Now all we need is ...

_ _ _ _ _ _ _ _ _ _ _ (skimask)
http://www.picbasic.co.uk/forum/showthread.php?p=dontknowyet
&nbsp; &nbsp;???? Interrupts


Jack of all trades, master of none. I know you've seen me say it before, I'm not doing anything that somebody else has already done...
Maybe someday I'll come up with something really neat and revolutionary to post...but I haven't come up with anything just yet...(that FFT routine adaptation I've got posted on my webpage for the PIC18Fxxxx is under an NDA, otherwise it would be here in a second).

WishMaster^
- 25th April 2007, 08:25
I almost hate to point this out to you since you've already got all this work into your project/code...but...
Do a search on 'Olympic Timer'...
You'll find a timer that Melanie did awhile back, and it's very accurate...well, at least as accuracte as your oscillator is.

Yeah, I saw that one... But I learned much more about assembly and stuff with my own code then by simple copy/paste.

And if I finish the main project, the 3-timers-thing, then I will share the happiness too. Might be handy to clock the top3 formula 1 cars when you are at a race or something :P

Here it will be used for viscositymeasurements (http://en.wikipedia.org/wiki/Viscosity), where we can start a measurement at any time we want and not one per time (time = money and stuff ;) ).

And, most important reason of all, making your own code is so much more fun, seeing it grow and on the end, see it work! :D


Cheers,

William