本例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;
}
}
|