单片机成长之路(51基础篇)- 024 基于 N76E003 的按键按键状态机
前端时间要用按键,搞了个状态机(如图):
main.c
1 #include <N76E003.H> 2 #include <SFR_Macro.h> //N76E003 SFR寄存器设置宏定义 3 #include <Function_define.h> //功能定义 4 #include "data.h" 5 #include "interrupt.h" 6 #include "button.h" 7 /*--------------------------------------------------------*/ 8 // 初始化所有 9 void Init_All(void){ 10 InitMcu(); // 初始化MCU 11 Init_button(); // 键盘初始化 12 } 13 /*******************************************************************/ 14 // 发布版本 15 void main(void){ 16 Init_All(); 17 while(1){ 18 ; 19 } 20 }
data.h
1 /*-------------------------------------------------------------------------- 2 data.h 3 --------------------------------------------------------------------------*/ 4 #ifndef __DATA_H__ 5 #define __DATA_H__ 6 7 8 /*----------------------------------------------------*/ 9 // 按键状态(状态定义) 10 #define Button_DOWN 0 // 按键按下 11 #define Button_UP 1 // 按键抬起 12 // 按键功能模式(软件模式定义) 13 #define Button_mode_NoOperation 0 // 无动作 14 #define Button_mode_ShortPress 1 // 短按 15 #define Button_mode_longPress 2 // 长按 16 #define Button_mode_evenPress 3 // 连续快按(双击) 17 // 键盘消抖时间 18 #define Button_TimeDebounce 20/2 // 单位 ms 去抖动时间 19 #define Button_TimeShort_even 100/2 // 单位 ms 短按转连续按时间 20 #define Button_TimeEvenPressinterval 5000/2 // 单位 ms 双击判断阈值 21 #define Button_TimeState_reset 60000/2 // 单位 ms 60s 无动作 退出设置 22 // 键盘状态机模式 23 #define Button_status_S0 0 // 等待按键按下 24 #define Button_status_S1 1 // 去抖验证 25 #define Button_status_S2 2 // 按下时间(计算是不是长按) 26 #define Button_status_S3 3 // 快安判断(判断是不是短按) 27 #define Button_status_S4 4 // 快安去抖 28 #define Button_status_S5 5 // 等待快安退出 29 /*----------------------------------------------------*/ 30 #define Unit_cycle 32000 // 中断处理周期 31 /*----------------------------------------------------*/ 32 struct Button_data{ 33 unsigned int Button_LiftTime; // 抬起时间 34 unsigned int Button_PressTime; // 按下时间 35 unsigned char Button_State_machine_mode:3; // 按键状态模式(状态机) 36 unsigned char Button_statusmode:2; // 0无动作 1短按 2连发 3长按 37 unsigned char Button_status:1; // 按键的状态(按键松开,界面刷新) 38 39 }; 40 /*------------------------ 系统时间 ----------------------------*/ 41 struct OS_DATA{ 42 // 系统初始化 43 unsigned char u8TH0_Tmp; // 中断高8位 44 unsigned char u8TL0_Tmp; // 中断低8位 45 // 键盘 46 struct Button_data Button0; 47 48 }; 49 50 extern struct OS_DATA DATA; 51 #endif
data.c
1 #include "data.h" 2 3 struct OS_DATA DATA; // 系统数据
interrupt.h
1 /*-------------------------------------------------------------------------- 2 interrupt.h 3 --------------------------------------------------------------------------*/ 4 5 #ifndef __INTERRUPT_H__ 6 #define __INTERRUPT_H__ 7 8 /*----------------------------------------------------*/ 9 void InitMcu(void); 10 #endif
interrupt.c
1 #include <N76E003.H> 2 #include <SFR_Macro.h> //N76E003 SFR寄存器设置宏定义 3 #include <Function_define.h> //功能定义 4 #include "data.h" 5 #include "interrupt.h" 6 #include "button.h" 7 8 /*--------------------------------------------------------*/ 9 #define T0_INIT Unit_cycle 10 #define T0_ms 500 11 /*--------------------------------------------------------*/ 12 //初始化单片机 13 void InitMcu(void){ 14 TIMER0_MODE1_ENABLE; //定时器0的模式1 15 set_T0M; //设置定时器0的时钟为系统时钟 16 //u8TH0_Tmp和u8TL0_Tmp 宏变量 中断可调用 17 //Init_OS_Date();已经初始化 18 DATA.u8TH0_Tmp = (65536-T0_INIT)/256; //计算T0高8位数据 19 DATA.u8TL0_Tmp = (65536-T0_INIT)%256; //计算T0低8位数据 20 TH0 = DATA.u8TH0_Tmp; //数据装入定时器0(计数器0)数据 21 TL0 = DATA.u8TL0_Tmp; 22 set_ET0; //开启定时器0中断 23 set_EA ; //开启总中断 24 set_TR0; //启动定时器0 25 } 26 /************************************************************************** 27 Function: TIM1_UPD_OVF_IRQHandler 28 Description: TIM1溢出中断 10ms 29 Input: no 30 Output: no 31 Return: no 32 **************************************************************************/ 33 //定时器 ms 34 void Timer0_ISR ( void ) interrupt 1 //interrupt address is 0x000B 35 { 36 //获取定时器数据 37 TH0 = DATA.u8TH0_Tmp; 38 TL0 = DATA.u8TL0_Tmp; 39 // 按键时间模块 40 All_Buttonrefresh(); 41 } 42 /******************************************************************/
button.h
1 /*--------------------------------------------------------- 2 button.h 3 按键控制 4 ---------------------------------------------------------*/ 5 #ifndef _BUTTON_H_ 6 #define _BUTTON_H_ 7 /*---------------------------------------- 数据初始化 ------------------------------------------*/ 8 #define button0_Num 5 9 sbit button0 = P1^button0_Num; // 按键 10 #define Git_button0 button0 11 /*---------------------------------------- 数据获取部分 ------------------------------------------*/ 12 13 /*---------------------------------------- 键盘初始化 ------------------------------------------*/ 14 void Init_button(void); 15 void All_Buttonrefresh(void); 16 17 #endif
button.c
1 #include <N76E003.H> 2 #include <SFR_Macro.h> //N76E003 SFR寄存器设置宏定义 3 #include <Function_define.h> //功能定义 4 #include "button.h" 5 #include "data.h" 6 7 /*---------------------------------------- 数据宏定义 ------------------------------------------*/ 8 9 /*---------------------------------------- 按键初始化 ------------------------------------------*/ 10 // 初始化按键 11 void Init_button(void){ 12 //button1 13 P1M1 |= (0x00 << button0_Num); // 设置为1 14 P1M2 &= ~(0x01 << button0_Num); // 设置为0 15 } 16 /*---------------------------------------- 功能模块 ------------------------------------------*/ 17 // 获取按键 18 void Button_Process(struct Button_data* Button,bit status){ 19 switch(Button->Button_State_machine_mode){ 20 case Button_status_S0:{ // 等待按键按下 21 if(Button_UP == status){ 22 Button->Button_status = Button_UP; // 按键状态抬起 23 Button->Button_State_machine_mode = Button_status_S0; // 无操作 24 Button->Button_statusmode = Button_mode_NoOperation; // 按键无动作 25 DATA.Button0.Button_LiftTime = DATA.Button0.Button_LiftTime + 1; // 低状态计数 26 } 27 else if(Button_DOWN == status){ // 按键按下 28 Button->Button_State_machine_mode = Button_status_S1; // 切换去抖模块 29 Button->Button_PressTime = Button_TimeDebounce; // 设置去抖时间 30 } 31 }break; 32 case Button_status_S1:{ // 去抖验证 33 if(Button->Button_PressTime){Button->Button_PressTime = Button->Button_PressTime - 1;} // 等待时间 34 else if(0 == Button->Button_PressTime){ // 去抖时间到 35 if(Button_UP == status){ 36 Button->Button_State_machine_mode = Button_status_S0; // 无操作 37 DATA.Button0.Button_LiftTime = 0; // 清空按键抬起计数 38 } 39 else if(Button_DOWN == status){ // 短按成立 40 Button->Button_status = Button_DOWN; // 按键按下 41 Button->Button_State_machine_mode = Button_status_S2; // 切换等待按键松开 42 Button->Button_PressTime = 0; // 清零按下时间 43 } 44 } 45 }break; 46 case Button_status_S2:{ // 按下时间(计算是不是长按) 47 if(Button_DOWN == status){ // 按键按下 48 // 计时 49 Button->Button_PressTime = Button->Button_PressTime + 1; // 按键计时 50 if(Button->Button_PressTime > Button_TimeEvenPressinterval){ 51 Button->Button_PressTime = Button_TimeEvenPressinterval; 52 } 53 } 54 else if (Button_UP == status){ // 按键松开 55 if(Button->Button_PressTime == Button_TimeEvenPressinterval){ 56 Button->Button_status = Button_UP; 57 Button->Button_State_machine_mode = Button_status_S0; 58 DATA.Button0.Button_LiftTime = 0; // 清空按键抬起计数 59 Button->Button_statusmode = Button_mode_longPress; // 长按 60 }else{ 61 Button->Button_State_machine_mode = Button_status_S3; // 短按 或 双击 62 } 63 Button->Button_LiftTime = 0; // 按键松开计时 64 } 65 }break; 66 case Button_status_S3:{ // 快安判断(判断是不是短按) 67 Button->Button_LiftTime = Button->Button_LiftTime + 1; //时间记录 68 if(Button->Button_PressTime > Button_TimeShort_even){ // 大于快安值 69 Button->Button_status = Button_UP; 70 Button->Button_State_machine_mode = Button_status_S0; // 短按 71 DATA.Button0.Button_LiftTime = 0; // 清空按键抬起计数 72 Button->Button_statusmode = Button_mode_ShortPress; // 短按 73 }else{ 74 if(Button_DOWN == status){ // 按键按下 75 Button->Button_State_machine_mode = Button_status_S4; // 双击去抖 76 Button->Button_PressTime = Button_TimeDebounce; // 设置去抖时间 77 } 78 } 79 }break; 80 case Button_status_S4:{ // 双击去抖 81 Button->Button_LiftTime = Button->Button_LiftTime + 1; //时间记录 82 if(Button->Button_PressTime){Button->Button_PressTime = Button->Button_PressTime - 1;} // 等待时间 83 else if(0 == Button->Button_PressTime){ // 去抖时间到 84 if(Button_UP == status){ // 去抖失败 85 Button->Button_status = Button_UP; 86 Button->Button_State_machine_mode = Button_status_S0; // 短按 87 DATA.Button0.Button_LiftTime = 0; // 清空按键抬起计数 88 Button->Button_statusmode = Button_mode_ShortPress; // 短按 89 } 90 else if(Button_DOWN == status){ // 双击成立 91 Button->Button_status = Button_DOWN; // 按键按下 92 Button->Button_State_machine_mode = Button_status_S5; // 切换等待按键松开 93 } 94 } 95 }break; 96 case Button_status_S5:{ // 等待快安退出 97 if(Button_UP == status){ 98 Button->Button_status = Button_UP; 99 Button->Button_State_machine_mode = Button_status_S0; // 双击 100 DATA.Button0.Button_LiftTime = 0; // 清空按键抬起计数 101 Button->Button_statusmode = Button_mode_evenPress; // 双击 102 } 103 }break; 104 default:{ 105 Button->Button_State_machine_mode = Button_status_S0; 106 DATA.Button0.Button_LiftTime = 0; // 清空按键抬起计数 107 }break; // 有问题转等待按键 108 } 109 // Button->Button_status = status; 110 } 111 /*---------------------------------------- 中断调用模块 ------------------------------------------*/ 112 // 批处理函数 113 void All_Buttonrefresh(void){ 114 Button_Process(&DATA.Button0,(bit)Git_button0); 115 }
工程文件:51内核按键状态机.rar