第二次按下K2暂停跑表,正常显示xx秒xx毫秒。
#include "reg52.h"
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define N_key 0 //按键没被按下
#define S_key 1 // 单击
#define D_key 2 //双击
#define L_key 3 //长安
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2
#define key_state_3 3
sbit key1 = P3^0;
sbit key2 = P3^2;
unsigned char time_10ms_ok = 0;
unsigned char key = 0;
//引脚定义:
sbit LED8_0 = P1^0; //定义数码管阳级控制脚(千位)
sbit LED8_1 = P1^1; //定义数码管阳级控制脚(百位)
sbit LED8_2 = P1^2; //定义数码管阳级控制脚(十位)
sbit LED8_3 = P1^3; //定义数码管阳级控制脚(个位)
sbit LED=P1^7;
sbit led=P1^6;
uchar Flag_Fresh = 0; // 刷新标志
bit flag=1;
bit sflag,dflag,lflag;
bit T1keyflag,INT0flag;
unsigned char disp_BUF[4]; //显示缓冲区(4个字节,对应4个数码管)
//disp_BUF[0] disp_BUF[1] disp_BUF[2] disp_BUF[3]
// 千位 百位 十位 个位
uchar shi,fen,counter;
uint count=0;
uint miao=0;
const unsigned char leddata[]={
0x03, //"0" 显示码/段码/字形码
0x9F, //"1"
0x25, //"2"
0x0D, //"3"
0x99, //"4"
0x49, //"5"
0x41, //"6"
0x1F, //"7"
0x01, //"8"
0x09, //"9"
0x11, //"A"
0xC1, //"B"
0x63, //"C"
0x85, //"D"
0x61, //"E"
0x71, //"F"
0x91, //"H"
0xE3, //"L"
0x13, //"n"
0x83, //"u"
0x31, //"P"
0xC5, //"o"
0xFD, //"-"
0xFF, //熄灭
0xFE,
0x11 //自定义
};
enum KeyState{StateInit,StateAffirm,StateSingle,StateRepeat};
//======================================函数声明=======================
void delay20ms(void);
void HEXtoBCD_miao(uchar count);
void display_LED(void);
void HEXtoBCD_shi(uchar miao);
void delay();
//=================延时函数================================================//
void delay()
{
unsigned int j;
//for(i=0; i<100; i++)
for(j=0; j<200; j++); //软件延时
}
//=========================T0初始化========================================//
void T0_init(void)
{
TMOD = 0x01; // 设置定时器0工作在模式1下
TH0 = 0xDC; // 定时10ms
TL0 = 0x00; // 赋初始值
PT0=0;
EA=1;
ET0=1;
// TR0 = 1;//启动定时器0;
}
//======================================外部中断0初始化================
void INT0init()
{
EA=1;
EX0=1;
IT0=1;
}
//===================================================T1初始化=============
void T1_Init(void) //10毫秒@12.000MHz
{
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x10; //设置定时器模式
PT1=1;
TL1 = 0xF0; //设置定时初值
TH1 = 0xD8; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
EA=1;
ET1=1;
}
//=============================================开机初始化=================
void start_init()
{
delay20ms();
disp_BUF[0] = leddata[22];
disp_BUF[1] = leddata[22];
disp_BUF[2] = leddata[22];
disp_BUF[3] = leddata[22];
P0=0xff;
}
//===================延时环数==============================================//
void Delay5ms() //@12.000MHz
{
unsigned char i, j;
i = 10;
j = 183;
do
{
while (--j);
} while (--i);
}
void delay20ms(void)
{
unsigned int i;
for(i=0; i<3850; i++);
}
//============================//数码管显示=====================================//
void display_LED(void)
{
unsigned char temp,i;
temp = 0xfe; //1111 1110 1111 1100 1111 1010
// 1111 1101 1111 1011
for(i=0; i<4; i++)
{
P1 = temp; //temp中是“位选”
temp = (temp<<1)|0x01;
P0 = disp_BUF[i]; //送“段码”(要显示的内容)
delay(); //扫描刷新时间(频率)
//时间长——会闪烁、时间短——会模糊(有其他的笔画)
}
}
//========函数名称:HEXtoBCD===============================================
//函数功能:转换一个小于9999的十六进制数为BCD码(非压缩)并放入显示缓冲区disp_BUF[0]--disp_BUF[3]中================================//
void HEXtoBCD_shi(uchar miao)
{
if(shi> 59)shi =0;
disp_BUF[0] = leddata[miao/10];//得到时的高位,并送到相应的显示缓冲区
P0=0xff;
if(flag)
{
disp_BUF[1] = leddata[miao%10]&0xfe; //小数点闪烁
}
else
{
disp_BUF[1] = leddata[miao%10]; //得到时的低位,并送到相应的显示缓冲区
P0=0xff;
}
}
void HEXtoBCD_miao(uchar count)
{
if(miao>99) miao=0;
disp_BUF[2] = leddata[count/10]; //得到秒的高位,并送到相应的显示缓冲区
P0=0xff; //消除鬼影
disp_BUF[3] = leddata[count%10]; //得到秒的位,并送到相应的显示缓冲区
P0=0xff;
}
// ============================================外部中断counter处理函数========================
void counterhandle()
{
if(counter==1)
{
EA=1;
TR0=1;
}
else if(counter==2)
{
EA=1;
TR0=0;
}
else if(counter==3)
{
TR0=0;
EA=1;
count=0;
miao=0;
counter=0;
}
}
//============================================标志处理函数==============================
void flaghandle()
{
if(dflag==1)
{
disp_BUF[0] = leddata[1];
P0=0xff;
disp_BUF[1] = leddata[2];
P0=0xff;
disp_BUF[2] = leddata[3];
P0=0xff;
disp_BUF[3] = leddata[4];
P0=0xff;
dflag=0;
}
if(sflag==1)
{
disp_BUF[0] = leddata[16];
P0=0xff;
disp_BUF[1] = leddata[14];
P0=0xff;
disp_BUF[2] = leddata[17];
P0=0xff;
disp_BUF[3] = leddata[21];
P0=0xff;
sflag=0;
}
if(lflag==1)
{
if(flag)
{
disp_BUF[0] = leddata[23];
disp_BUF[1] = leddata[23];
disp_BUF[2] = leddata[23];
disp_BUF[3] = leddata[23];
}
else {
disp_BUF[0] = leddata[22];
disp_BUF[1] = leddata[22];
disp_BUF[2] = leddata[22];
disp_BUF[3] = leddata[22];
}
lflag=0;
}
}
//===========================================按键扫描======================
unsigned char key_driver(void)
{
static unsigned char key_state = key_state_0; // 变量初始化
static unsigned int keytime = 0;
unsigned char key_return = N_key;
bit key_press; //定义一个位
key_press = key1; //P3^0的按下状态,按下0,不按为1
switch (key_state)
{
case key_state_0:
if (!key_press) key_state = key_state_1; //如果按键被按下,置状态1
break;
case key_state_1:
if (!key_press) //判断状态1
{ //如果按键还是被按下的 “去抖”
keytime = 0; //按下时间初始值为0
key_state = key_state_2; //按键还是被按下的,置状态2
}
else
key_state = key_state_0; //否则置状态0,再次进行按键判断
break;
case key_state_2:
if(key_press) //如果按键是没被按下的,key_press为1 即条件为真。按下为0,条件为假
{
key_return = S_key; // 状态2中按键是被松开的,即判断为单击
key_state = key_state_0; //返回状态0,进行下次的按键操作
}
else if (++keytime >= 1000) // if条件为假按键还是被按下的,进行key_time自增运算,再进行key_time>=1000的判断
{
key_return = L_key; //如果条件成立、则定义为长按的操作
key_state = key_state_3; // 进入状态3
}
break; //跳出循环
case key_state_3: // 执行状态3的操作
if (key_press) key_state = key_state_0; //如果按键被松开了,返回状态0
break;
}
return key_return; //返回值key_return
}
unsigned char key_read(void) // 键值处理函数
{
static unsigned char key_m = key_state_0 ; //静态变量 key_m,key_time_1。
static unsigned int key_time_1 = 0;
unsigned char key_return = N_key,key_temp; //
key_temp = key_driver(); //key_temp= key_return。(S_key或者L_key)
switch(key_m)
{
case key_state_0: //状态0的操作
if (key_temp == S_key ) // 如果判断为单击
{
key_time_1 = 0; // key_time_1初始值为0
key_m = key_state_1; // 进入状态2
}
else
key_return = key_temp; // 状态0里,将 key_temp的值给key_return
break;
case key_state_1: //状态1
if (key_temp == S_key) //单击之后还有一次按键
{
key_return = D_key; // 定为双击
key_m = key_state_0; // 返回状态0
}
else
{
if(++key_time_1 >= 500)//key_time_1 自增,如果大于等于500 (两次按键时间间隔大于50)
{
key_return = S_key;// 定义为单击
key_m = key_state_0;// 返回状态0
}
}
break; //跳出循环
}
return key_return; // 返回值key_return
}
//===========================================主函数=======================
void main(void)
{
T1_Init() ;
T0_init();
INT0init();
start_init();
while(1)
{
if(INT0flag==1)
{
HEXtoBCD_shi(miao);
HEXtoBCD_miao(count);
INT0flag=0;
display_LED();
}
else if(T1keyflag==1)
{
T1keyflag=0;
display_LED(); //数码管显示
}
}
}
//======================================T0 T1 中断函数========================
void T0_ISR(void) interrupt 1
{
TH0 = 0xDC; // 定时10ms
TL0 = 0x00;
count++;
if(count==100)
{
count=0;
miao++;
led=~led;
flag=~flag;
if(miao>59)
miao=0;
}
}
void T1_ISR(void) interrupt 3
{
TL1 = 0xF0; //设置定时0初值
TH1 = 0xD8; //设置定时初值
LED=~LED;
flaghandle();
key = key_read(); //没10ms得到一次 key_return
T1keyflag=1;
if (key == L_key) //长按清零
{
lflag=1;
}
else if(key == S_key) //单击
{
sflag=1;
}
else if(key == D_key) //双击停止
{
dflag=1;
}
}
void INT0_ISR(void) interrupt 0
{
delay20ms();
EA=0;
counter++;
INT0flag=1;
counterhandle();
}
|