Timer Issue

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

I'm running into an issue with my timer for the ATmega644, where the timer was running way too fast. Below is the source for my clock program. The simulator runs the program fine, but I'm finding that it's running way too fast when loaded onto the actual micro controller, even at a prescaler of 1024 it is going way too fast (led binary display counts up to 60 several times a second). Can someone please take a look to see what the issue may be.

NOTE: Timer 1 counts up to 15625, with a prescaler of 64 @ 1MHz, after reaching 15625, it increments r0 which is output to the LEDs. Theres no way it should be incrementing this fast.

;************************************************************************
;*		Standard Hours:Minutes:Seconds Clock, supports AM, PM, & Days	*
;*					By Austin Salgat			V1		12/26/07		*
;************************************************************************
;
;
;
;DESCRIPTION
;	Using the 16 bit counter, increments a counter every second. This counter
;	is reset every 60 seconds, which in turn increments a counter that keeps
;	track of minutes. When the minutes counter reaches 60, it is reset and
;	the hours counter is incremented. This process is continued untill the
;	hours counter reaches 24, at which time it will reset to 0. For ensured
;	precision, a crystal is used as the frequency source. In this case, the
;	frequency source is assumed to be 1MHz, which will allow for low power
;	applications (especially low for the ATmega644p). This counter is designed
;	with the ATmega644 in mind, and an optional LCD display can be added to the
;	program to output the data.
;
;
;	R0 = Seconds Counter
;	R1 = Minutes Counter
;	R2 = Hours Counter
;	R16 = Holds constant 60 (to compare to R0 & R1)
;	R17 = Holds constant 24 (to compare to R2)
;
;
;NOTE
;	This circuit is intended to be save as much power as possible, so it is advised
;	to set the fuses to disable any features not needed. If a feature is needed,
;	comment out the disabling feature in the INITIALIZATION section or change the
;	fuses to your needs.


;**** DIRECTIVES ****
.device		ATmega644
.include	"C:\Program Files\Atmel\AVR Tools\AvrAssembler2\Appnotes\m644def.inc"

.def	TEMP		=r16		;Used for changing Registers
.def	SIXTY		=r17		;Holds constant 60 (to compare to R0 & R1)
.def	TWENTYFOUR	=r18		;Holds constant 24 (to compare to R2)
.def	SECONDS		=r0			;Seconds Counter
.def	MINUTES		=r1			;Minutes Counter
.def	HOURS		=r2			;Hours counter

.org	$0000	;RESET
	jmp		RESET

.org	$001A	;CTC Interrupt
	jmp		INC_TIME

.org 	$0100
;**** INITIALIZATION ****
RESET:
	ldi		TEMP,high(RAMEND)	;INIT STACK
	out		SPH,r16				;
	ldi		TEMP,low(RAMEND)	;
	out		SPL,r16				;

	ldi		SIXTY,60			;Set Constants
	ldi		TWENTYFOUR,24		;

;	ldi		TEMP,0b00000000		;Disable ADC (to save power)
;	sts		ADCSRA,r16			;

;	ldi		TEMP,0b10000000		;Disable Analog Comparator (to save power)
;	out		ACSR,r16			;

;	ldi		TEMP,0b11100111		;Disable Various Features (to save power)
;	sts		PRR,r16				;

;
;**** TIMER INIT ****	CTC MODE
;~~~~~~~~~~~~~~~~~~~~TESTING~~~~~~~~~~~~~~~~~~~~~~;
;	ldi		TEMP,low(40)		;Value to Clear Timer and Set Interrupt Flag
;	sts		OCR1AL,r16			;(THESE VALUES ARE FOR TESTING)
;	ldi		TEMP,high(40)		;
;	sts		OCR1AH,r16			;

;	ldi		TEMP,0b00001001		;TCCR1B Register
;	sts		TCCR1B,r16			;1x Prescaler (Modify this for an external crystal)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;

	ldi		TEMP,low(15625)		;Value to Clear Timer and Set Interrupt Flag
	sts		OCR1AL,r16			;
	ldi		TEMP,high(15625)	;
	sts		OCR1AH,r16			;

	ldi		TEMP,0b00001011		;TCCR1B Register
	sts		TCCR1B,r16			;64x Prescaler (Modify this for an external crystal)

	ldi		TEMP,0b00000010		;Set Interrupt
	sts		TIMSK1,r16			;

	ldi		TEMP,$FF			;Set PORTB to OUTPUT
	out		DDRB,TEMP			;


;**** MAIN ****
MAIN:
	sei							;Enable Interrupts

	mov		r3,r0				;LEDs go HIGH when Pins are Low, ONEs COMPLEMENT made to fix this issue.
	com		r3					;
	out		PORTB,r3			;Output Seconds to PORTB

;	ldi		TEMP,0b00000001		;Configure Sleep Mode for IDLE
;	out		SMCR,r16			;
;	sleep						;Save power, Wait for interrupt from Counter

	rjmp	MAIN				;Loop back


;**** TIMER INTERRUPT ****
INC_TIME:
;	ldi		r16,0b00000000		;Disable Sleep Mode
;	out		SMCR,r16			;

	inc		SECONDS				;Increment Seconds Counter
	
	cp		SIXTY,SECONDS		;Has Seconds Counter Reached 60?
	breq	INC_MIN				;If Seconds Counter = 60, branch to Minutes Increment	
	reti						;If Seconds Counter < 60, go back to Sleep


INC_MIN:
	clr		SECONDS				;Since Seconds Counter has reached 60, clear it
	inc		MINUTES				;Increment Minutes since it has been 60 seconds

	cp		SIXTY,MINUTES		;Has Minutes Counter Reached 60?
	breq	INC_HOUR			;If Minutes Counter = 60, branch to Hours Increment
	reti						;If Minutes Counter <60, go back to Sleep


INC_HOUR:
	clr		MINUTES				;Since Minutes Counter has reached 60, clear it
	inc		HOURS				;Increment Hours since it has been 60 minutes

	cp		TWENTYFOUR,HOURS	;Has Hours Counter Reached 24?
	brne	INC_HOURNE			;Hours Counter < 24
	clr		HOURS				;Hours Counter = 24

INC_HOURNE:
	reti						;Go back to Sleep



Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
   ldi      TEMP,low(15625)      ;Value to Clear Timer and Set Interrupt Flag
   sts      OCR1AL,r16         ;
   ldi      TEMP,high(15625)   ;
   sts      OCR1AH,r16         ; 

Quote:
To do a 16-bit write, the high byte must be written before the low byte. For a 16-bit read, the low byte must be read before the high byte.

write OCR1AH first.

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

Thank you so much! My best guess is that in my haste I confused the READ asm example with the WRITE one. It feels so great to have the program working properly.