想实现按键触发的输入捕捉,计算计数次数。思路是:开发板刚上电,使能溢出中断和输入捕捉中断,然后等待第一次按键按下。如果第一次按键按下触发了输入捕捉中断,进入中断服务程序后把0写入PER1。然后等待第二次输入捕捉中断,当第二次输入捕捉中断到来时,关闭预分频,把计数值写入PER2,用PER2-PER1得到两次按键期间的计数值,若其中发生溢出count++。计算出数值以后显示在数码管上,但是实际工作时,数码管始终显示全0。求高手能帮忙看看,解决小弟这个超超超新人的困惑。感激不尽
/*
* capture.c
*
* Created: 2014-8-25 14:11:47
* Author: Administrator
*/
#include <avr/io.h>
#define F_CPU 8000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
unsigned char DuanMa[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
unsigned char WeiMa[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
volatile unsigned char TempData[8];
unsigned char count = 0;
volatile unsigned char num = 0;
volatile unsigned int PER1=0,PER2=0;
volatile unsigned long int PER = 0;
void led_init(void)
{
DDRA = 0xff;
DDRF |= (1 << 3);
PORTA = 0xff;
PORTF |= (1 << 3);
PORTF &= ~(1 << 3);
}
void seg_init(void)
{
DDRA = 0xff;
DDRC = 0xff;
DDRF |= (1 << 1) | (1 << 2);
PORTC = 0xff;
PORTF |= (1 << 1);
PORTF &= ~(1 << 1);
PORTA = 0xff;
PORTF |= (1 << 2);
PORTF &= ~(1 << 2);
}
void seg_display(unsigned char firstbit,unsigned char weishu) //数码管显示函数
{
static unsigned char i;
PORTC = 0xff; //数码管消隐
PORTF |= (1 << 1);
PORTF &= ~(1 << 1);
PORTC = TempData[i];
PORTF |= (1 << 1);
PORTF &= ~(1 << 1);
PORTA = WeiMa[i+firstbit];
PORTF |= (1 << 2);
PORTF &= ~(1 << 2);
_delay_ms(1);
i++;
if(i == weishu)
i = 0;
}
void portd_init(void)
{
DDRD &= (0 << 4); //PD4设为输入口
PORTD |= (1 << 4); //PD4输出高电平
}
void timer1_init(void)
{
TCCR1A = 0x00; //设为普通模式
TCCR1B |= (1 << ICNC1) | (0 << ICES1) | (0 << CS12) | (0 << CS11) | (0 << CS10); //开启输入捕捉噪声抑制器,输入捕捉下降沿触发,无时钟
TIMSK |= (1 << TICIE1) | (1 << TOIE1); //定时计数器1输入捕捉使能,溢出中断使能
sei(); //开启总中断
}
int main(void)
{
led_init();
seg_init();
portd_init();
timer1_init();
while(1)
{
PER = ((65535*count+PER)*8); //计算两次按键时间间隔
TempData[0] = DuanMa[PER/10000000];
TempData[1] = DuanMa[(PER%10000000)/1000000];
TempData[2] = DuanMa[(PER%10000000%1000000)/100000];
TempData[3] = DuanMa[(PER%10000000%1000000%100000)/10000];
TempData[4] = DuanMa[(PER%10000000%1000000%100000%10000)/1000];
TempData[5] = DuanMa[(PER%10000000%1000000%100000%10000%1000)/100];
TempData[6] = DuanMa[(PER%10000000%1000000%100000%10000%1000%100)/10];
TempData[7] = DuanMa[(PER%10000000%1000000%100000%10000%1000%100)%10];
seg_display(0,8);
}
}
ISR(TIMER1_CAPT_vect)
{
num++;
if(((num % 2) == 1) && ((TIFR & 0x04) == 0x00))
{
PER = 0; //初始为0
count = 0; //溢出次数为0
TCNT1 = 0; //计数器初值为0
ICR1 = 0; //捕捉寄存器初值为0
PER1 = ICR1; //标记初值
TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10); //开启8分频
}
if(((num % 2) == 0) && ((TIFR & 0x04) == 0x00))
{
TCCR1B &= ~((1 << CS12) | (1 << CS11) | (1 << CS10)); //时钟停止
PER2 = ICR1; //读取第二次按键后计数器值
PER = PER2 - PER1; //计算两次按下时间间隔
}
}
ISR(TIMER2_OVF_vect)
{
count++; //溢出次数计数
} |