;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Author: MLH ; Date: 9 May 2007 ; Purpose: ; This example demonstrates the use of the Timer/Counter subsystem. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .NOLIST .include "m32def.inc" .LIST ; data segment, reserve data memory in SRAM .DSEG overflow_counter: .byte 1 ; this byte stores the number of Counter0 overflows ; code segment for program instructions .CSEG .ORG 0 rjmp start .ORG 0x14 ; Output Comparator vector rjmp comparator_matchISR .ORG 0x16 ; Counter0 Overflow vector rjmp counter0_overflowISR .DEF temp=r18 ; use arbitrary register for temporary operations .org 0x2a start: ; Initialize the Stack Pointer (SP) CPU register for subsequent use ldi temp, LOW(RAMEND) ; get low byte of the address of the highest byte in Data Memory we can use out SPL, temp ; load it into the low byte of SP ldi temp, HIGH(RAMEND) ; high byte of address of highest Data Memory byte out SPH, temp ; load it into the high byte of SP ldi temp, 0xFF ; setup PortB for digital output out DDRB, temp andi temp, 0x00 out PORTB, temp ; turn LEDs off clr temp sts overflow_counter, temp ; initialize overflow_counter to 0 ; initialize Timer/Counter0 out TCNT0, temp ; clear Counter0 counter register; this is what Counter0 increments in temp, TCCR0 ; get current state of Timer/Counter0 Control Register andi temp, 0b11111000 ; clear CS02:CS00 that control frequency ori temp, 0b00000100 ; set CS02:CS00 to increment Counter0 every 256 CPU clock cycles (16us @ 16MHz) out TCCR0, temp ; counter is now running, TCNT0 is incrementing automatically every 16us ; next, enable Counter0 interrupts in temp, TIMSK ; get state of Timer/Counter Interrupt Mask andi temp, 0b11111100 ; clear TOIE0 and OCIE0; keep other bits ori temp, 0b00000001 ; set bit TOIE0 to enable Counter0 overflow interrupt ; ori temp, 0b00000010 ; set bit OCIE0 to enable Output Comparator interrupt out TIMSK, temp sei ; this enables interrupts globally loop: rjmp loop ; loop forever, waiting for Timer/Counter interrupts ; interrupt handler counter0_overflowISR ; Purpose: implements the handling of the Timer/Counter0 overflow interrupt ; Every time the Counter0 overflow interrupt occurs, the overflow_counter (a byte in data memory) ; is incremented. The Counter0 is incremented every 256 clock cycles (16us), which ; corresponds to an overflow every 4096us, or 4.096ms. This means 244 overflows takes ; 999.424ms, or 0.999424s. After counting this many overflows, the LEDs are blinked. counter0_overflowISR: push temp lds temp, overflow_counter ; load last-stored value of overflow_counter from data memory inc temp ; increment value of overflow_counter in temp register cpi temp, 244 ; check if overflow_counter has reached 244 breq reset ; if so, reset the overflow_counter to 0 sts overflow_counter, temp ; store incremented value of overflow_counter clr temp ; all bits 0 out PORTB, temp rjmp end_ISR reset: ; reset the overflow_counter to 0 clr temp com temp ; all bits 1 out PORTB, temp ; toggle LEDs clr temp sts overflow_counter, temp ; here's where we actually clear the overflow_counter end_ISR: pop temp ; restore temporary registers reti ; end interrupt handler counter0_overflowISR ; interrupt handler comparator_matchISR ; Purpose: implements the handling of the Output Comparator match comparator_matchISR: // TODO: implement if using Output Comparator reti ; end interrupt handler comparator_matchISR