欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標(biāo)題:
單片機(jī)單個按鍵狀態(tài)機(jī)編程控制5種不同LED閃法程序與仿真
[打印本頁]
作者:
nxw_toyosz
時間:
2022-9-17 10:22
標(biāo)題:
單片機(jī)單個按鍵狀態(tài)機(jī)編程控制5種不同LED閃法程序與仿真
LED流水燈堆疊設(shè)計,且按鍵不占用CPU時間,上電顯示第1功能,單個按鍵的單擊顯示第2種功能,單按第5次返回第1功能,任意功能長按2S以上返回第2功能.程序注釋全。附件包含程序源碼和PROTUSE仿真圖。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.gif
(66.59 KB, 下載次數(shù): 20)
下載附件
2022-9-17 15:57 上傳
單片機(jī)源程序如下:
/*****************************************************************************
*名稱:頭文件,預(yù)定義。
*功能:包含頭文件,預(yù)定義,端口定義
******************************************************************************/
#include<reg51.h> //包含 51 單片機(jī)寄存器定義的頭文件
#define uchar unsigned char //定義uchar可在函數(shù)中當(dāng)unsign char使用,取值不超過255。
#define uint unsigned int //定義uint可在函數(shù)中當(dāng)unsign int使用,取值不超過65535。
sbit KEY=P1^0; //定義按鍵KEY為P1.0
#define LED P2 //定義LED為P2口
#define KEY_STATE_0 0 //按鍵初始狀態(tài)
#define KEY_STATE_1 1 //按鍵消抖
#define KEY_STATE_2 2 //按鍵按下功能種類是單擊,雙擊還是長按
#define KEY_STATE_3 3 //按鍵彈起
#define SINGLE_KEY_TIME 3 //SINGLE_KEY_TIME*10MS = 30MS?判定單擊的時間長度,軟件消抖
#define KEY_INTERVAL 30 //KEY_INTERVAL*10MS?= 300MS 判定雙擊的時間間隔
#define LONG_KEY_TIME 200 //LONG_KEY_TIME*10MS? ?= 2S? ?判定長按的時間長度
#define N_KEY 0 //按鍵沒動作
#define S_KEY 1 //單擊
#define L_KEY 2 //長按
#define D_KEY 3 //雙擊
uchar code Zuoyi[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //左流水?dāng)?shù)組,低電平導(dǎo)通
uchar code Youyi[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //右流水?dāng)?shù)組,低電平導(dǎo)通
uchar keySu=0; // 定義按鍵功能狀態(tài)變量
uchar key_val; // 按鍵值
uchar time_10ms_ok=0; //10MS定時標(biāo)志
//define LongCount 100; //延時長按變量100X10MS=1S
/******************************************************************************
***函數(shù)名稱: void delay_ms(uint x)
***函數(shù)功能: MS延時(按下按鍵時,可以跳出循環(huán)體)
***輸入: 無
***輸出: 無
******************************************************************************/
/*******/
void delay_ms(uint x) // 延時函數(shù),延時x MS,
{
uint i; //定義無符號字符型變量j值域為0-65536.
uchar j; //定義無符號字符型變量i值域為0-255.
if(KEY) //如果按鍵為1時,則執(zhí)行延時循環(huán)
{
for(i=0;i<x;i++) // 循環(huán)x遍
{
for(j=0;j<112;j++)
; //空語句等待一個機(jī)器周期
}
}
else //如果按鍵按下則跳出循環(huán)
return;
}
/******************************************************************************
***函數(shù)名稱: void move_l(void)
***函數(shù)功能: 左流水(P2口低位向高位流動跑馬)
***輸入: 無
***輸出: 無
******************************************************************************/
/******/
void move_l(void) //1.左流水函數(shù)
{
uchar b; //循環(huán)變量b
while(1) //死循環(huán)
{
for(b=0;b<8;b++) // 循環(huán)8遍
{
LED=Zuoyi[b]; //調(diào)用左流水?dāng)?shù)組
delay_ms(500); //延時500MS
if(KEY==0) //如果有按鍵按下
return; //退出循環(huán)
}
//if(KEY==0) //此兩語句可以不用
//return;
}
}
/******************************************************************************
***函數(shù)名稱: void move_r(void)
***函數(shù)功能: 右流水(P2口高位向低位流動跑馬)
***輸入: 無
***輸出: 無
******************************************************************************/
/******/
void move_r(void) //2.右流水函數(shù)
{
uchar b; //循環(huán)變量b
while(1) //無限循環(huán)
{
for(b=0;b<8;b++) // 循環(huán)8遍
{
LED=Youyi[b]; //調(diào)用右流水?dāng)?shù)組
delay_ms(500); //延時500MS
if(KEY==0) //如果有按鍵按下則退出循環(huán)
return; //退出循環(huán)
}
//if(KEY==0) //此兩語句可以不用
//return;
}
}
/******************************************************************************
***函數(shù)名稱: void flash(void)
***函數(shù)功能: 閃爍
***輸入: 無
***輸出: 無
******************************************************************************/
/******/
void flash(void) //3.閃爍
{
while(1) //無限循環(huán)
{
LED=0x00; //亮
delay_ms(500); //延時500MS
LED=0xff; //滅
delay_ms(500); //延時500MS(毫秒)
if(KEY==0) //如果有按鍵按下則退出循環(huán)
return; //退出循環(huán)
}
}
/******************************************************************************
***函數(shù)名稱: void Di_zeng1 (void)
***函數(shù)功能:.左遞增右遞減,,右遞增左遞減
***輸入: 無
***輸出: 無
******************************************************************************/
/******/
void Di_zeng1 (void) //4.左遞增右遞減,,右遞增左遞減
{
while(1)
{
uchar m; //循環(huán)變量
uchar n=0; //中間變量
uchar n1=0; //中間變量
uchar n2=0; //中間變量
uchar n3=0; //中間變量
for(m=0;m<8;m++) //左遞增,循環(huán)8位
{
n +=(0x01<<m); // 1左移m位再賦值給n
LED=~n; //n取反后點亮LED燈
delay_ms(500); //延時500毫秒
if(KEY==0) //如果按鍵按下
return; //退出循環(huán)
}
for(m=0;m<8;m++) //右遞減,循環(huán)8位
{
n1 +=(0x80>>m); // 1右移m位再賦值給n1
LED=n1; //n1取反后點亮LED燈
delay_ms(500); //延時500毫秒
if(KEY==0) //如果按鍵按下
return; //退出循環(huán)
}
for(m=0;m<8;m++) //右遞增
{
n2 +=(0x80>>m);
LED=~n2;
delay_ms(500);
if(KEY==0)
return;
}
for(m=0;m<8;m++) //左遞減
{
n3=n3+(0x01<<m);
LED=n3;
delay_ms(500);
if(KEY==0)
return;
}
//if(KEY==0) //此兩語句可以不用
//return;
}
}
/******************************************************************************
***函數(shù)名稱: void Di_zeng2 (void)
***函數(shù)功能:左遞增左遞減,,右遞增右遞減
***輸入: 無
***輸出: 無
******************************************************************************/
/******/
void Di_zeng2 (void) //5.左遞增左遞減,,右遞增右遞減
{
while(1)
{
uchar m,n=0;
uchar n1=0;
uchar n2=0;
uchar n3=0;
for(m=0;m<8;m++) //左遞增
{
n=n+(0x01<<m);
LED=~n;
delay_ms(500);
if(KEY==0)
return;
}
for(m=0;m<8;m++)//左遞減
{
n1 +=(0x01<<m);
LED=n1;
delay_ms(500);
if(KEY==0)
return;
}
for(m=0;m<8;m++) //右遞增
{
n2 +=(0x80>>m);
LED=~n2;
delay_ms(500);
if(KEY==0)
return;
}
for(m=0;m<8;m++) //右遞減
{
n3=n3+(0x80>>m);
LED=n3;
delay_ms(500);
if(KEY==0)
return;
}
//if(KEY==0) //此兩語句可以不用
//return;
}
}
/******************************************************************************
***函數(shù)名稱: uchar key_read(void)
***函數(shù)功能: 鍵盤掃描函數(shù)(按鍵狀態(tài)機(jī)方式)
***輸入: 無
***輸出: 返回值。單擊,長按,雙擊
******************************************************************************/
/******/
uchar key_read(void)
{
static uchar key_state = 0; //按鍵初始狀態(tài)
static uint key_time =0; //按鍵時間間隔計時變量
uchar key_press; //按鍵是按下還是抬起變量
uchar key_return; //按鍵函數(shù)返回
key_return=N_KEY; //清除返回按鍵值
key_press=KEY; //讀取當(dāng)前鍵值
switch(key_state)
{
case KEY_STATE_0: //按鍵初始狀態(tài)0:判斷有無按鍵按下
if(!key_press) //有按鍵按下
{
key_time=0; //一次10ms,時間間隔計數(shù)器清0
key_state=KEY_STATE_1;//然后進(jìn)入轉(zhuǎn)到按鍵確認(rèn)態(tài)1
}
break;
case KEY_STATE_1:
//按鍵確認(rèn)狀態(tài)1:軟件消抖(確定按鍵是否有效,而不是誤觸)
//按鍵有效的定義:按鍵持續(xù)按下超過設(shè)定的消抖時間
if(!key_press) //按鍵仍然按下
{
key_time++; //一次10ms,時間間隔變量加1
//消抖時間為SINGLE_KEY_TIME*10MS=30MS
if(key_time>=SINGLE_KEY_TIME) //如果大于消抖時間
{
key_state = KEY_STATE_2;//按鍵仍然處于按下狀態(tài)
}
//如果按鍵時間超過消抖時間,即判定為按下的按鍵有效。
//按鍵有效包括兩種:單擊或長按,繼續(xù)判定為那種有效按鍵
}
else //按鍵時間沒有超過,判定為誤觸,按鍵無效,返回狀態(tài)0
{
key_state = KEY_STATE_0; //返回初始狀態(tài)
}
break; //跳出
case KEY_STATE_2: //按鍵狀態(tài)2:判定按鍵有效的種類:是單擊,還是長按
if(key_press) //如果按鍵在設(shè)定的長按時間內(nèi)釋放,則判定為單擊
{
key_time++; //一次10ms,時間間隔變量加1
//按鍵彈起(高電平)后計時,計時大于雙擊30*10MS時間小于長按時間則為單擊
if((key_time >=KEY_INTERVAL)&&( key_time < LONG_KEY_TIME))
{
key_return = S_KEY; //返回有效按鍵值: 單擊
key_time=0; //時間間隔變量清0
key_state = KEY_STATE_0; //返回按鍵狀態(tài)0繼續(xù)等待按鍵
}
else //否則在此時間段為低電平則為雙擊
{
key_return = D_KEY; //返回有效按鍵值: 雙擊
key_time=0; //時間間隔變量清0
key_state = KEY_STATE_0; //返回按鍵狀態(tài)0繼續(xù)等待按鍵
}
}
else // 如果一直按下,則計算按下的時間
{
key_time++;
//如果按鍵繼續(xù)按下時間超過設(shè)定的長按時間
//(LONG_KEY_TIME*10ms=300*10ms=3000ms)則判定為長按
if(key_time >= LONG_KEY_TIME)
{
key_return = L_KEY; //返回有效鍵值:長按
key_time=0; //時間間隔變量清0
key_state = KEY_STATE_3; //去狀態(tài)3,等待按鍵釋放
}
}
break;
case KEY_STATE_3: //狀態(tài)3為長按按鍵釋放抬起
if(key_press) //如果按鍵為1,釋放狀態(tài)
{
key_state = KEY_STATE_0; //按鍵彈起,進(jìn)行下一次按鍵的判定
}
break;
//特殊情況:key_state 是其他值的情況,清0key_state ,這種情況一般出現(xiàn)
//在沒有初始key_state,第一次執(zhí)行這個函數(shù)的時候
default: key_state = KEY_STATE_0;
break;
}
return key_return; //返回按鍵值
}
/******************************************************************************
***函數(shù)名稱: void Timer0Init()
***函數(shù)功能: 定時器0初始化
***輸入: 無
***輸出: 無
******************************************************************************/
/******/
void Timer0Init() //10毫秒@12.00MHZ
{
TMOD=0x01; //設(shè)置定時器工作方式1
TH0=(65536-10000)/256;
TL0=(65536-10000)%256; //定時器0預(yù)設(shè)初值10000US=10MS
TR0=0; //關(guān)閉定時器0,當(dāng)按鍵按下才開啟定時器0,計算按下的時長
EA=1; //開總中斷
ET0=1; //允許定時器0中斷
TR0=1; //啟動定時器0
}
/******************************************************************************
***函數(shù)名稱: void Timer0_Isr() interrupt 1
***函數(shù)功能: 定時器0中斷函數(shù)
***輸入: 無
***輸出: 無
******************************************************************************/
/******/
void Timer0_Isr() interrupt 1 //定時器0中斷服務(wù)函數(shù)
{
TH0=(65536-10000)/256; //預(yù)設(shè)初值50MS
TL0=(65536-10000)%256; //預(yù)設(shè)初值50MS
time_10ms_ok=1; //10毫秒到標(biāo)志
}
/**********主程序*******/
void main(void)
{
KEY=0x01; //P1.0作為輸入口前必須輸出高電平
Timer0Init(); //調(diào)用定時器0初始化函數(shù)
while(1)
{
if(time_10ms_ok) //10MS定時時間到
{
time_10ms_ok=0; //賦值0,10MS查詢一次按鍵狀態(tài)
key_val=key_read(); //讀取按鍵的返回值
if(key_val==S_KEY) //如果是單擊
{
keySu++; //變量按鍵數(shù)加1
if(keySu==5) //如果加到5
keySu=0; //重新賦值0
}
if(key_val==L_KEY) //如果是長按
{
keySu=1; //按鍵數(shù)為1
}
if(key_val==D_KEY) //如果是雙擊
{
keySu=2; //按鍵數(shù)為2
}
switch(keySu) //5路分支
{
case 0: move_l();break; //當(dāng)按鍵數(shù)為0,執(zhí)行左流水功能
case 1: move_r();break; //當(dāng)按鍵數(shù)為1,執(zhí)行右流水功能
case 2: flash(); break; //當(dāng)按鍵數(shù)為2,執(zhí)行閃爍功能
case 3: Di_zeng1(); break; //當(dāng)按鍵數(shù)為3執(zhí)行左遞增右遞減,右遞增左遞減功能
case 4: Di_zeng2(); break;//當(dāng)按鍵數(shù)為4執(zhí)行左遞增左遞減,右遞增右遞減功能
default : break; //默認(rèn)跳出
}
}
}
}
復(fù)制代碼
Keil代碼與Proteus8.8仿真下載:
單個按鍵狀態(tài)機(jī)編程控制5種功能.7z
(75.63 KB, 下載次數(shù): 38)
2022-9-17 15:57 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1