HAL STM32+EC11编码器实现增减调节及单击、双击、长按功能
📺实现效果演示:
📘内容提要
📝本文主要实现,通过STM32 HAL库开发,实现的EC11编码器功能,按键结合状态机思想实现的拓展单击、双击、长按的综合功能。单片机硬件上使用了2个外部中断引脚实现。 🗝该功能可以很方便实现移植,例如使用在OLED屏幕显示菜单上。
🔖验证对象:STM32F401 🍁EC11编码器部分的原理图:
🛠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