;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Author: MLH ; Date: 8 Feb 2008/updated Feb 2012 ; Purpose: ; This example demonstrates the use of the Timer/Counter input capture ; to measure the number of ticks that occur between successive presses ; of a pushbutton that causes the voltage on in PD6 (ICP) to fall to 0v. ; Configuration: connect pushbutton switch on PD2 to PD6. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .NOLIST .include "m32def.inc" .LIST ; code segment for program instructions .CSEG .ORG 0 rjmp start .ORG 0xC ; Counter 1 input capture rjmp counter1_captureISR .ORG 0x12 ; Counter 1 overflow rjmp counter1_overflowISR .DEF temp=r22 ; use arbitrary register for temporary operations .DEF overflow_counter=r25 ; use this register to count TC1 overflows between input capture events .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 ; setup PortB for digital output ldi temp, 0xFF out DDRB, temp ldi temp, 0x00 out PORTB, temp ; all LEDs off ; configure PD6 for input (for Input Capture using TC1) cbi DDRD, 6 sbi PORTD, 6 ; pull PD6 high cbi DDRD, 2 sbi PORTD, 2 ; pull PD2 high ; initialize the LCD display rcall display_init ; initialize the LCD display rcall display_clear rcall initTC1 ; initialze TC1 sei ; this enables interrupts globally loop: ; clear LEDs every 100ms rcall delay100 cbi PORTB, 0 cbi PORTB, 1 rjmp loop ; loop forever, waiting for Timer/Counter interrupts ; subroutine initTC1 ; initializes Timer/Counter1 in Normal mode with Input Capture on PD6 (ICP) enabled, ; as well as overflow interrupts enabled. The prescaler is set so that overflows take ; place about every second initTC1: push temp ; reset Timer/Counter1 (Normal mode, stopped) clr temp ; clear all bits in TCCR1A out TCCR1A, temp ; initialize the overflow counter clr overflow_counter ; initialize (clear) Timer/Counter1 registers clr temp out TCNT1L, temp out TCNT1H, temp ; initialize (clear) input capture registers out ICR1L, temp out ICR1H, temp ; enable Counter1 input capture interrupt in temp, TIMSK ; get state of Timer/Counter Interrupt Mask andi temp, 0b11000011 ; clear TICIE1, OCIE1A, OCIE1B and TOIE1; other bits for TC0 and TC2 settings ori temp, 0b00100100 ; set bit TICIE1, TOIE1 to enable input capture interrupt and overflow interrupt out TIMSK, temp ; Start the Counter ticking once every 256 clock cycles 62500 ticks/s). ; Since TC1 counts up to 65535 before overflowing, each overflow takes 1.046s. clr temp sbr temp, 0b00000100 ; set CS12-CS10 (bits 2-0); clock divider=256 ori temp, 0b00000000 ; clr ICNC1 (no noise cancel); ICES1=0 (select falling edge) out TCCR1B, temp pop temp ret ; end subroutine initTC1 ; interrupt handler counter1_captureISR ; Purpose: implements the handling of the Timer/Counter1 input capture event. ; This ISR is triggered whenever the signal on the input capture pin (ICP, or PD6) falls counter1_captureISR: cli push r0 push r23 push temp push ZL push ZH in r0, SREG ; get current value of status reg push r0 ; save the value on the stack sbi PORTB, 1 ; light LED1 to indicate TIC ; output the value of the overflow counter ldi r23, 0x80 ; move cursor to first line, first column rcall display_gotoLocation mov ZL, overflow_counter ; overflow counter is just 1 byte, so put it in ZL clr ZH ; ZH is always 0 when displaying the overflow counter value rcall displayValue16 ; now clear the overflow counter clr overflow_counter ; write a separator character ldi r23, '*' mov r0, r23 rcall sendByte ; copy input capture registers in ZL, ICR1L in ZH, ICR1H rcall displayValue16 ; reset Timer/Counter1 registers clr temp out TCNT1H, temp out TCNT1L, temp pop r0 ; pop the saved value of SREG from the stack out SREG, r0 ; restore SREG pop ZH pop ZL pop temp pop r23 pop r0 reti ; end interrupt handler counter1_captureISR ; interrupt handler counter1_overflowISR ; Purpose: implements the handling of the Timer/Counter1 overflow interrupt. ; This ISR is triggered whenever the Counter register TCNT1 overflows when the T/C is in Normal mode counter1_overflowISR: in r0, SREG ; get current value of status reg push r0 ; save the value on the stack inc overflow_counter sbi PORTB, 0 ; light LED0 to indicate overflow pop r0 ; pop the saved value of SREG from the stack out SREG, r0 ; restore SREG reti ; end interrupt handler counter1_overflowISR .include "delay.asm" .include "rs232_dd.asm" .include "display_dd.asm"