前端时间要用按键,搞了个状态机(如图):

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(){
  18. ;
  19. }
  20. }

data.h

  1. /*--------------------------------------------------------------------------
  2. data.h
  3. --------------------------------------------------------------------------*/
  4. #ifndef __DATA_H__
  5. #define __DATA_H__
  6.  
  7. /*----------------------------------------------------*/
  8. // 按键状态(状态定义)
  9. #define Button_DOWN 0 // 按键按下
  10. #define Button_UP 1 // 按键抬起
  11. // 按键功能模式(软件模式定义)
  12. #define Button_mode_NoOperation 0 // 无动作
  13. #define Button_mode_ShortPress 1 // 短按
  14. #define Button_mode_longPress 2 // 长按
  15. #define Button_mode_evenPress 3 // 连续快按(双击)
  16. // 键盘消抖时间
  17. #define Button_TimeDebounce 20/2 // 单位 ms 去抖动时间
  18. #define Button_TimeShort_even 100/2 // 单位 ms 短按转连续按时间
  19. #define Button_TimeEvenPressinterval 5000/2 // 单位 ms 双击判断阈值
  20. #define Button_TimeState_reset 60000/2 // 单位 ms 60s 无动作 退出设置
  21. // 键盘状态机模式
  22. #define Button_status_S0 0 // 等待按键按下
  23. #define Button_status_S1 1 // 去抖验证
  24. #define Button_status_S2 2 // 按下时间(计算是不是长按)
  25. #define Button_status_S3 3 // 快安判断(判断是不是短按)
  26. #define Button_status_S4 4 // 快安去抖
  27. #define Button_status_S5 5 // 等待快安退出
  28. /*----------------------------------------------------*/
  29. #define Unit_cycle 32000 // 中断处理周期
  30. /*----------------------------------------------------*/
  31. struct Button_data{
  32. unsigned int Button_LiftTime; // 抬起时间
  33. unsigned int Button_PressTime; // 按下时间
  34. unsigned char Button_State_machine_mode:; // 按键状态模式(状态机)
  35. unsigned char Button_statusmode:; // 0无动作 1短按 2连发 3长按
  36. unsigned char Button_status:; // 按键的状态(按键松开,界面刷新)
  37.  
  38. };
  39. /*------------------------ 系统时间 ----------------------------*/
  40. struct OS_DATA{
  41. // 系统初始化
  42. unsigned char u8TH0_Tmp; // 中断高8位
  43. unsigned char u8TL0_Tmp; // 中断低8位
  44. // 键盘
  45. struct Button_data Button0;
  46.  
  47. };
  48.  
  49. extern struct OS_DATA DATA;
  50. #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 = (-T0_INIT)/; //计算T0高8位数据
  19. DATA.u8TL0_Tmp = (-T0_INIT)%; //计算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 //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 + ; // 低状态计数
  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 - ;} // 等待时间
  34. else if( == Button->Button_PressTime){ // 去抖时间到
  35. if(Button_UP == status){
  36. Button->Button_State_machine_mode = Button_status_S0; // 无操作
  37. DATA.Button0.Button_LiftTime = ; // 清空按键抬起计数
  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 = ; // 清零按下时间
  43. }
  44. }
  45. }break;
  46. case Button_status_S2:{ // 按下时间(计算是不是长按)
  47. if(Button_DOWN == status){ // 按键按下
  48. // 计时
  49. Button->Button_PressTime = Button->Button_PressTime + ; // 按键计时
  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 = ; // 清空按键抬起计数
  59. Button->Button_statusmode = Button_mode_longPress; // 长按
  60. }else{
  61. Button->Button_State_machine_mode = Button_status_S3; // 短按 或 双击
  62. }
  63. Button->Button_LiftTime = ; // 按键松开计时
  64. }
  65. }break;
  66. case Button_status_S3:{ // 快安判断(判断是不是短按)
  67. Button->Button_LiftTime = Button->Button_LiftTime + ; //时间记录
  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 = ; // 清空按键抬起计数
  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 + ; //时间记录
  82. if(Button->Button_PressTime){Button->Button_PressTime = Button->Button_PressTime - ;} // 等待时间
  83. else if( == 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 = ; // 清空按键抬起计数
  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 = ; // 清空按键抬起计数
  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 = ; // 清空按键抬起计数
  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

单片机成长之路(51基础篇)- 024 基于 N76E003 的按键按键状态机的更多相关文章

  1. 单片机成长之路(51基础篇) - 022 N76e003 APROM模拟EEPROM驱动

    N76e003单片机内部没有EEPROM,但是可以使用 APROM模拟EEPROM功能,代码如下: eeprom.h #ifndef _EEPROM_H_ #define _EEPROM_H_ //E ...

  2. 单片机成长之路(51基础篇) - 023 N76e003 系统时钟切换到外部时钟

    N76e003切换到外部时钟的资料很少(因为N76e003的片子是不支持无源晶振的,有源晶振的成本又很高,所以网上很少有对N76e003的介绍).有图有真相: 代码如下: main.c #includ ...

  3. 单片机成长之路(51基础篇) - 015 关于sdcc的多文件编译范例二

    本文是续 单片机成长之路(51基础篇) - 009 关于sdcc的多文件编译范例(一)编写的. 在实际的工作中,单片机的头文件和功能函数不可能同全部放在同一个文件夹下面,我们把单片机成长之路(51基础 ...

  4. 单片机成长之路(51基础篇) - 009 关于sdcc的多文件编译范例(一)

    本文是续 单片机成长之路(51基础篇) - 006 在Linux下搭建51单片机的开发烧写环境编写的. 本范例主要由(main.c ,delay.h,delay.c,makefile)4个文件组成,s ...

  5. (转)Python成长之路【第九篇】:Python基础之面向对象

    一.三大编程范式 正本清源一:有人说,函数式编程就是用函数编程-->错误1 编程范式即编程的方法论,标识一种编程风格 大家学习了基本的Python语法后,大家就可以写Python代码了,然后每个 ...

  6. Sass进阶之路,之一(基础篇)

    Sass 学习Sass之前,应该要知道css预处理器这个东西,css预处理器是什么呢? Css预处理器定义了一种新的语言将Css作为目标生成文件,然后开发者就只要使用这种语言进行编码工作了.预处理器通 ...

  7. python成长之路第三篇(1)_初识函数

    目录: 函数 为什么要使用函数 什么是函数 函数的返回值 文档化函数 函数传参数 文件操作(二) 1.文件操作的步骤 2.文件的内置方法 函数: 一.为什么要使用函数 在日常写代码中,我们会发现有很多 ...

  8. C++自学成长之路(第一篇)

    今天开始我将开启C++自学成长之路,今天是第一天,在以前就一直在网上查找关于c++的资料,想买一本好一点的,权威一点的资料书,通过努力查找,我选择了c++ primer,在网上这本书的好评如潮.更多的 ...

  9. 单片机成长之路(51基础篇) - 008 C51 的标示符和关键字

    标准 C 语言定义了 32 个关键字,如下表(ANSI C的32个关键字): C51在此基础上针对单片机功能进行了扩展,详情见下表(C51编译器扩充关键字): C 51的数据类型 51单片机使用的C语 ...

随机推荐

  1. maven 学习---Maven 插件

    什么是 Maven 插件? Maven 实际上是一个依赖插件执行的框架,每个任务实际上是由插件完成.Maven 插件通常被用来: 创建 jar 文件 创建 war 文件 编译代码文件 代码单元测试 创 ...

  2. PHP json中文

    json_encode 和 json_decode 只支持utf-8编码的字符串,GBK的字符串要用json就得转换成utf-8字符串 看效果 <?php header("Conten ...

  3. Windows 10 Java开发环境配置

    一.JDK下载 安装java开发环境,第一步就是下载jdk安装包.打开浏览器进入oracle官网下载.这里注意jdk和jre的区别,jdk(java develop environment)是java ...

  4. 章节十四、9-Actions类鼠标悬停、滚动条、拖拽页面上的元素

    一.鼠标悬停 1.在web网站中,有一些页面元素只需要我们将鼠标指针放在上面就会出现被隐藏的下拉框或者其它元素,在自动化的过程中我们使用Actions类对鼠标进行悬停操作. 2.案例演示 packag ...

  5. JMETER 用户变量作用域

    在编写JMETER 脚本时,我们会使用到变量,变量的作用域是线程. 我们通过下面的脚本验证一下变量的返回是线程. 1. 我们先定义一个amount的流程变量. 2.线程组使用三个线程 3.在线程组中添 ...

  6. Python从零开始——迭代器与生成器

    一:迭代器 二:生成器

  7. Ubuntu 18.04上安装 phpMyAdmin

    我们将安装 phpMyAdmin 在 Ubuntu18.04 上配合 Apache 一起工作. 在安装 phpMyAdmin 之前需要已经安装了LAMP栈并提供了web页面. 如果没有安装可以参照 U ...

  8. 201871010101-陈来弟《面向对象程序设计(Java)》第八周学习总结

    实验七 接口的定义与使用 第一部分:理论知识 一.接口.lambda和内部类:  Comparator与comparable接口: 1.comparable接口的方法是compareTo,只有一个参数 ...

  9. zz:一个框架看懂优化算法之异同 SGD/AdaGrad/Adam

    首先定义:待优化参数:  ,目标函数: ,初始学习率 . 而后,开始进行迭代优化.在每个epoch  : 计算目标函数关于当前参数的梯度:  根据历史梯度计算一阶动量和二阶动量:, 计算当前时刻的下降 ...

  10. Getting Started with TensorFlow.js

    使用TensorFlow.js,您不仅可以在浏览器中运行深度学习模型进行推理,你还能够训练它们.在这个简单的样例中,将展示一个相当于“Hello World”的示例. 1.引入TensorFlow.j ...