📄 消抖的另一种方法(avr).txt
字号:
贴上实验二中的2个参考代码
在实验板上设计一个采用外部中断方式的6位数码管(分、秒、1%秒各占2位)显示的简易秒表系统。可以先使用CVAVR中的程序生成向导功能进行配置,然后在它生成的程序框架基础上完成定时器中断部分程序。该系统程序设计可参考demo_7_2.c,在这个基础上修改代码,最终设计出一个完整的秒表系统。
提示:使用Mega16两个外部中断源INT0和INT1。将其中一个外部中断源与板上500Hz的标准频率相连,另外的一个外部中断源与一个按键相连。500Hz的标准频率被作为秒表系统的计时基准。按键的起到了“开始/停止/清零”作用。上电后,数码管显示全零,第一次按键,表示秒表计时开始,数码管显示的数值按1%秒速率计时。第二次按键计时停止,数码管显示最终的计时时间。第三次按键对数码管清零。以上功能可反复执行。
/*********************************************
Chip type : ATmega16
Program type : Application
Clock frequency : 4.000000 MHz
Memory model : Small
External SRAM size : 0
Data Stack size : 256
*********************************************/
#include <mega16.h>
flash unsigned char led_7[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
flash unsigned char position[6]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
unsigned char time[3]; // 时、分、秒计数单元
unsigned char dis_buff[6]; // 显示缓冲区,存放要显示的6个字符的段码值
unsigned char time_counter; // 中断次数计数单元
unsigned char posit;
unsigned char key_state=0;
bit pre_pind3, int1_off, time_10ms_ok,time_20ms_ok;
void display(void) // 6位LED数码管动态扫描函数
{
PORTC = 0xff;
PORTA = led_7[dis_buff[posit]];
if (posit==2 || posit == 4) PORTA |= 0x80;
PORTC = position[posit];
if (++posit >=6 ) posit = 0;
}
// External Interrupt 0 service routine 2ms 一次
interrupt [EXT_INT0] void ext_int0_isr(void)
{
display(); // 调用LED扫描显示
if (++time_counter>=5)
{
time_counter = 0;
time_10ms_ok = 1;
}
}
// External Interrupt 1 service routine 外部按键中断
interrupt [EXT_INT1] void ext_int1_isr(void)
{
GICR &= 0x7F; // 关INT1中断,是做消抖处理
int1_off = 1;
pre_pind3 = 0;
if (++key_state>=3) key_state = 0;
}
void time_to_disbuffer(void) // 时钟时间送显示缓冲区函数
{
unsigned char i,j=0;
for (i=0;i<=2;i++)
{
dis_buff[j++] = time[i] % 10;
dis_buff[j++] = time[i] / 10;
}
}
void main(void)
{
PORTA=0x00; // 显示控制I/O端口初始化
DDRA=0xFF;
PORTC=0x3F;
DDRC=0x3F;
PORTD = 0xFF; // PD2,PD3输入,上拉有效
time[2] = 0; time[1] = 0; time[0] = 0; // 设时间初值00:00:00
posit = 0;
time_to_disbuffer();
GICR|=0xC0; // INT1,INT0中断允许
MCUCR=0x0A; // INT1,INT0下降沿触发
#asm("sei") // 全局中断允许
while (1)
{
if (key_state == 0)
{
time[0] = 0;
time[1] = 0;
time[2] = 0;
time_to_disbuffer();
}
if (time_10ms_ok) // 10ms到
{
time_10ms_ok = 0;
time_20ms_ok = ~time_20ms_ok;
if ( time_20ms_ok && int1_off ) // 这段是间隔20ms检测按键是否释放
{ // 确认释放后开INT1中断,可以接收下次的按键
if (PIND.3 && pre_pind3) // 这样就防止了一次按键过程中按键抖动对INT1的影响,构成消抖功能
{
GIFR |= 0x80;
GICR |= 0x80;
int1_off = 0;
}
pre_pind3 = PIND.3;
}
if (key_state == 1)
{
if (++time[0] >= 100) // 以下时间调整
{
time[0] = 0;
if (++time[1] >= 60)
{
time[1] = 0;
if (++time[2] >= 60) time[2] = 0;
}
}
time_to_disbuffer(); // 新调整好的时间送显示缓冲区
}
}
}
}
==============================================================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -