单片机成长之路(51基础篇)- 024 基于 N76E003 的按键按键状态机
前端时间要用按键,搞了个状态机(如图):

main.c
#include <N76E003.H>
#include <SFR_Macro.h> //N76E003 SFR寄存器设置宏定义
#include <Function_define.h> //功能定义
#include "data.h"
#include "interrupt.h"
#include "button.h"
/*--------------------------------------------------------*/
// 初始化所有
void Init_All(void){
InitMcu(); // 初始化MCU
Init_button(); // 键盘初始化
}
/*******************************************************************/
// 发布版本
void main(void){
Init_All();
while(){
;
}
}
data.h
/*--------------------------------------------------------------------------
data.h
--------------------------------------------------------------------------*/
#ifndef __DATA_H__
#define __DATA_H__ /*----------------------------------------------------*/
// 按键状态(状态定义)
#define Button_DOWN 0 // 按键按下
#define Button_UP 1 // 按键抬起
// 按键功能模式(软件模式定义)
#define Button_mode_NoOperation 0 // 无动作
#define Button_mode_ShortPress 1 // 短按
#define Button_mode_longPress 2 // 长按
#define Button_mode_evenPress 3 // 连续快按(双击)
// 键盘消抖时间
#define Button_TimeDebounce 20/2 // 单位 ms 去抖动时间
#define Button_TimeShort_even 100/2 // 单位 ms 短按转连续按时间
#define Button_TimeEvenPressinterval 5000/2 // 单位 ms 双击判断阈值
#define Button_TimeState_reset 60000/2 // 单位 ms 60s 无动作 退出设置
// 键盘状态机模式
#define Button_status_S0 0 // 等待按键按下
#define Button_status_S1 1 // 去抖验证
#define Button_status_S2 2 // 按下时间(计算是不是长按)
#define Button_status_S3 3 // 快安判断(判断是不是短按)
#define Button_status_S4 4 // 快安去抖
#define Button_status_S5 5 // 等待快安退出
/*----------------------------------------------------*/
#define Unit_cycle 32000 // 中断处理周期
/*----------------------------------------------------*/
struct Button_data{
unsigned int Button_LiftTime; // 抬起时间
unsigned int Button_PressTime; // 按下时间
unsigned char Button_State_machine_mode:; // 按键状态模式(状态机)
unsigned char Button_statusmode:; // 0无动作 1短按 2连发 3长按
unsigned char Button_status:; // 按键的状态(按键松开,界面刷新) };
/*------------------------ 系统时间 ----------------------------*/
struct OS_DATA{
// 系统初始化
unsigned char u8TH0_Tmp; // 中断高8位
unsigned char u8TL0_Tmp; // 中断低8位
// 键盘
struct Button_data Button0; }; extern struct OS_DATA DATA;
#endif
data.c
#include "data.h" struct OS_DATA DATA; // 系统数据
interrupt.h
/*--------------------------------------------------------------------------
interrupt.h
--------------------------------------------------------------------------*/ #ifndef __INTERRUPT_H__
#define __INTERRUPT_H__ /*----------------------------------------------------*/
void InitMcu(void);
#endif
interrupt.c
#include <N76E003.H>
#include <SFR_Macro.h> //N76E003 SFR寄存器设置宏定义
#include <Function_define.h> //功能定义
#include "data.h"
#include "interrupt.h"
#include "button.h" /*--------------------------------------------------------*/
#define T0_INIT Unit_cycle
#define T0_ms 500
/*--------------------------------------------------------*/
//初始化单片机
void InitMcu(void){
TIMER0_MODE1_ENABLE; //定时器0的模式1
set_T0M; //设置定时器0的时钟为系统时钟
//u8TH0_Tmp和u8TL0_Tmp 宏变量 中断可调用
//Init_OS_Date();已经初始化
DATA.u8TH0_Tmp = (-T0_INIT)/; //计算T0高8位数据
DATA.u8TL0_Tmp = (-T0_INIT)%; //计算T0低8位数据
TH0 = DATA.u8TH0_Tmp; //数据装入定时器0(计数器0)数据
TL0 = DATA.u8TL0_Tmp;
set_ET0; //开启定时器0中断
set_EA ; //开启总中断
set_TR0; //启动定时器0
}
/**************************************************************************
Function: TIM1_UPD_OVF_IRQHandler
Description: TIM1溢出中断 10ms
Input: no
Output: no
Return: no
**************************************************************************/
//定时器 ms
void Timer0_ISR ( void ) interrupt //interrupt address is 0x000B
{
//获取定时器数据
TH0 = DATA.u8TH0_Tmp;
TL0 = DATA.u8TL0_Tmp;
// 按键时间模块
All_Buttonrefresh();
}
/******************************************************************/
button.h
/*---------------------------------------------------------
button.h
按键控制
---------------------------------------------------------*/
#ifndef _BUTTON_H_
#define _BUTTON_H_
/*---------------------------------------- 数据初始化 ------------------------------------------*/
#define button0_Num 5
sbit button0 = P1^button0_Num; // 按键
#define Git_button0 button0
/*---------------------------------------- 数据获取部分 ------------------------------------------*/ /*---------------------------------------- 键盘初始化 ------------------------------------------*/
void Init_button(void);
void All_Buttonrefresh(void); #endif
button.c
#include <N76E003.H>
#include <SFR_Macro.h> //N76E003 SFR寄存器设置宏定义
#include <Function_define.h> //功能定义
#include "button.h"
#include "data.h" /*---------------------------------------- 数据宏定义 ------------------------------------------*/ /*---------------------------------------- 按键初始化 ------------------------------------------*/
// 初始化按键
void Init_button(void){
//button1
P1M1 |= (0x00 << button0_Num); // 设置为1
P1M2 &= ~(0x01 << button0_Num); // 设置为0
}
/*---------------------------------------- 功能模块 ------------------------------------------*/
// 获取按键
void Button_Process(struct Button_data* Button,bit status){
switch(Button->Button_State_machine_mode){
case Button_status_S0:{ // 等待按键按下
if(Button_UP == status){
Button->Button_status = Button_UP; // 按键状态抬起
Button->Button_State_machine_mode = Button_status_S0; // 无操作
Button->Button_statusmode = Button_mode_NoOperation; // 按键无动作
DATA.Button0.Button_LiftTime = DATA.Button0.Button_LiftTime + ; // 低状态计数
}
else if(Button_DOWN == status){ // 按键按下
Button->Button_State_machine_mode = Button_status_S1; // 切换去抖模块
Button->Button_PressTime = Button_TimeDebounce; // 设置去抖时间
}
}break;
case Button_status_S1:{ // 去抖验证
if(Button->Button_PressTime){Button->Button_PressTime = Button->Button_PressTime - ;} // 等待时间
else if( == Button->Button_PressTime){ // 去抖时间到
if(Button_UP == status){
Button->Button_State_machine_mode = Button_status_S0; // 无操作
DATA.Button0.Button_LiftTime = ; // 清空按键抬起计数
}
else if(Button_DOWN == status){ // 短按成立
Button->Button_status = Button_DOWN; // 按键按下
Button->Button_State_machine_mode = Button_status_S2; // 切换等待按键松开
Button->Button_PressTime = ; // 清零按下时间
}
}
}break;
case Button_status_S2:{ // 按下时间(计算是不是长按)
if(Button_DOWN == status){ // 按键按下
// 计时
Button->Button_PressTime = Button->Button_PressTime + ; // 按键计时
if(Button->Button_PressTime > Button_TimeEvenPressinterval){
Button->Button_PressTime = Button_TimeEvenPressinterval;
}
}
else if (Button_UP == status){ // 按键松开
if(Button->Button_PressTime == Button_TimeEvenPressinterval){
Button->Button_status = Button_UP;
Button->Button_State_machine_mode = Button_status_S0;
DATA.Button0.Button_LiftTime = ; // 清空按键抬起计数
Button->Button_statusmode = Button_mode_longPress; // 长按
}else{
Button->Button_State_machine_mode = Button_status_S3; // 短按 或 双击
}
Button->Button_LiftTime = ; // 按键松开计时
}
}break;
case Button_status_S3:{ // 快安判断(判断是不是短按)
Button->Button_LiftTime = Button->Button_LiftTime + ; //时间记录
if(Button->Button_PressTime > Button_TimeShort_even){ // 大于快安值
Button->Button_status = Button_UP;
Button->Button_State_machine_mode = Button_status_S0; // 短按
DATA.Button0.Button_LiftTime = ; // 清空按键抬起计数
Button->Button_statusmode = Button_mode_ShortPress; // 短按
}else{
if(Button_DOWN == status){ // 按键按下
Button->Button_State_machine_mode = Button_status_S4; // 双击去抖
Button->Button_PressTime = Button_TimeDebounce; // 设置去抖时间
}
}
}break;
case Button_status_S4:{ // 双击去抖
Button->Button_LiftTime = Button->Button_LiftTime + ; //时间记录
if(Button->Button_PressTime){Button->Button_PressTime = Button->Button_PressTime - ;} // 等待时间
else if( == Button->Button_PressTime){ // 去抖时间到
if(Button_UP == status){ // 去抖失败
Button->Button_status = Button_UP;
Button->Button_State_machine_mode = Button_status_S0; // 短按
DATA.Button0.Button_LiftTime = ; // 清空按键抬起计数
Button->Button_statusmode = Button_mode_ShortPress; // 短按
}
else if(Button_DOWN == status){ // 双击成立
Button->Button_status = Button_DOWN; // 按键按下
Button->Button_State_machine_mode = Button_status_S5; // 切换等待按键松开
}
}
}break;
case Button_status_S5:{ // 等待快安退出
if(Button_UP == status){
Button->Button_status = Button_UP;
Button->Button_State_machine_mode = Button_status_S0; // 双击
DATA.Button0.Button_LiftTime = ; // 清空按键抬起计数
Button->Button_statusmode = Button_mode_evenPress; // 双击
}
}break;
default:{
Button->Button_State_machine_mode = Button_status_S0;
DATA.Button0.Button_LiftTime = ; // 清空按键抬起计数
}break; // 有问题转等待按键
}
// Button->Button_status = status;
}
/*---------------------------------------- 中断调用模块 ------------------------------------------*/
// 批处理函数
void All_Buttonrefresh(void){
Button_Process(&DATA.Button0,(bit)Git_button0);
}
工程文件:51内核按键状态机.rar
单片机成长之路(51基础篇)- 024 基于 N76E003 的按键按键状态机的更多相关文章
- 单片机成长之路(51基础篇) - 022 N76e003 APROM模拟EEPROM驱动
N76e003单片机内部没有EEPROM,但是可以使用 APROM模拟EEPROM功能,代码如下: eeprom.h #ifndef _EEPROM_H_ #define _EEPROM_H_ //E ...
- 单片机成长之路(51基础篇) - 023 N76e003 系统时钟切换到外部时钟
N76e003切换到外部时钟的资料很少(因为N76e003的片子是不支持无源晶振的,有源晶振的成本又很高,所以网上很少有对N76e003的介绍).有图有真相: 代码如下: main.c #includ ...
- 单片机成长之路(51基础篇) - 015 关于sdcc的多文件编译范例二
本文是续 单片机成长之路(51基础篇) - 009 关于sdcc的多文件编译范例(一)编写的. 在实际的工作中,单片机的头文件和功能函数不可能同全部放在同一个文件夹下面,我们把单片机成长之路(51基础 ...
- 单片机成长之路(51基础篇) - 009 关于sdcc的多文件编译范例(一)
本文是续 单片机成长之路(51基础篇) - 006 在Linux下搭建51单片机的开发烧写环境编写的. 本范例主要由(main.c ,delay.h,delay.c,makefile)4个文件组成,s ...
- (转)Python成长之路【第九篇】:Python基础之面向对象
一.三大编程范式 正本清源一:有人说,函数式编程就是用函数编程-->错误1 编程范式即编程的方法论,标识一种编程风格 大家学习了基本的Python语法后,大家就可以写Python代码了,然后每个 ...
- Sass进阶之路,之一(基础篇)
Sass 学习Sass之前,应该要知道css预处理器这个东西,css预处理器是什么呢? Css预处理器定义了一种新的语言将Css作为目标生成文件,然后开发者就只要使用这种语言进行编码工作了.预处理器通 ...
- python成长之路第三篇(1)_初识函数
目录: 函数 为什么要使用函数 什么是函数 函数的返回值 文档化函数 函数传参数 文件操作(二) 1.文件操作的步骤 2.文件的内置方法 函数: 一.为什么要使用函数 在日常写代码中,我们会发现有很多 ...
- C++自学成长之路(第一篇)
今天开始我将开启C++自学成长之路,今天是第一天,在以前就一直在网上查找关于c++的资料,想买一本好一点的,权威一点的资料书,通过努力查找,我选择了c++ primer,在网上这本书的好评如潮.更多的 ...
- 单片机成长之路(51基础篇) - 008 C51 的标示符和关键字
标准 C 语言定义了 32 个关键字,如下表(ANSI C的32个关键字): C51在此基础上针对单片机功能进行了扩展,详情见下表(C51编译器扩充关键字): C 51的数据类型 51单片机使用的C语 ...
随机推荐
- 201871010126 王亚涛 《面向对象程序设计(Java)》第十周实验总结
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...
- UiPath:Delay延迟执行,解决UiPath自动输入值不完整问题
学习过程中出现点击按钮后,由于网页弹出框显示速度慢,造成输入值遗漏或者根本就没有输入问题. 查阅了一下,目前解决方法是在点击按钮后加一段延迟时间,等待他显示完整在输入值.如图 时间格式以秒为单位 00 ...
- day32_8_14 并发编程三 线程的GIL
一.GIL 什么是GIL? GIL是一个全局排他锁,简单来说就是为了防止多线程并行操作的锁.这里有官方解释: In CPython, the global interpreter lock, or G ...
- linux中以.d结尾的目录
一般为了保持对原有配置方式的兼容,而增加的.d结尾目录. 如: /etc/X11/xorg.conf 这原本是个文件,现在也有了一个/etc/X11/xorg.conf.d这样的目录,显卡驱动的相关设 ...
- LG1983 「NOIP2013」车站分级 拓扑排序
问题描述 LG1983 题解 考虑建立有向边\((a,b)\),代表\(a\)比\(b\)低级. 于是枚举每一辆车次经过的车站\(x \in [l,r]\),如果不是车辆停靠的车站,则从\(x\)向每 ...
- javascript专题系列--js乱序
乱序的意思想必没有不知道:就是将数组打乱. 听到乱序一般都会想到js的随机函数Math.random(); var values = [1, 2, 3, 4, 5]; values.sort(func ...
- postgres判断字符串是否为时间,数字
时间判断函数定义: -- FUNCTION: public.isdate(character varying) -- DROP FUNCTION public.isdate(character var ...
- [知识点]最近公共祖先LCA
UPDATE(20180822):重写部分代码. 1.前言 最近公共祖先(LCA),作为树上问题,应用非常广泛,而求解的方式也非常多,复杂度各有不同,这里对几种常用的方法汇一下总. 2.基本概念和暴力 ...
- Python正则表达式学习与运用
一.什么是正则表达式 正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个 ...
- it's over | 2019 CSP-S 第二轮认证(超长预警)
也许应该从Day -1(2019年11月14日周四)开始说起? 卑微的我们在学长的怂恿下终于...停课了(哇我们太菜了,只停一天半的课有个卵用 早读后我带头去办公室请假,飞哥很大方地答应了,同时免了我 ...