Anybody see why my Timer3 interrupt isn't interrupting?

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I took code from an old project that is still working, though I haven't tried building the old project with AVRStudio 4:

Set everything up:

Reset: ;Here on reset
	   ldi	r16,high(RAMEND)	;Intialize stackpointer
	   out	SPH,r16
	   ldi	r16,low(RAMEND)
	   out	SPL,r16

	                            ; Disable Sleep
       clr Scratch
	   out MCUCR,scratch		;


	   out DDRE,scratch		; Port E is input
	   ldi scratch,7
	   out portE,scratch			; And pullups
	   ldi scratch,3
	   OUT DDRB,scratch		; Port B bit 0 and 1 are output
	   
	   sbi ddrb,1
	   ldi scratch,0        ; Turn the cap off
	   OUT PORTB,scratch
	   LDI scratch,255
	   OUT DDRD,scratch     ; Port D is output
	   OUT DDRC,scratch		; Port C is output
	   OUT DDRA,scratch		; Port A is output

       ldi scratch,0b11111101 ; Dashes to LEDs
	   out PortD,scratch
	   out PortC,scratch
	   out PortA,scratch
	   CALL InitTimer3

	   SEI					;Enable Interrupts
Reloop: 
        in scratch,PortB
       ldi r17,2
	   eor scratch,r17
	   out PortB,scratch
      RJMP ReLoop

Set up Timer 3:

InitTimer3:

    ; Timer 3 is timebase for opperations
       

	ldi scratch,0b00000000  ; 
	STS TCCR3B,scratch      ; Stop timer 3
	STS ETIMSK,scratch      ; Stop overflow interrupt
	STS TCCR3A,scratch
	ldi scratch,255  ; counts from overflow
	sts TCNT3H,scratch
	ldi scratch,100
	sts TCNT3L,scratch
	ldi scratch,0b00000101  ; TCCR31B Clock / 1024
	STS TCCR3B,scratch
	ldi scratch,4   ; Enable overflow interrupt on Timer 3
	STS ETIMSK,scratch

    cbi PortA,0             ; Turn on an LED so we see this got called
	RET

And the interrupt

Timer3Interrupt:
	PUSH scratch
	IN scratch,sreg			; Get the status register
	PUSH scratch ; And save that

    cbi PortB,0     ;Turn on an LED so we see this ran

	
    CALL InitTimer3
	POP scratch ; Restore the status register
	OUT sreg,scratch
	POP scratch ; And scratch
	SEI
	RETI

(I'll probably see it myself tomorrow)

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interrupts vectors?? Also ensure that you use the correct instruction RJMP or JMP in the vectors according to your chip. May want to run it in the simulator.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hehe Thought about the vectors after posting...

.cseg ;CODE Segment
.org 0
	rjmp reset ;Reset vector

.org ACIaddr ; $034 ;ANA_CMPaddr	; Comparator Trigger vector
	rjmp ComparatorInterrupt

.org OVF3addr ; Timer 1 overflow vector
	rjmp timer3interrupt

I did notice the names of the vectors changed. I'll try jmps.... No change :|

It doesn't seem to be going haywire, that is, my loop at the ReLoop is still running. I can see the pin twiddeling with my scope.

Hmm. I'm using an ATMega162 and including:

.include "m162def.inc"

(just like in the old project)

The interrupt's working in the simulator.

Curiouser and curiouser.

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you saying you never see the led on PortB,0 switch on?

Keep it simple it will not bite as hard

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
STS TCCR3A,scratch 

Try the "out" instruction instead of "sts".

OUT TCCR3A,scratch 

Will work much better?

:roll:

And here you can leave out SEI.

SEI 
   RETI

8)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Umm did you know that on some of the smaller AVRs the interrupt vectors are a single machine instruction and you program with "RJMP handler" for each active interrupt but on larger devices the vectors are two machine instructions and are populated with "JMP handler".

Your code is using RJMP but the datasheet for 162 shows the use of JMP so it has "double spaced" interrupt vectors. Could this be the source of your problem?

Your comment against ".org ACIaddr " shows "$34" which IS the correct address but are you SURE that's what you have it defined as - have a look at the listing output by the assembler to verify.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How are you testing this? Is there really an LED (or a scope) on PB0?

    cbi PortB,0     ;Turn on an LED so we see this ran

As near as I can tell, PB0 is initialized to 0, and nowhere set to 1, so
this instruction has no effect. (I'd expect the LED to be ON all the time?)

Reloop:
      in scratch,PortB
      ldi r17,2
      eor scratch,r17
      out PortB,scratch
      RJMP ReLoop

On the face of it, this code has a 50% probability of un-doing the CBI
in the ISR (assuming the CBI were doing something). The effect would
be that the LED would light for such a short time as to be undetectable.

It's further possible that if we were to add up all the clocks on the paths
it would turn out that the timer goes off consistently during the "hazardous"
subsequence, i.e. that it Always un-does the CBI.

I'd suggest an alternate coding using e.g. SBIC/CBI.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Out or STS: I found some time ago that I had to use STS instead of OUT on Timer 3 because it's in the extra IO space that OUT can't reach.

RJMPs worked fine on other 162 projects :roll:

I did notice the names in the inc file changed for the vectors. I was used to using

.org TIMER3OVFaddr

but that seems to have changed to OVF3addr

Ok. I started with a blank program and started stuffing things into it until it breaks :roll: I have the timer 3 interrupt interrupting and doing a binary count on one of the 7 segment displays. Whew.

Strange. It runs for a while then goes haywire. I wonder if it's a stack problem...

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

McKenney's correct. The problem was I should have been twiddeling port C not port B. Program now looks like this:

; Timer 1 is used with the comparator to make an A/D converter to read
;	the temperature from a LM34 precision temperature sensor.
; 7 segment displays are connected to PortA, PortC and PortD.
;	MSD is AortD, LSD is PortA.
; PortB is used for the comparator and the programming connector.


.include "m162def.inc"



.def scratch = r16
.def ah = r0	;a
.def al = r1

.def bh = r2	;b
.def bl = r3

.def ch = r6	;c
.def cl = r7
.def Offsetl = r8
.def Offseth = r9
.def Multiplier = r10
.def Dividerl  = r11
.def Dividerh = r12

; LED displays
.equ MSD = PORTA
.equ SSD = PORTC
.equ LSD = PORTD

.cseg ;CODE Segment
.org 0
	rjmp reset ;Reset vector

.org OVF3addr ; Timer 1 overflow vector
	rjmp timer3interrupt

Reset: ;Here on reset
	   ldi	r16,high(RAMEND)	;Intialize stackpointer
	   out	SPH,r16
	   ldi	r16,low(RAMEND)
	   out	SPL,r16

	                            ; Disable Sleep
       clr Scratch
	   out MCUCR,scratch		;


	   out DDRE,scratch		; Port E is input
	   ldi scratch,7
	   out portE,scratch			; And pullups
	   ldi scratch,3
	   OUT DDRB,scratch		; Port B bit 0 and 1 are output
	   
	   sbi ddrb,1
	   cbi PORTB,0

	   LDI scratch,255
	   OUT DDRD,scratch     ; Port D is output
	   OUT DDRC,scratch		; Port C is output
	   OUT DDRA,scratch		; Port A is output

       ldi scratch,0b11111111 
	   out MSD,scratch
	   out SSD,scratch
	   out LSD,scratch
	   CALL InitTimer3

	   SEI					;Enable Interrupts
Reloop: 
        in scratch,PortB
        ldi r17,2
	    eor scratch,r17
	    out PortB,scratch
        RJMP ReLoop

InitTimer3:

    ; Timer 3 is timebase for opperations
       

	ldi scratch,0b00000000  ; 
	STS TCCR3B,scratch      ; Stop timer 3
	STS ETIMSK,scratch      ; Stop overflow interrupt
	STS TCCR3A,scratch
	ldi scratch,255 		; counts from overflow
	sts TCNT3H,scratch
	ldi scratch,100
	sts TCNT3L,scratch
	ldi scratch,0b00000101  ; TCCR31B Clock / 1024
	STS TCCR3B,scratch
	ldi scratch,4  			; Enable overflow interrupt on Timer 3
	STS ETIMSK,scratch

    cbi MSD,0             ; Turn on an LED so we see this got called
	RET

Timer3Interrupt:
	PUSH scratch
	IN scratch,sreg			; Get the status register
	PUSH scratch			; And save that

    IN scratch,LSD
	inc scratch
	OUT LSD,scratch


	;CALL StartAD
    CALL InitTimer3
	POP scratch				; Restore the status register
	OUT sreg,scratch
	POP scratch				; And scratch
	RETI

The behavior is almost right :oops: It blinks segments on and off binary wise for a while, the all of a sudden other LEDs start fiddeling and the count stops. Then after a while, it starts again. Like maybe the stack is growing on each interrupt and overwriting the memory where the ports are... Doesn't seem to do that in the simulator :?

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

First thing I notice is you're making too much use of a single register scratch. Assuming you don't plan to use the other 20 registers for anything, I'd start using more registers in the ISR, so you don't have to keep pushing/popping scratch. Once T3 has been initiated, the ISR should only have to reload the TCNT registers, not do the entire init routine calling InitTimer3. Also you could make use of the "Clear on Compare" mode and not have to worry about reloading the timer registers.

I notice that you're reading back portd, incrementing it, and writing it back to portd. I would be suspitious about this working correctly with LED's on the port, since the voltage levels may be lower then expected and not readback correctly. Rather then store the LSD value in the port register, use another general pupose register to store this value.

.def   SaveSreg = r19
.def   ISRreg = r20
.def   LSDreg = r21

Timer3Interrupt:
   IN SaveSreg,sreg         
   ldi ISRreg,255
   sts TCNT3H,ISRreg
   ldi ISRreg,100
   sts TCNT3L,ISRreg
   inc LSDreg
   OUT LSD,LSDreg
   OUT sreg,SaveSreg
   RETI
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Reading Portx not Pinx...

Ok. I scratched the push and pop instructions and used another register and now it's running without going haywire. I think it just didn't like me pushing and popping the "scratch" register, though it doesn't seem to mind calling the subroutine. I didn't see any difference when I changed the subroutine call to just set the timer.

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

:oops: It seems to have been a hardware problem :oops:

It's now displaying what I want and running the programs I want just like I think it should, except I can't turn off my relay connected to a transistor on port b bit 4... Hmm, that's also SS and that's always an input when you...

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hmmm. My precision temperature controler seems to be more of a random number generator :cry:

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And now, it's working very nicely!

Thanks, guys!

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, here it is:

I make figures for my model railroad using polymer clay, and you have to bake these in an oven, reaching 275 degrees, but not exceeding 300 degrees (or you get smoke). This toaster oven wouldn't hold a temperature near close enough.

I designed it to turn on at less than 280 and off above 285 degrees, so it had a margin either way. It actually does better than that, holding the temperature between 279 and 281, though the display says 276 to 290. (The clip leads go to a dvm to read the real temperature from the sensor).

I had hoped the capacitor charging a/d converter would be a little more linear than it is in the range of 0 - 2 v, but in the range where I want the oven, it is quite fine.

Perhaps I'll try the 555 circuit like this:

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead.