我把程序改了下,可是按键时只有第一次按下有作用,有时复位键有作用,我怀疑是按键消抖作用需要时间太长,和扫描形成了时间差,您觉得是不是有这样的可能。普中的板子是会在长按按键一段时间后自动取消置高电平的吗?- #include <reg52.h>
- #include <intrins.h>
- typedef unsigned char u8;
- typedef unsigned int u16;
- typedef unsigned long u32;
- sbit LS = P2; //38译码器引脚编号,选择数码管
- sbit number = P0; //发送转换表(段码)
- sbit key1 = P3^1; //复位
- sbit key2 = P3^0; //开始/暂停
- sbit key3 = P3^2; //
- sbit key4 = P3^3; //
- u8 code smgduan[17] = {
- 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
- 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71
- };//数码管转换表
- u8 LedBuff[8] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- } ;//数码管缓冲区
- u8 KeySt[4] = {
- 1, 1, 1, 1
- };//按键电平状态储存区
- bit StopwatchRunning = 0; //秒表是否运行(确定是否暂停)
- bit StopwatchRefresh = 1; //秒表是否要刷新
- u8 mseconds = 0; //计数毫秒部分
- u8 seconds = 0; //计数秒部分
- u8 minutes = 0; //计数分钟部分
- u8 T0RH = 0; //T0重装高位
- u8 T0RL = 0; //T0重装低位
- void ConfigTimer0(u16 ms); //配置定时器
- void StopwatchDisplay(); //显示函数(数字分割显示)
- void KeyDriver(); //检测按键,执行指令(主函数中调用)
- void LedScan();
- void KeyScan();
- void main()
- {
- EA = 1; //打开总中断
- ConfigTimer0(2); //定时器2ms
- while(1)
- {
- if(StopwatchRefresh) //是否更新数码管显示
- {
- StopwatchRefresh = 0;
- StopwatchDisplay();
- }
- LedScan();
- KeyScan();
- KeyDriver(); //调用按键驱动
- }
- }
- /*函数部分*/
- void ConfigTimer0(u16 ms)//配置定时器
- {
- u32 tmp;
-
- tmp = 11059260 / 12;
- tmp = (tmp * ms) / 1000;
- tmp = 65536 - tmp;
- tmp += 18; //时间补偿
- T0RH = (u8)(tmp >> 8);
- T0RL = (u8)tmp;
- TMOD &= 0XF0; //仅改变后四位(置零)
- TMOD |= 0X01;
- TH0 = T0RH;
- TL0 = T0RL;
- ET0 = 1;
- TR0 = 1;
- }
- void StopwatchDisplay()//显示函数(数字分割显示)
- {
- signed char i;
- u8 buf[2]; u8 minbuf[2];
- LedBuff[0] = smgduan[mseconds % 10]; //毫秒转换
- LedBuff[1] = smgduan[mseconds / 10];
- buf[1] = seconds % 10;
- buf[2] = (seconds / 10) % 10;
- minbuf[1] = (minutes) % 10;
- minbuf[2] = (minutes / 10) % 10;
- for(i = 1; i < 3; i ++) //秒位数字转换0
- {
- if(buf[i] == 0)
- {
- LedBuff[i + 2] = 0X00;
- }
- else break;
- }
- for(i = 1; i < 3; i ++) //分位数字转换0
- {
- if(minbuf[i] == 0)
- {
- LedBuff[i + 5] = 0X00;
- }
- else break;
- }
- for(i = 1 ; i < 3; i ++) //秒和分位数字转换
- {
- LedBuff[i + 2] = smgduan[buf[i]];
- LedBuff[i + 5] = smgduan[minbuf[i]];
- }
- LedBuff[2] = 0X40; //"-"符号显示
- LedBuff[5] = 0x40;
- }
- void StopwatchAction()//秒表的启动与暂停
- {
- if (StopwatchRunning) //已启动则停止
- StopwatchRunning = 0;
- else //未启动则启动
- StopwatchRunning = 1;
- }
- void StopwatchReset()//秒表复位
- {
- StopwatchRunning = 0;
- mseconds = 0;
- seconds = 0;
- minutes = 0;
- StopwatchRefresh = 1;
- }
- void KeyDriver()//检测按键,执行指令(主函数中调用)
- {
- static u8 i;
- static u8 backup[4] = {1, 1, 1 , 1};//键值对比样本
- for(i = 0; i < 4; i ++)
- {
- if(backup[i] != KeySt[i])
- {
- if(backup[i] != 0)
- {
- if(i == 0)
- {
- StopwatchReset(); //重置
- }
- else if(i == 1)
- {
- StopwatchAction(); //开始/暂停
- }
- }
- else if(i == 1)
- {
- StopwatchAction(); //开始/暂停
- }
- backup[i] = KeySt[i]; //刷新备份,作为下次判定样本
- }
- }
- }
- void KeyScan()//按键扫描
- {
- u8 i = 0;
- static u8 keybuf[4] = {
- 0xFF, 0xFF, 0xFF, 0xFF
- };
- keybuf[0] = (keybuf[0] << 1) | key1; //键值输入,8次分位输入,消抖
- keybuf[1] = (keybuf[1] << 1) | key2;
- keybuf[2] = (keybuf[2] << 1) | key3;
- keybuf[3] = (keybuf[3] << 1) | key4;
- for(i = 0; i < 4; i ++)
- {
- if(keybuf[i] == 0X00)
- {
- KeySt[i] = 0;
- }
- else if(keybuf == 0XFF)
- {
- KeySt[i] = 1;
- }
- }
- }
- void LedScan()//数码管扫描
- {
- u8 i = 0;
- for( ; i < 8; i ++)
- {
- P2 = (P2 & 0XE3) | (i << 2);
- P0 = LedBuff[i];
- _nop_(); //延时两个机器周期
- _nop_();
- P0 = 0x00;
- }
- }
- void StopwatchCount()//秒数统计
- {
- if(StopwatchRunning)
- {
- mseconds ++;
- if(mseconds >= 100)
- {
- mseconds = 0;
- seconds ++;
- if(seconds >= 60)
- {
- seconds = 0;
- minutes ++;
- }
- if(minutes >= 60)
- {
- minutes = 0;
- }
- }
- StopwatchRefresh = 1; //提醒刷新
- }
- }
- void InterruptTimer0() interrupt 1 //中断函数
- {
- static u8 tmr10ms = 0;
-
- TH0 = T0RH;
- TL0 = T0RL;
- tmr10ms ++;
- if(tmr10ms >= 5) //10ms记一次数
- {
- tmr10ms = 0;
- StopwatchCount();
- }
- }
复制代码 |