本例T/C1工作于定时器方式,TCNT1计数脉冲由系统时钟分频繁后提供,本例系统时钟为1MHz,TCCR1B设置分频比为1,计数时钟仍为1MHz,在该计数时钟下,每1us时间TCNT1计数1次。主程序通过设置TCCR1B=_BV(ICNC1)|_BV(ICES1),设置了输入捕获嗓音消除(ICNC1=1)位和ICP上升沿触发输入捕获(ICES1 = 1)位。由于PD6(ICP)输入捕获引脚输入信号的每次上升沿都将触发捕获,在捕获中断时,中断服务程序通过计算2次所读取的ICR1的差值,即可得出相邻2次TCNT1的计数差值。
以下是Proteus仿真载图
以下是Studio6.2编译通过的截图:
程序清单:
- /*
- * GccApplication6.c
- *
- * Created: 2014-10-30 20:31:23
- * Author: Administrator
- */
- #define F_CPU 1000000UL
- #include <avr/io.h>
- #include <AVR/io.h>
- #include <avr/interrupt.h>
- #include <util/delay.h>
- #include <stdint.h>
- const uint8_t SEG_CODE[]={0x3F,0x06,0x58,0x4f,0x66,0x6d,0x7d,0x07,0x7F,0x6F,0x00};
- uint8_t Display_Buffer[] = {0,0,0,0};
- uint16_t CAPi = 0,CAPj = 0;
- void Show_FRQ_ON_DSY()
- {
- uint8_t i = 0;
- for(i=0;i<4;i++)
- {
- PORTA = 0x00;
- PORTB = ~_BV(i);
- PORTA = SEG_CODE[Display_Buffer[i]];
- if(i==0)PORTA |= 0x80;
- _delay_ms(2);
- }
- }
- int main(void)
- {
- uint8_t LastKey = 0xFF;
- DDRA = 0xFF;
- DDRB = 0xFF;
- DDRC = 0x00; PORTC = 0xFF;
- DDRD = 0x00; PORTD = 0xFF;
- TCCR1B = _BV(ICNC1)|_BV(ICES1);
- sei();
- while(1)
- {
- if(LastKey != PINC)
- {
- TIMSK = _BV(TICIE1);
- TCCR1B |= 0x01;
- LastKey = PINC;
- }
- Show_FRQ_ON_DSY();
- }
- }
- ISR(TIMER1_CAPT_vect)
- {
-
- uint8_t i;
- if(CAPi == 0) CAPi = ICR1;
- else
- {
-
- CAPj = ICR1-CAPi;
- CAPj = 1000000UL/CAPj;
- TIMSK = 0x00;
- TCCR1B &= 0xFC;
- for(i=3;i!=0xFF;i--)
- {
- Display_Buffer[i] = CAPj % 10 ;
- CAPj /= 10;
- }
- TCNT1 = CAPi = CAPj = 0;
-
- }
- }
|