第二次按下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();
}
|