网站续费后为何还不能用,青岛网站建设在线,建个网站找,电子商务网站建设课后习题答案HAL STM32EC11编码器实现增减调节及单击、双击、长按功能 #x1f4fa;实现效果演示#xff1a;
#x1f4d8;内容提要 #x1f4dd;本文主要实现#xff0c;通过STM32 HAL库开发#xff0c;实现的EC11编码器功能#xff0c;按键结合状态机思想实现的拓展单击、双击、… HAL STM32EC11编码器实现增减调节及单击、双击、长按功能 实现效果演示
内容提要 本文主要实现通过STM32 HAL库开发实现的EC11编码器功能按键结合状态机思想实现的拓展单击、双击、长按的综合功能。单片机硬件上使用了2个外部中断引脚实现。 该功能可以很方便实现移植例如使用在OLED屏幕显示菜单上。 验证对象STM32F401EC11编码器部分的原理图
stm32cubemx配置
将EC11中键引脚配置为输入模式、开启内部上拉模式其余2个引脚配置为外部中断引脚一个配置为下降沿中断另外一个配置为上、下降沿中断这一点很关键。 ✅EC11编码器增减功能通过外部中断实现
外部中断回调处理函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{/* Prevent unused argument(s) compilation warning */UNUSED(GPIO_Pin);static uint8_t count 0;static uint8_t b_flag;GPIO_PinState a_value HAL_GPIO_ReadPin(EC11_A_GPIO_Port, EC11_A_Pin);GPIO_PinState b_value HAL_GPIO_ReadPin(EC11_B_GPIO_Port, EC11_B_Pin);if(GPIO_Pin EC11_A_Pin) {if(a_value RESET count 0) {b_flag 0;if(b_value) b_flag 1;count 1;}if(a_value SET count 1) {if(b_value RESET b_flag 1) { //开始逆时针转动test_num--;dir_flag 1;}if(b_value b_flag 0) { //开始顺时针转动test_num;dir_flag 0;}count 0;}}/* EC11中键按键中断 */// if(GPIO_Pin EC11_KEY_Pin)// {// key_click_flag 1;// }
}单击、双击、长按功能实现驱动代码
KEY.C
#include key.h//代码来源网络 侵权联系删除
/*--------------------------------------------------------------------
| short click |
| ______ ________ |
| | \ / | |
| | \_______________/ | |
| | | | | |
| |shake| long |shake| |
| |-------------------------------------------------------------------
| double click |
| ______ _____________ ____ |
| | \ / | | \ / | |
| | \_______________/ | | \_______________/ | |
| | | | | max | | | | |
| |shake| long |shake|dclick |shake| any time |shake| |
| |--------------------------------------------------------------------
| long click |
| ______ ________ |
| | \ / | |
| | \_______________________________________/ | |
| | | | | |
| |shake| long click |shake| |
| |--------------------------------------------------------------------*/#define KEY_STATUS_DOWN_CHECK 0x00
#define KEY_STATUS_DOWN_SHAKE 0x01
#define KEY_STATUS_DOWN_HANDLE 0x02
#define KEY_STATUS_LONG_CHECK 0x03
#define KEY_STATUS_SHORT_UP_SHAKE 0x04
#define KEY_STATUS_DOUBLE_CHECK 0x05
#define KEY_STATUS_SHORT_UP_HANDLE 0x06
#define KEY_STATUS_DOUBLE_DOWN_SHAKE 0x07
#define KEY_STATUS_DOUBLE_UP_CHECK 0x08
#define KEY_STATUS_DOUBLE_UP_SHAKE 0x09
#define KEY_STATUS_DOUBLE_UP_HANDLE 0x0a
#define KEY_STATUS_LONG_HANDLE 0x0b
#define KEY_STATUS_CONTINUE_CHECK 0x0c
#define KEY_STATUS_LONG_UP_SHAKE 0x0d
#define KEY_STATUS_LONG_UP_HANDLE 0x0e#define KEY_READ_DOWN 0x00 /* key is pressed */
#define KEY_READ_UP 0x01 /* Key isnt pressed */ #define KEY_BUF_SIZE 0x10 /* key value buffer size */struct
{unsigned short value[KEY_BUF_SIZE];unsigned char rd;unsigned char wr;
}key_buf;struct key_dev
{unsigned char status; /* state machine status */unsigned char num; /* number */unsigned short count_ms; /* ms counter */unsigned short long_click_ms; /* long click check min time */unsigned short shake_filter_ms; /* shake filter time */unsigned short max_dclick_ms; /* double click max interval time */unsigned short continue_send_ms; /* after long, continue send interval */unsigned char (*read_key)(void); /* key read pin status function pointer*/
};/******************************************************************************User Interface [START]
*******************************************************************************/unsigned char key0_read(void)
{if (HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) GPIO_PIN_RESET){return KEY_READ_DOWN;}else{return KEY_READ_UP;}
}struct key_dev key_dev[] {{KEY_STATUS_DOWN_CHECK,KEY0_NUM,0,1500,20,300,1000,(unsigned char (*)(void))key0_read,},/*..user add other key ..*/};/******************************************************************************User Interface [END]
*******************************************************************************/static void key_write_value(unsigned short key_val);
static void key_status_down_check(struct key_dev *key_dev);
static void key_status_down_shake(struct key_dev *key_dev);
static void key_status_down_handle(struct key_dev *key_dev);
static void key_status_long_check(struct key_dev *key_dev);
static void key_status_short_up_shake(struct key_dev *key_dev);
static void key_status_double_check(struct key_dev *key_dev);
static void key_status_short_up_handle(struct key_dev *key_dev);
static void key_status_double_down_shake(struct key_dev *key_dev);
static void key_status_double_up_check(struct key_dev *key_dev);
static void key_status_double_up_shake(struct key_dev *key_dev);
static void key_status_double_up_handle(struct key_dev *key_dev);
static void key_status_long_hanle(struct key_dev *key_dev);
static void key_status_continue_check(struct key_dev *key_dev);
static void key_status_long_up_shake(struct key_dev *key_dev);
static void key_status_long_up_handle(struct key_dev *key_dev);/**
description : write key vaule to buffer
param : key_val - key value , (KEY_EVENT | KEY_NUMBER8)
retval : None
author : huohongpeng
data : 2017-03-02
*/
static void key_write_value(unsigned short key_val)
{ key_buf.value[key_buf.wr] key_val;key_buf.wr % KEY_BUF_SIZE;/*overflow handle*/if(key_buf.wr key_buf.rd){key_buf.rd;key_buf.rd % KEY_BUF_SIZE;}
}/**
description : read key vaule from buffer
param : None
retval : key_val - key value , (KEY_EVENT | KEY_NUMBER8)
author : huohongpeng
data : 2017-03-02
*/
unsigned short key_read_value(void)
{unsigned short key_val;if(key_buf.wr key_buf.rd){key_val KEY_EVENT_NULL;}else{key_val key_buf.value[key_buf.rd];key_buf.rd % KEY_BUF_SIZE;}return key_val;
}/**
description : check key whether press down
param : key_dev - key device pointer
retval : None
author : huohongpeng
data : 2017-03-02
*/
static void key_status_down_check(struct key_dev *key_dev)
{unsigned char key_read;key_read key_dev-read_key();if(key_read KEY_READ_DOWN){key_dev-status KEY_STATUS_DOWN_SHAKE;key_dev-count_ms 0;}
}/**
description : filter shake after key pressed down
param : key_dev - key device pointer
retval : None
author : huohongpeng
data : 2017-03-02
*/
static void key_status_down_shake(struct key_dev *key_dev)
{unsigned char key_read;key_dev-count_ms;if(key_dev-count_ms key_dev-shake_filter_ms){return;}key_read key_dev-read_key();if(key_read KEY_READ_DOWN){key_dev-status KEY_STATUS_DOWN_HANDLE;}else{key_dev-status KEY_STATUS_DOWN_CHECK;}
}/**
description : key press down handle after pressed down filter shake
param : key_dev - key device pointer
retval : None
author : huohongpeng
data : 2017-03-02
*/
static void key_status_down_handle(struct key_dev *key_dev)
{unsigned short key_val key_dev-num8 | KEY_EVENT_DOWN;key_write_value(key_val);key_dev-status KEY_STATUS_LONG_CHECK;key_dev-count_ms 0;}/**
description : check key whether long click
param : key_dev - key device pointer
retval : None
author : huohongpeng
data : 2017-03-02
*/
static void key_status_long_check(struct key_dev *key_dev)
{unsigned char key_read;key_dev-count_ms;key_read key_dev-read_key();if(key_dev-count_ms key_dev-long_click_ms){if(key_read KEY_READ_UP){key_dev-status KEY_STATUS_SHORT_UP_SHAKE; }return;}key_dev-status KEY_STATUS_LONG_HANDLE; }/**
description : short cilck key up filter shake
param : key_dev - key device pointer
retval : None
author : huohongpeng
data : 2017-03-02
*/
static void key_status_short_up_shake(struct key_dev *key_dev)
{unsigned char key_read;static unsigned short old 0xffff;if(old 0xffff){old key_dev-count_ms;key_dev-count_ms 0;}key_dev-count_ms;if(key_dev-count_ms key_dev-shake_filter_ms){return;}key_read key_dev-read_key();if(key_read KEY_READ_UP){key_dev-status KEY_STATUS_DOUBLE_CHECK;key_dev-count_ms 0;}else{key_dev-status KEY_STATUS_LONG_CHECK;key_dev-count_ms old; }old 0xffff;
}/**
description : double cilck check. we consider double click event if key pressed down when after short click up and within max double click interval
param : key_dev - key device pointer
retval : None
author : huohongpeng
data : 2017-03-02
*/
static void key_status_double_check(struct key_dev *key_dev)
{unsigned char key_read;key_dev-count_ms;key_read key_dev-read_key();if(key_dev-count_ms key_dev-max_dclick_ms){if(key_read KEY_READ_DOWN){key_dev-status KEY_STATUS_DOUBLE_DOWN_SHAKE;key_dev-count_ms 0; }}else{key_dev-status KEY_STATUS_SHORT_UP_HANDLE; }}/**
description : short click key up handle
param : key_dev - key device pointer
retval : None
author : huohongpeng
data : 2017-03-02
*/
static void key_status_short_up_handle(struct key_dev *key_dev)
{unsigned short key_val;key_val key_dev-num8 | KEY_EVENT_SHORT;key_write_value(key_val);key_val key_dev-num8 | KEY_EVENT_UP_SHORT;key_write_value(key_val);key_dev-status KEY_STATUS_DOWN_CHECK;
}/**
description : double click key down filter shake
param : key_dev - key device pointer
retval : None
author : huohongpeng
data : 2017-03-02
*/
static void key_status_double_down_shake(struct key_dev *key_dev)
{unsigned char key_read;static unsigned short old 0xffff;if(old 0xffff){old key_dev-count_ms;key_dev-count_ms 0;}key_dev-count_ms;if(key_dev-count_ms key_dev-shake_filter_ms){return;}key_read key_dev-read_key();if(key_read KEY_READ_DOWN){unsigned short key_val;key_val key_dev-num8 | KEY_EVENT_DOUBLE;key_write_value(key_val);key_dev-status KEY_STATUS_DOUBLE_UP_CHECK;key_dev-count_ms 0;}else{key_dev-status KEY_STATUS_DOUBLE_CHECK;key_dev-count_ms old; }old 0xffff;
}/**
description : double click key up check
param : key_dev - key device pointer
retval : None
author : huohongpeng
data : 2017-03-02
*/
static void key_status_double_up_check(struct key_dev *key_dev)
{unsigned char key_read;key_read key_dev-read_key();if(key_read KEY_READ_UP){key_dev-status KEY_STATUS_DOUBLE_UP_SHAKE;key_dev-count_ms 0;}
}/**
description : double click key up filter shake
param : key_dev - key device pointer
retval : None
author : huohongpeng
data : 2017-03-02
*/
static void key_status_double_up_shake(struct key_dev *key_dev)
{unsigned char key_read;key_dev-count_ms;if(key_dev-count_ms key_dev-shake_filter_ms){return;}key_read key_dev-read_key();if(key_read KEY_READ_UP){key_dev-status KEY_STATUS_DOUBLE_UP_HANDLE;}else{key_dev-status KEY_STATUS_DOUBLE_UP_CHECK;}}/**
description : double click key up handle
param : key_dev - key device pointer
retval : None
author : huohongpeng
data : 2017-03-02
*/
static void key_status_double_up_handle(struct key_dev *key_dev)
{unsigned short key_val;key_val key_dev-num8 | KEY_EVENT_UP_DOUBLE;key_write_value(key_val);key_dev-status KEY_STATUS_DOWN_CHECK;
}/**
description : long click handle after long click check
param : key_dev - key device pointer
retval : None
author : huohongpeng
data : 2017-03-02
*/
static void key_status_long_hanle(struct key_dev *key_dev)
{unsigned short key_val;key_val key_dev-num8 | KEY_EVENT_LONG;key_write_value(key_val);key_dev-status KEY_STATUS_CONTINUE_CHECK;key_dev-count_ms 0;
}/**
description : continue send short click if long click time overflow
param : key_dev - key device pointer
retval : None
author : huohongpeng
data : 2017-03-02
*/
static void key_status_continue_check(struct key_dev *key_dev)
{unsigned char key_read;unsigned short key_val;key_dev-count_ms;key_read key_dev-read_key();if(key_read KEY_READ_UP){key_dev-status KEY_STATUS_LONG_UP_SHAKE;}if(key_dev-count_ms key_dev-continue_send_ms){return;}if(key_dev-continue_send_ms 0){return;}key_val key_dev-num8 | KEY_EVENT_SHORT;key_write_value(key_val);key_dev-count_ms 0;
}/**
description : long click key up filter shake
param : key_dev - key device pointer
retval : None
author : huohongpeng
data : 2017-03-02
*/
static void key_status_long_up_shake(struct key_dev *key_dev)
{unsigned char key_read;static unsigned short old 0xffff;if(old 0xffff){old key_dev-count_ms;key_dev-count_ms 0;}key_dev-count_ms;if(key_dev-count_ms key_dev-shake_filter_ms){return;}key_read key_dev-read_key();if(key_read KEY_READ_UP){key_dev-status KEY_STATUS_LONG_UP_HANDLE;}else{key_dev-status KEY_STATUS_CONTINUE_CHECK;key_dev-count_ms old; }old 0xffff;
}/**
description : long click key up filter handle
param : key_dev - key device pointer
retval : None
author : huohongpeng
data : 2017-03-02
*/
static void key_status_long_up_handle(struct key_dev *key_dev)
{unsigned short key_val;key_val key_dev-num8 | KEY_EVENT_UP_LONG;key_write_value(key_val);key_dev-status KEY_STATUS_DOWN_CHECK;
}/**
description : run key state machine once every 1ms
param : key_dev - key device pointer
retval : None
author : huohongpeng
data : 2017-03-02
*/
static void key_check_1ms(struct key_dev *key_dev)
{switch(key_dev-status){case KEY_STATUS_DOWN_CHECK :key_status_down_check(key_dev);break; case KEY_STATUS_DOWN_SHAKE : key_status_down_shake(key_dev);break; case KEY_STATUS_DOWN_HANDLE : key_status_down_handle(key_dev);break; case KEY_STATUS_LONG_CHECK : key_status_long_check(key_dev);break; case KEY_STATUS_SHORT_UP_SHAKE : key_status_short_up_shake(key_dev);break;case KEY_STATUS_DOUBLE_CHECK :key_status_double_check(key_dev);break;case KEY_STATUS_SHORT_UP_HANDLE :key_status_short_up_handle(key_dev);break;case KEY_STATUS_DOUBLE_DOWN_SHAKE : key_status_double_down_shake(key_dev);break;case KEY_STATUS_DOUBLE_UP_CHECK :key_status_double_up_check(key_dev);break;case KEY_STATUS_DOUBLE_UP_SHAKE :key_status_double_up_shake(key_dev);break;case KEY_STATUS_DOUBLE_UP_HANDLE :key_status_double_up_handle(key_dev);break; case KEY_STATUS_LONG_HANDLE :key_status_long_hanle(key_dev);break;case KEY_STATUS_CONTINUE_CHECK : key_status_continue_check(key_dev);break;case KEY_STATUS_LONG_UP_SHAKE : key_status_long_up_shake(key_dev);break;case KEY_STATUS_LONG_UP_HANDLE : key_status_long_up_handle(key_dev);break;default:key_dev-status key_dev-status;}
}/**
description : run all key state machine once every 1ms
param : key_dev - key device pointer
retval : None
author : huohongpeng
data : 2017-03-02
call :timer(1ms) interrupt handle
*/
void key_check_all_loop_1ms(void)
{unsigned char key_num, i;key_num sizeof(key_dev)/sizeof(struct key_dev);for(i 0; i key_num; i){key_check_1ms(key_dev[i]);}}
KEY.h
#ifndef __key_H
#define __key_H#ifdef __cplusplusextern C {
#endif #include main.h#define shortmaxclickms (300)
#define shortminclickms (10)
#define longclickms (800)#define KEY_EVENT_NULL 0x0000
#define KEY_EVENT_DOWN 0x0001
#define KEY_EVENT_UP_SHORT 0x0002 // 短按后松开事件
#define KEY_EVENT_UP_LONG 0x0003 // 长按后松开事件
#define KEY_EVENT_UP_DOUBLE 0x0004 // 双击后松开事件
#define KEY_EVENT_SHORT 0x0005
#define KEY_EVENT_LONG 0x0006
#define KEY_EVENT_DOUBLE 0x0007#define KEY_READ_DOWN 0x00 /* key is pressed */
#define KEY_READ_UP 0x01 /* Key isnt pressed */ /******************************************************************************User Interface [START]
*******************************************************************************/#define KEY0_NUM 0x0001#define KEY0_DOWN (KEY_EVENT_DOWN | KEY0_NUM8)
#define KEY0_UP_SHORT (KEY_EVENT_UP_SHORT | KEY0_NUM8)
#define KEY0_UP_LONG (KEY_EVENT_UP_LONG | KEY0_NUM8)
#define KEY0_UP_DOUBLE (KEY_EVENT_UP_DOUBLE | KEY0_NUM8)
#define KEY0_SHORT (KEY_EVENT_SHORT | KEY0_NUM8)
#define KEY0_LONG (KEY_EVENT_LONG | KEY0_NUM8)
#define KEY0_DOUBLE (KEY_EVENT_DOUBLE | KEY0_NUM8)/******************************************************************************User Interface [END]
*******************************************************************************/void key_check_all_loop_1ms(void);
unsigned short key_read_value(void);#ifdef __cplusplus
}
#endif#endif
main函数中按键处理内容
#include stdio.h
#include key.h
int32_t test_num 0;//支持正负数值增减
uint8_t dir_flag 2; /* 方向标志 0: 顺时 1: 逆时 2: 未动*/
uint8_t key_click_flag 0;//EC11 中键unsigned short key_value;int main(void)
{/* USER CODE BEGIN 1 */uint32_t tick2, tick3;/* 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_USART1_UART_Init();/* USER CODE BEGIN 2 */uint32_t Main_Fosc HAL_RCC_GetSysClockFreq();printf(Main_Fosc:%dHz \r\n, Main_Fosc);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while(1) {/* USER CODE END WHILE *//* USER CODE BEGIN 3 */if(dir_flag ! 2) {switch(dir_flag) {case 0:printf(顺时针转动\r\n);break;case 1:printf(逆时针转动\r\n);break;}dir_flag 2;printf(num: %d\n, test_num);}if(HAL_GetTick() - tick2 1) {tick2 HAL_GetTick();key_check_all_loop_1ms();}/* Key按键按下查询 */if(HAL_GetTick() - tick3 10) {tick3 HAL_GetTick();key_value key_read_value();if(key_value KEY0_UP_SHORT) { //单击事件HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);// 实现单击KEYtest_num;printf(Press 单击,num:%d\r\n, test_num);} else if(key_value KEY0_UP_DOUBLE) { //双击事件HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);test_num 2;printf(\r\nDouble Press 双击,num:%d\r\n, test_num);} else if(key_value KEY0_LONG) { //长按事件printf(\r\nLong Press 长按\r\n);// 实现长按KEYtest_num 0;//清除编码器计数值printf(按键计数清零,num:%d\r\n, test_num);}}}/* USER CODE END 3 */
}工程源码
链接https://pan.baidu.com/s/1zTMkY8iEGSCu_gSavR_I3A?pwd4m2q
提取码4m2q