当前位置: 首页>編程日記>正文

单片机系统中实用的按键驱动(STM32、51都适用)

单片机系统中实用的按键驱动(STM32、51都适用)

目录

  • 1、自己使用的按键驱动
    • 1.1 驱动源码
    • 1.2 使用方法
  • 2、另一种按键驱动
    • 2.1 驱动源码
    • 2.2 使用方法

在我们嵌入式开发中,产品上往往少不了按键,一个好的按键驱动可以满足不同场合的客户需求,这里我分享几个实用的按键驱动,希望抛砖引玉,大家多多指出不足以及提出改进办法,或者有更好的方案希望也能分享分享。

不废话,直接上源码:

1、自己使用的按键驱动

不同平台需要做相应的修改,该驱动最初在51上运行,然后我用在了STM32F系列上,最近在STM32L系列上也在使用。

1.1 驱动源码

用最近的一个作为demo

/*
2019/5/21 按键程序移植成功,以后可以使用此按键,需要研究一下
和以前单片机项目按钮方式类似  
by  qzh
2019/8/30  
确定了第三行,第一个必须是7,才能按下到时间自动触发
by  qzh
*/
#include "mod_button.h"//GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
void io_getDigital(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin,uint8 *pu8Value)
{	*pu8Value = HAL_GPIO_ReadPin(GPIOx,GPIO_Pin);
}void time_setTimerCount(TIMER_TYPE *pu8timer,uint32 u32timeToCount)  
{// __HAL_TIM_SET_COUNTERHAL_TIM_Base_Start_IT(&htim21);// HAL_TIM_Base_Stop_IT// TIM_Cmd(TIM4, ENABLE);if(pu8timer->on == 0)pu8timer->on = 1;if(pu8timer->on == 1)//IntNum = 0;pu8timer->timeInit = Timer4_count;//pu8timer->timeInit = IntNum;pu8timer->timeOut = 0;pu8timer->timeToCount = u32timeToCount;
}RETURN_TYPE time_getTimeOut(TIMER_TYPE *pu8timer)
{uint32 Temp_Val;if(Timer4_count > pu8timer->timeInit)Temp_Val = Timer4_count - pu8timer->timeInit;elseTemp_Val = (0xFFFFFFFF-pu8timer->timeInit)+Timer4_count;if(Temp_Val >= pu8timer->timeToCount){pu8timer->timeOut = 1;pu8timer->on = 0;pu8timer->timeToCount = 0;pu8timer->timeInit = 0;}	else pu8timer->timeOut = 0;return (pu8timer->timeOut == 1)?TIME_OUT:OK;
}BTN_STATE btn_getState(BTN_STRUCT *pBtn)
{
const uint8 transition_table[8][4]={	0,	1,	0,	1,5,	2,	5,	1,7,	2,	5,	3,5,	4,	5,	4,5,	4,	5,	4,6,	1,	0,	1,6,	1,	7,	1,0,	1,	0,	1 };//register uint8 u8Input;uint8 u8Input;// Get button stateio_getDigital(pBtn->u8Pin,pBtn->GPIO_Pin ,&u8Input);u8Input = (u8Input == pBtn->u8ActiveState)?1:0;// Get timeout stateu8Input |= ((time_getTimeOut(&(pBtn->tTimer))==TIME_OUT)?2:0);// Get new statepBtn->u8State = transition_table[pBtn->u8State][u8Input]; // we want only the state, not action// Perform action switch (pBtn->u8State){case 1:time_setTimerCount(&(pBtn->tTimer), pBtn->u16TimeOutON);break;case 5:time_setTimerCount(&(pBtn->tTimer), pBtn->u16TimeOutOFF);break;}// return pBtn->u8State;//待测试return (BTN_STATE)pBtn->u8State;	
} //下面是mod_button.h#ifndef _MOD_BUTTON_H_INCLUDED
#define _MOD_BUTTON_H_INCLUDED#include "main.h"
#include "Datadef.h"
#include "tim.h"
/*Timeout ON_______|_____P             |             |		  Timeout OFFR  ___________|             |________|____^      ^  ^    ^  ^  ^   ^    ^S		0	   1  2    3  4  5	 6    7P - pressed, R - released, S - BTN_STATE
*//*
°´Å¥Ïà¹Ø  KEY1  learn  PB5  KEY2  CLEAR  PB6
*/
#define BTN_ACTIVE    0		     //when pressed, switch to GNDtypedef struct
{// Public //uint8		u8Pin;			// e.g. ADIO0//uint16		u8Pin;			// e.g. ADIO0GPIO_TypeDef * u8Pin;uint16_t    GPIO_Pin;uint8		u8ActiveState;	// button is pressed if (io_getDigital(u8Button)==bActiveState)uint16		u16TimeOutON;	// time the button has to be pressed to be recognized as presseduint16		u16TimeOutOFF;	// time the button has to be pressed to be recognized as released// PrivateTIMER_TYPE	tTimer;uint8		u8State;} BTN_STRUCT;typedef enum 
{BTN_IDLE = 0,BTN_EDGE1,BTN_TRIGGERED,BTN_PRESSED,	//< most importantBTN_PRESS_HOLD,BTN_EDGE2,BTN_RELEASE_HOLD,BTN_RELEASED	
} BTN_STATE;extern u16 Timer4_count;BTN_STATE btn_getState(BTN_STRUCT *pBtn);
void time_setTimerCount(TIMER_TYPE *pu8timer,uint32 u32timeToCount); 
void io_getDigital(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin,uint8 *pu8Value);
RETURN_TYPE time_getTimeOut(TIMER_TYPE *pu8timer);#endif //_MOD_BUTTON_H_INCLUDED

1.2 使用方法

//先定义一个按键的结构体类型,
BTN_STRUCT	K1_BUTTON_150mS ={K1_GPIO_Port,	K1_Pin,BTN_ACTIVE,			                  // Active state150,		                          // Time the button has to be in 'Active state' to be recognized as pressed100 };	
BTN_STRUCT	K1_BUTTON_2S = { K1_GPIO_Port,K1_Pin,BTN_ACTIVE,			                  // Active state2000,		                          // Time the button has to be in 'Active state' to be recognized as pressed100	 } ;//然后在主函数循环中调用不同的状态
if(btn_getState(&K1_BUTTON_150mS) == BTN_EDGE2){...}//BTN_EDGE2按住松开
if(btn_getState(&K1_BUTTON_2S) == BTN_PRESSED){...} //BTN_PRESSED为按住不松开状态
//注意使用的时候,如果长时间的按钮操作需要状态为 BTN_EDGE2 ,即长按松开 才会执行,在执行完语句最后需要包含比此次短的 BTN_EDGE2 操作:if((btn_getState(&CLEAR_BUTTON_2S)==BTN_EDGE2){...while(btn_getState(&CLEAR_BUTTON_150mS));// 防止长时间按住松开会触发短时间的松开操作
}

一般的情况下,上面代码中用到的按键事件足够应付,所以 BTN_STATE 中其他的按键状态我也没有花太多事件去测试,如果有谁能够把其他状态测试说清楚,还希望能够告知一声,

此按键程序最初原型是国外一家公司提供的SDK包里面的 Demo,然后经过自己的多次测试与修改才变成自己的最常用的驱动,当然他还可以更加的优化,希望大家多多指导。

2、另一种按键驱动

当初在做按键的时候,想着除了上面的是否有其他简单的通俗易懂的按键驱动,然后自己在网上各种寻找,反正不可能按键直接检测IO,然后防抖做一个短延时,最终这种还是逃不过得开定时器,然后还是做了一个测试可用的:

2.1 驱动源码

//开启按键IO的外部中断,为上升下降沿都能触发,这样是检测按下,弹起之间的时间差EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
/*
有一个问题,就是按下以后,长按需要下一次进入外部中断才能执行
*/
void EXTI9_5_IRQHandler(void)
{if( EXTI_GetITStatus(EXTI_Line7)!= RESET){if( KEY == 0 ){				Timer4_count = 0;readkey1 =0;}else readkey1=1;}EXTI_ClearITPendingBit(EXTI_Line7);	
}//外部中断实施按键操作
KEY_TIME Press_Key1(void)
{KEY_TIME i;if( readkey1 == 1 ){if( Timer4_count < 20 ){Timer4_count = 0;readkey1 = 0;i = NOT;}else if(( Timer4_count >= 80) && (Timer4_count < 2000 )){Timer4_count = 0;readkey1 = 0;i = Short;}else if(( Timer4_count >= 2000 ) && (Timer4_count < 5000 )){Timer4_count = 0;readkey1 = 0;i = Medium;}else if( Timer4_count >= 5000 ){Timer4_count = 0;readkey1 = 0;i = Long;}}return i;
}//在.h文件中定义枚举类型
typedef enum
{NOT   = 0,Short =2,Medium=3 ,Long =4 ,	
}KEY_TIME;
/*
好像记得当时在上面这个枚举类型时候,Short 定义为 1 是会有问题的,当时也不确定是什么问题,改成 2 测试就OK了,也没花时间研究
*/
KEY_TIME Press_Key1(void);

2.2 使用方法

if(Press_Key1() == Short){...	
}
else if(Press_Key1() == Medium);

当时这种按键也用了一会,但是好像是与点小问题,但是只使用 short 和 Medium 是可以的,具体什么问题,因为实际用不到那么多,所以也没继续研究下去,这个方法是在网上参照的例子拿过来使用的。


https://www.fengoutiyan.com/post/15381.html

相关文章:

  • 51单片机按键开关程序
  • 51单片机流水灯程序
  • 单片机驱动电路
  • 单片机按键电路
  • 单片机STM32
  • 单片机按键检测
  • 单片机程序100例
  • 51单片机可以做什么
  • 鏡像模式如何設置在哪,圖片鏡像操作
  • 什么軟件可以把圖片鏡像翻轉,C#圖片處理 解決左右鏡像相反(旋轉圖片)
  • 手機照片鏡像翻轉,C#圖像鏡像
  • 視頻鏡像翻轉軟件,python圖片鏡像翻轉_python中鏡像實現方法
  • 什么軟件可以把圖片鏡像翻轉,利用PS實現圖片的鏡像處理
  • 照片鏡像翻轉app,java實現圖片鏡像翻轉
  • 什么軟件可以把圖片鏡像翻轉,python圖片鏡像翻轉_python圖像處理之鏡像實現方法
  • matlab下載,matlab如何鏡像處理圖片,matlab實現圖像鏡像
  • 圖片鏡像翻轉,MATLAB:鏡像圖片
  • 鏡像翻轉圖片的軟件,圖像處理:實現圖片鏡像(基于python)
  • canvas可畫,JavaScript - canvas - 鏡像圖片
  • 圖片鏡像翻轉,UGUI優化:使用鏡像圖片
  • Codeforces,CodeForces 1253C
  • MySQL下載安裝,Mysql ERROR: 1253 解決方法
  • 勝利大逃亡英雄逃亡方案,HDU - 1253 勝利大逃亡 BFS
  • 大一c語言期末考試試題及答案匯總,電大計算機C語言1253,1253《C語言程序設計》電大期末精彩試題及其問題詳解
  • lu求解線性方程組,P1253 [yLOI2018] 扶蘇的問題 (線段樹)
  • c語言程序設計基礎題庫,1253號C語言程序設計試題,2016年1月試卷號1253C語言程序設計A.pdf
  • 信奧賽一本通官網,【信奧賽一本通】1253:抓住那頭牛(詳細代碼)
  • c語言程序設計1253,1253c語言程序設計a(2010年1月)
  • 勝利大逃亡英雄逃亡方案,BFS——1253 勝利大逃亡
  • 直流電壓測量模塊,IM1253B交直流電能計量模塊(艾銳達光電)
  • c語言程序設計第三版課后答案,【渝粵題庫】國家開放大學2021春1253C語言程序設計答案
  • 18轉換為二進制,1253. 將數字轉換為16進制
  • light-emitting diode,LightOJ-1253 Misere Nim
  • masterroyale魔改版,1253 Dungeon Master
  • codeformer官網中文版,codeforces.1253 B
  • c語言程序設計考研真題及答案,2020C語言程序設計1253,1253計算機科學與技術專業C語言程序設計A科目2020年09月國家開 放大學(中央廣播電視大學)
  • c語言程序設計基礎題庫,1253本科2016c語言程序設計試題,1253電大《C語言程序設計A》試題和答案200901
  • 肇事逃逸車輛無法聯系到車主怎么辦,1253尋找肇事司機