一、前言
双轴旋钮传感器(也称为二维旋钮、2D旋钮)是一种集成了旋转和推压功能的输入设备,能够在两个轴(X轴和Y轴)上进行旋转或推压操作。它通常由旋转编码器和一个按压开关(按钮)组成,能够提供丰富的交互方式,广泛应用于电子产品、工业设备、家电控制等领域。
二、简介
双轴旋钮传感器的构造与工作原理
- 旋转编码器:双轴旋钮的旋转部分通常使用增量编码器或旋转电位器。当旋钮旋转时,编码器会产生一定的电信号,表示旋转的角度或方向。旋转编码器有两个主要的电信号(A、B通道),根据这两个信号的相对变化来判断旋转的方向和步数。
- 按压开关:双轴旋钮传感器通常还集成了一个按压开关,用户可以按下旋钮来触发操作。这个按键信号是一个简单的开关操作,常用于确认选择或切换模式。
- 两个轴:旋转可以分别控制水平(X轴)和垂直(Y轴)两个方向的输入。例如,可以通过旋转控制音量(X轴)和亮度(Y轴),而按下旋钮则用来确认选择或进入设置菜单。
双轴旋钮传感器的应用
- 音量控制:在许多音响、电视、车载系统等设备中,双轴旋钮传感器被用来同时控制音量和音效模式(如平衡、低音、高音等),提供更直观的操作体验。
- 界面操作:在数字仪表盘、液晶显示器或嵌入式设备中,双轴旋钮传感器常用于菜单导航、参数调节、光标控制等。
- 工业控制:双轴旋钮可以在设备的控制面板中用于调节设备的工作状态、温度、速度等,例如在空调、机械设备和电梯的控制面板中应用。
- 游戏控制器:某些游戏设备或模拟器中,也会使用双轴旋钮传感器来提供更加精细的控制体验。
双轴旋钮传感器的使用
在实际应用中,双轴旋钮传感器通常会通过与微控制器(如Arduino、STM32等)连接来进行控制。以下是一个简单的连接和使用示例:
硬件连接
- 旋转部分:通常通过3个引脚连接到控制器:VCC(电源)、GND(地线)、和数据输出引脚(通常有两个信号引脚A和B,负责读取旋转的方向和步数)。
- 按压开关:将按压开关的两个引脚连接到一个数字I/O引脚上,通过读取按键的状态来判断是否被按下。
三、资料获取
关注微信公众号--星之援工作室 发送关键字(双轴旋钮)
代码含重要注释,开源,可自行移植
➡️➡️
四、设备使用
实现效果
连接好线 打开串口工具 即可输出获取的数据
接线
VCC - 5.0
GND - GND
X - PB12
Y - PB13
SWD - PB14
四、代码编写
main.c
实现函数调用
/*--------------------------------------------------------*
*
* 星之援网络科技工作室学习资料v1.0
* 时间:2023.7.14
* 程序介绍:模拟按键
* 实现效果:双轴旋钮
* 需求请联系:13648103287
*--------------------------------------------------------*
*/
/*--------------------------------------------------------*
VCC - 5.0
GND - GND
X - PB12
Y - PB13
SWD - PB14
*--------------------------------------------------------*
*/
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "rotary.h"
#include "usart.h"
int main(void)
{
u16 i;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
delay_init();
// 串口初始化
uart_init(115200);
// LED 端口初始化
LED_GPIO_Config();
// 双轴初始化
Key_GPIO_Config();
printf("init okn");
while(1)
{
i++;
if(i % 30 ==0){
//监测旋钮
i=0;
Check_Key_ON_OFF();
}
delay_ms(10);
}
}
rotary.c
实现端口为输入模式 ,实现按键读取
#include "rotary.h"
#include "delay.h"
#include "usart.h"
// 协议文件
/*********************************************************************************
* @Function : 初始化控制LED的IO
* @Input : None
* @Output : None
* @Return : None
* @Others : None
* @Date : 2022-07-23
**********************************************************************************/
void Key_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*开启按键端口的时钟*/
RCC_APB2PeriphClockCmd(KEY1_GPIO_CLK, ENABLE);
// 选择按键的引脚
GPIO_InitStructure.GPIO_Pin = KEY1_GPIO_PIN;
// 设置按键的引脚为浮空输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
// 使用结构体初始化按键
GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure);
// 选择按键的引脚
GPIO_InitStructure.GPIO_Pin = KEY2_GPIO_PIN;
// 设置按键的引脚为浮空输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
// 使用结构体初始化按键
GPIO_Init(KEY2_GPIO_PORT, &GPIO_InitStructure);
// 选择按键的引脚
GPIO_InitStructure.GPIO_Pin = KEY3_GPIO_PIN;
// 设置按键的引脚为浮空输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
// 使用结构体初始化按键
GPIO_Init(KEY3_GPIO_PORT, &GPIO_InitStructure);
}
/*********************************************************************************
* @Function : 检测是否有按键按下
* @Input : GPIOx:x 可以是 A,B,C,D或者 E
* : GPIO_Pin:待读取的端口位
* @Output : None
* @Return : KEY_OFF(没按下按键)、KEY_ON(按下按键)
* @Others : None
* @Date : 2022-07-23
**********************************************************************************/
u8 Key_Scan(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
/*检测是否有按键按下 */
if (GPIO_ReadInputDataBit(GPIOx, GPIO_Pin) == KEY_ON)
{
/*等待按键释放 */
while (GPIO_ReadInputDataBit(GPIOx, GPIO_Pin) == KEY_ON)
;
return KEY_ON;
}
else
return KEY_OFF;
}
/*********************************************************************************
* @Function : 按键处理函数
* @Input : Gmode:0,不支持连续按;1,支持连续按;
* @Output : None
* @Return : 0,没有任何按键按下
* 1,KEY1按下
* 2,KEY2按下
* 3,KEY3按下
* @Others : 注意此函数有响应优先级,KEY0>KEY1>KEY2>KEY3!!
* @Date : 2022-07-23
**********************************************************************************/
u8 KEY_Scan(u8 mode)
{
static u8 key_up = 1; // 按键按松开标志
if (mode)
key_up = 1; // 支持连按
if (key_up && (KEY1 == KEY_ON || KEY2 == KEY_ON || KEY3 == KEY_ON))
{
//delay_ms(10); // 去抖动
key_up = 0;
if (KEY1 == KEY_ON)
return KEY1_PRES;
else if (KEY2 == KEY_ON)
return KEY2_PRES;
else if (KEY3 == KEY_ON)
return KEY3_PRES;
}
else if (KEY1 == KEY_OFF && KEY2 == KEY_OFF && KEY3 == KEY_OFF)
key_up = 1;
return 0; // 无按键按下
}
// 检测按键是否按下
static u8 num_on = 0;
static u8 key_old = 0;
void Check_Key_ON_OFF(void)
{
u8 key;
key = KEY_Scan(1);
// 与上一次的键值比较 如果不相等,表明有键值的变化,开始计时
if (key != 0 && num_on == 0)
{
key_old = key;
num_on = 1;
}
if (key != 0 && num_on >= 1 && num_on <= Key_Scan_Time) // 25*10ms
{
num_on++; // 时间记录器
}
switch (key)
{
case KEY1_PRES:
printf("Leftn");
break;
case KEY2_PRES:
printf("Rightn");
break;
default:
break;
}
if (key == 0 && num_on > 0 && num_on < Key_Scan_Time) // 短按
{
switch (key_old)
{
case KEY1_PRES:
printf("Key1_Shortn");
break;
case KEY2_PRES:
printf("Key2_Shortn");
break;
case KEY3_PRES:
printf("Key3_Shortn");
break;
default:
break;
}
num_on = 0;
}
else if (key == 0 && num_on >= Key_Scan_Time) // 长按
{
switch (key_old)
{
case KEY1_PRES:
printf("Key1_Longn");
break;
case KEY2_PRES:
printf("Key2_Longn");
break;
case KEY3_PRES:
printf("Key3_Longn");
break;
default:
break;
}
num_on = 0;
}
}
/*********************************************END OF FILE**********************/
rotary.h
配置函数
#ifndef __KEY_H
#define __KEY_H
#include "stm32f10x.h"
// 引脚定义
#define KEY1_GPIO_CLK RCC_APB2Periph_GPIOB
#define KEY1_GPIO_PORT GPIOB
#define KEY1_GPIO_PIN GPIO_Pin_12
#define KEY2_GPIO_CLK RCC_APB2Periph_GPIOB
#define KEY2_GPIO_PORT GPIOB
#define KEY2_GPIO_PIN GPIO_Pin_13
#define KEY3_GPIO_CLK RCC_APB2Periph_GPIOB
#define KEY3_GPIO_PORT GPIOB
#define KEY3_GPIO_PIN GPIO_Pin_14
#define KEY1 GPIO_ReadInputDataBit(KEY1_GPIO_PORT, KEY1_GPIO_PIN) // 读取按键0
#define KEY2 GPIO_ReadInputDataBit(KEY2_GPIO_PORT, KEY2_GPIO_PIN) // 读取按键1
#define KEY3 GPIO_ReadInputDataBit(KEY3_GPIO_PORT, KEY3_GPIO_PIN) // 读取按键2
#define KEY1_PRES 1 // KEY1按下
#define KEY2_PRES 2 // KEY2按下
#define KEY3_PRES 3 // KEY3按下
#define Key_Scan_Time 30 // 短按时长时间判断
/** 按键按下标置宏
* 按键按下为高电平,设置 KEY_ON=1, KEY_OFF=0
* 若按键按下为低电平,把宏设置成KEY_ON=0 ,KEY_OFF=1 即可
*/
#define KEY_ON 0
#define KEY_OFF 1
/*********************************************************************************
* @Function : 初始化控制LED的IO
* @Input : None
* @Output : None
* @Return : None
* @Others : None
* @Date : 2022-07-23
**********************************************************************************/
void Key_GPIO_Config(void);
/*********************************************************************************
* @Function : 检测是否有按键按下
* @Input : GPIOx:x 可以是 A,B,C,D或者 E
* : GPIO_Pin:待读取的端口位
* @Output : None
* @Return : KEY_OFF(没按下按键)、KEY_ON(按下按键)
* @Others : None
* @Date : 2022-07-23
**********************************************************************************/
uint8_t Key_Scan(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);
/*********************************************************************************
* @Function : 按键处理函数
* @Input : Gmode:0,不支持连续按;1,支持连续按;
* @Output : None
* @Return : 0,没有任何按键按下
* 1,KEY1按下
* 2,KEY2按下
* 3,KEY3按下
* @Others : 注意此函数有响应优先级,KEY0>KEY1>KEY2>KEY3!!
* @Date : 2022-07-23
**********************************************************************************/
u8 KEY_Scan(u8 mode);
/*********************************************************************************
* @Function : 按键事件返回
* @Input : None
* : None
* @Output : None
* @Return : None
* @Others : 注意此函数有响应优先级,KEY0>KEY1>KEY2>KEY3!!
* @Date : 2022-07-23
**********************************************************************************/
void Send_Cmd(void);
void Check_Key_ON_OFF(void);
#endif /* __KEY_H */
五、参考
STM32 -- 实现按键的长按与短按检测(其他单片机可移植)https://blog.csdn.net/herui_2/article/details/128473627?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522d7f1b7e24384cae191eb4b90201ac1df%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=d7f1b7e24384cae191eb4b90201ac1df&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-128473627-null-null.nonecase&utm_term=%E6%8C%89%E9%94%AE&spm=1018.2226.3001.4450https://blog.csdn.net/herui_2/article/details/128473627?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522d7f1b7e24384cae191eb4b90201ac1df%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=d7f1b7e24384cae191eb4b90201ac1df&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-128473627-null-null.nonecase&utm_term=%E6%8C%89%E9%94%AE&spm=1018.2226.3001.4450
联系方式 微信号:13648103287