当前位置:首页 > 公众号精选 > 嵌入式云IOT技术圈
[导读]在嵌入式系统或单片机程序开发过程中,经常会遇到各种按键的需求,比如按键短按、按键长按、按键双击,这些功能虽然不难,但想要完全写好这些功能并不简单。网上已经有大神实现了这样的组件,该组件的特性如下: 使用时系统不阻塞 低耦合性 同一个按键可实现







在嵌入式系统或单片机程序开发过程中,经常会遇到各种按键的需求,比如按键短按、按键长按、按键双击,这些功能虽然不难,但想要完全写好这些功能并不简单。网上已经有大神实现了这样的组件,该组件的特性如下:

  • 使用时系统不阻塞
  • 低耦合性
  • 同一个按键可实现单击、双击、长按
  • 可根据按键线序更改,比如高电平触发或低电平触发

按键检测组件函数接口如下:

一、初始化按键

/**
* @name Init_Key_Struct
* @brief 初始化按键
* @param Update_Key_CallBack:更新按键状态
* @param Debug_CallBack:打印按键调试信息
* @retval 0:成功;
* 1:Update_Key_CallBack == NULL;
*/
char Init_Key_Struct(void (*Update_Key_CallBack)(void), void (*Debug_CallBack)(unsigned char *debug_mess));
  • 参数Update_Key_CallBack用于更新按键状态,即按下或者释放,是一个函数指针,该值一定不能为NULL。
  • 参数Debug_CallBack用于打印按键组件的异常信息,也是一个函数指针,如果不需要时候可以将该参数写NULL。

二、注册按键

/**
* @name Reg_Key
* @brief 添加注册按键(注:如果按键已经注册过,那么再次注册会覆盖之前注册过的相同的按键)
* @param key_s:按键状态
* @param count:按键计数
* @param Trig_Mode_E:按键触发模式
* @param Key_Mode_E:按键模式
* @param Key_Click_CallBack:按键触发回调
* @retval 0:成功;
* 1:Key_Click_CallBack == NULL;
* 2:Key.Reg_Key_Num > Key_Num_Max;
*/
char Reg_Key(unsigned char *key_s, const unsigned short count,
Trig_Mode_TypeDef Trig_Mode_E, Key_Mode_TypeDef Key_Mode_E, void (*Key_Click_CallBack)(void));
  • 参数key_s为按键状态,即是按键按下或者释放,可以与"一"中的Update_Key_CallBack回调函数关联起来。
  • 参数count为按键计数,意思是当按键按下多少次后出发对应的回调,这个回调就是参数Key_Click_CallBack
  • 参数Trig_Mode_E,指的是按键的出发方式,该组件用一个枚举来进行描述:
/**
* @brief 按键触发模式状态枚举
*/
typedef enum
{
N_Trig = 0, /*!< 0 空 */
L_Trig , /*!< 1 低电平触发 */
H_Trig, /*!< 2 高电平触发 */
}Trig_Mode_TypeDef;
  • 参数Key_Mode_E为按键模式,有单击,双击,长按三种,该组件也是用一个枚举来进行描述:
/**
* @brief 按键模式状态枚举
*/
typedef enum
{
N_Click = 0, /*!< 0 空 */
S_Click , /*!< 1 单击 */
D_Click, /*!< 2 双击 */
L_Press, /*!< 3 长按 */
}Key_Mode_TypeDef;
  • 参数Key_Click_CallBack,也就是相应模式下出发的回调函数了,这是一个函数指针。

三、按键检测

/**
* @name Key_Detect
* @brief 按键检测
* @param 无
* @retval 0:成功;
* 1:Key.Update_Key_CallBack == NULL;
*/
char Key_Detect(void);

该接口是用来检测按键状态的,使用该函数时,需要周期性的进行调用,当函数返回0时,表示函数一直在运行,如果返回1,则表示更新按键电平状态的回调函数Update_Key_CallBack为空。

四、打印组件版本信息

/**
* @name Get_Version_Mess
* @brief 打印Key_Detect组件版本信息
* @param 无
* @retval 返Key_Detect组件版本信息
*/
char *Get_Version_Mess(void)

其中一、二、三是就是我们使用这个按键组件的核心函数,我们来看看这个组件的使用方法,以下是我使用野火霸道F103开发板实现的例程,代码只贴出一部分核心的:

五、部分例程实现与讲解

//按键单击时发出时的事件值
#define KEY_SIGNAL 0
//按键长按时发出时的事件值
#define KEY_LONG 1
//按键没有发出时的事件值
#define KEY_NULL -1

/*按键状态==>按下or释放*/
uint8_t Key_Status = 0 ;
/*按键事件==>对应单击、双击、长按*/
int Key_Event = KEY_NULL;

/*按键发生单击时回调*/
void key_S_CallBack(void)
{
Key_Event = KEY_SIGNAL ;
}

/*按键发生长按时回调*/
void key_L_CallBack(void)
{
Key_Event = KEY_LONG ;
}

/*获取按键状态*/
void Get_Key_Status(void)
{
Key_Status = HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin);
}

/*打印调试信息*/
void Print_Debug_mess(unsigned char *debug_Mess)
{
printf("%s\n",debug_Mess);
}

/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t Register_Status = 1 ;
int Count = 0 ;
/* USER CODE END 1 */


/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
printf("按键组件demo初始化\n");
//HAL_GPIO_WritePin(GPIOB, LED_G_Pin|LED_B_Pin|LED_R_Pin, GPIO_PIN_SET);
/*显示绿灯*/
HAL_GPIO_WritePin(GPIOB, LED_R_Pin, GPIO_PIN_RESET);
/*初始化结构体*/
Register_Status = Init_Key_Struct(Get_Key_Status, Print_Debug_mess);
if(Register_Status)
{
printf("初始化按键失败\n");
return -1 ;
}
/*注册事件发生回调*/
Reg_Key(&Key_Status, 10, H_Trig, S_Click, key_S_CallBack);//单击
Reg_Key(&Key_Status, 200, H_Trig, L_Press, key_L_CallBack);//长按
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
Key_Detect();
if(KEY_SIGNAL == Key_Event)
{
HAL_GPIO_WritePin(GPIOB, LED_G_Pin|LED_B_Pin|LED_R_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, LED_G_Pin, GPIO_PIN_RESET);
}
if(KEY_LONG == Key_Event)
{
HAL_GPIO_WritePin(GPIOB, LED_G_Pin|LED_B_Pin|LED_R_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, LED_B_Pin, GPIO_PIN_RESET);
}
HAL_Delay(5);
}
/* USER CODE END 3 */
}

该例程的实现非常简单,即当没有发生任何按键的时候,显示红灯,当发生单击时,显示绿灯,当发生长按时,显示蓝灯。

六、例程及组件文档分享

链接:https://pan.baidu.com/s/1jV2dCE_wGGZSPBIUhMfUgQ
提取码:89zf

链接:https://pan.baidu.com/s/1Wg2jBfihFn-SKh0JmytIZA
提取码:o61v

往期精彩分享

让C语言的调试更加高大上

分享一个好用的C语言.ini文件的解析库

分享一个非常有用且简单C语言测试框架

分享一个自己量产项目上的集成测试软件MTTEST


免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

常州2023年9月13日 /美通社/ -- 9月11日-14日,全球光伏行业最具影响力之一的美国国际太阳能展览RE+2023在拉斯维加斯金沙会展中心隆重举行。展会上,天合光能(展台号#2138)携新一代210+N型至尊家...

关键字: 新能源 组件 电站 数字化

将建设一座放射治疗设备零部件制造工厂 新工厂预计2024年中期正式投产 投资约2500万欧元展现对鲁多尔施塔特工厂的坚定承诺 埃尔朗根2023年9月7日 /美通社/ -- 近日,西门子医疗宣布扩建其位...

关键字: 西门子 零部件 组件 计算机

56万千瓦光伏"蓝海"闪耀高原荒漠 常州2023年9月6日 /美通社/ -- 近日,天合光能开始向大唐海南州兴海县大基地 56 万千瓦光伏电站供货。项目采用了天合光能至尊 N 型 700W+ 系列超...

关键字: 组件 测试 大唐 高功率

常州2023年9月1日 /美通社/ -- 8月29日晚间,天合光能披露2023年半年度报告(下简称"报告"),今年上半年,天合光能组件出货27GW;截至同期,天合光能组件累计出货超150GW,其中21...

关键字: 组件 智慧能源 5G 电站

常州2023年8月31日 /美通社/ -- 8月18日,天合光能至尊N型700W+组件量产暨2024年组件升级发布会在青海一体化基地隆重举行。基于新一代N型i-TOPCon先进技术叠加210产品技术的加速全面应用,至尊N...

关键字: 光伏 组件 TOP PC

连接器是连接电气线路的组件之一,主要是在器件与组件、组件与机柜、系统与子系统之间起电连接和信号传递的作用,并且保持系统与系统之间不发生信号失真和能量损失,其品质好坏关系到系统设备整体运作的可靠性,属于主机厂商的重要配套产...

关键字: 连接器 器件 组件

常州2023年8月10日 /美通社/ -- 8月1日,天合光能青海基地年产5GW 210+N型i-TOPCon高效太阳能电池成功下线!该项目的投产,意味着天合光能青海基地从拉晶、切片到电池、组件的全面贯通,加速形成N型一...

关键字: 电池 组件 TOP PC

加利福尼亚州圣安娜, May 23, 2023 (GLOBE NEWSWIRE) -- TTM Technologies, Inc.(纳斯达克股票代码:TTMI)(下称:迅达)是一家全球领先的技术解决方案制造商,包括...

关键字: TECHNOLOGIES 电子电路 组件 COM

(全球TMT2023年7月19日讯)环旭电子正与多家车用SoC方案原厂(TP)携手合作,凭借多年深耕SiP/SoM模块将车用运算模块(Automotive Compute SiP/SoM Module)进一步微缩,同时...

关键字: 电子 组件 SoC SIP

智能折迭吉他、中国设计博物馆包豪斯展AR导览系统夺大奖 台北2022年12月8日 /美通社/ -- 亚洲设计界指标性奖项"金点设计奖",12月2日在台北举办颁奖典礼,揭晓"年度最佳设计奖&...

关键字: 呼吸机 工业设计 模块化 组件
关闭
关闭