HAL STM32+EC11编码器实现增减调节及单击、双击、长按功能
📺实现效果演示:
📘内容提要
📝本文主要实现,通过STM32 HAL库开发,实现的EC11编码器功能,按键结合状态机思想实现的拓展单击、双击、长按的综合功能。 🗝该功能可以很方便实现移植,例如使用在OLED屏幕显示菜单上。
🔖验证对象:STM32F401 🍁编码器部分的原理图:
🛠stm32cubemx配置
🔧将EC11中键引脚配置为输入模式、开启内部上拉模式,其余2个引脚配置为外部中断引脚(一个配置为下降沿中断,另外一个配置为上、下降沿中断 ,这一点很关键!)。
✅EC11编码器增减功能,通过外部中断实现
void HAL_GPIO_EXTI_Callback ( uint16_t GPIO_Pin)
{
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 ;
}
}
}
📓单击、双击、长按功能实现驱动代码
# include "key.h"
# 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
# define KEY_READ_UP 0x01
# define KEY_BUF_SIZE 0x10
struct
{
unsigned short value[ KEY_BUF_SIZE] ;
unsigned char rd;
unsigned char wr;
} key_buf;
struct key_dev
{
unsigned char status;
unsigned char num;
unsigned short count_ms;
unsigned short long_click_ms;
unsigned short shake_filter_ms;
unsigned short max_dclick_ms;
unsigned short continue_send_ms;
unsigned char ( * read_key) ( void ) ;
} ;
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,
} ,
} ;
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) ;
static void key_write_value ( unsigned short key_val)
{
key_buf. value[ key_buf. wr++ ] = key_val;
key_buf. wr %= KEY_BUF_SIZE;
if ( key_buf. wr == key_buf. rd)
{
key_buf. rd++ ;
key_buf. rd %= KEY_BUF_SIZE;
}
}
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;
}
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 ;
}
}
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;
}
}
static void key_status_down_handle ( struct key_dev * key_dev)
{
unsigned short key_val = key_dev-> num<< 8 | KEY_EVENT_DOWN;
key_write_value ( key_val) ;
key_dev-> status = KEY_STATUS_LONG_CHECK;
key_dev-> count_ms = 0 ;
}
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;
}
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 ;
}
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;
}
}
static void key_status_short_up_handle ( struct key_dev * key_dev)
{
unsigned short key_val;
key_val= key_dev-> num<< 8 | KEY_EVENT_SHORT;
key_write_value ( key_val) ;
key_val= key_dev-> num<< 8 | KEY_EVENT_UP_SHORT;
key_write_value ( key_val) ;
key_dev-> status = KEY_STATUS_DOWN_CHECK;
}
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-> num<< 8 | 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 ;
}
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 ;
}
}
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;
}
}
static void key_status_double_up_handle ( struct key_dev * key_dev)
{
unsigned short key_val;
key_val= key_dev-> num<< 8 | KEY_EVENT_UP_DOUBLE;
key_write_value ( key_val) ;
key_dev-> status = KEY_STATUS_DOWN_CHECK;
}
static void key_status_long_hanle ( struct key_dev * key_dev)
{
unsigned short key_val;
key_val= key_dev-> num<< 8 | KEY_EVENT_LONG;
key_write_value ( key_val) ;
key_dev-> status = KEY_STATUS_CONTINUE_CHECK;
key_dev-> count_ms = 0 ;
}
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-> num<< 8 | KEY_EVENT_SHORT;
key_write_value ( key_val) ;
key_dev-> count_ms = 0 ;
}
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 ;
}
static void key_status_long_up_handle ( struct key_dev * key_dev)
{
unsigned short key_val;
key_val= key_dev-> num<< 8 | KEY_EVENT_UP_LONG;
key_write_value ( key_val) ;
key_dev-> status = KEY_STATUS_DOWN_CHECK;
}
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;
}
}
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] ) ;
}
}
# ifndef __key_H
# define __key_H
# ifdef __cplusplus
extern "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
# define KEY_READ_UP 0x01
# define KEY0_NUM 0x0001
# define KEY0_DOWN ( KEY_EVENT_DOWN | KEY0_NUM<< 8 )
# define KEY0_UP_SHORT ( KEY_EVENT_UP_SHORT | KEY0_NUM<< 8 )
# define KEY0_UP_LONG ( KEY_EVENT_UP_LONG | KEY0_NUM<< 8 )
# define KEY0_UP_DOUBLE ( KEY_EVENT_UP_DOUBLE | KEY0_NUM<< 8 )
# define KEY0_SHORT ( KEY_EVENT_SHORT | KEY0_NUM<< 8 )
# define KEY0_LONG ( KEY_EVENT_LONG | KEY0_NUM<< 8 )
# define KEY0_DOUBLE ( KEY_EVENT_DOUBLE | KEY0_NUM<< 8 )
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 ;
uint8_t key_click_flag = 0 ;
unsigned short key_value;
int main ( void )
{
uint32_t tick2, tick3;
HAL_Init ( ) ;
SystemClock_Config ( ) ;
MX_GPIO_Init ( ) ;
MX_USART1_UART_Init ( ) ;
uint32_t Main_Fosc = HAL_RCC_GetSysClockFreq ( ) ;
printf ( "Main_Fosc:%dHz \r\n" , Main_Fosc) ;
while ( 1 ) {
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 ( ) ;
}
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) ;
test_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" ) ;
test_num = 0 ;
printf ( "按键计数清零,num:%d\r\n" , test_num) ;
}
}
}
}
📚工程源码
链接:https:
提取码:4 m2q