• 方案介绍
    • 一、前言
    • 二、简介
    • 三、资料获取
    • 四、设备使用
    • 四、代码编写
    • 五、参考
  • 附件下载
  • 相关推荐
申请入驻 产业图谱

【嵌入式外设】 双轴旋钮传感器(与按键同理)驱动代码

02/26 08:39
1017
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

联系方式.docx

共1个文件

一、前言

双轴旋钮传感器(也称为二维旋钮2D旋钮)是一种集成了旋转和推压功能的输入设备,能够在两个轴(X轴和Y轴)上进行旋转或推压操作。它通常由旋转编码器和一个按压开关(按钮)组成,能够提供丰富的交互方式,广泛应用于电子产品、工业设备、家电控制等领域。

二、简介

双轴旋钮传感器的构造与工作原理

  1. 旋转编码器:双轴旋钮的旋转部分通常使用增量编码器或旋转电位器。当旋钮旋转时,编码器会产生一定的电信号,表示旋转的角度或方向。旋转编码器有两个主要的电信号(A、B通道),根据这两个信号的相对变化来判断旋转的方向和步数。
  2. 按压开关:双轴旋钮传感器通常还集成了一个按压开关,用户可以按下旋钮来触发操作。这个按键信号是一个简单的开关操作,常用于确认选择或切换模式。
  3. 两个轴:旋转可以分别控制水平(X轴)和垂直(Y轴)两个方向的输入。例如,可以通过旋转控制音量(X轴)和亮度(Y轴),而按下旋钮则用来确认选择或进入设置菜单。

双轴旋钮传感器的应用

  1. 音量控制:在许多音响、电视、车载系统等设备中,双轴旋钮传感器被用来同时控制音量和音效模式(如平衡、低音、高音等),提供更直观的操作体验。
  2. 界面操作:在数字仪表盘、液晶显示器嵌入式设备中,双轴旋钮传感器常用于菜单导航、参数调节、光标控制等。
  3. 工业控制:双轴旋钮可以在设备的控制面板中用于调节设备的工作状态、温度、速度等,例如在空调、机械设备和电梯的控制面板中应用。
  4. 游戏控制器:某些游戏设备或模拟器中,也会使用双轴旋钮传感器来提供更加精细的控制体验。

双轴旋钮传感器的使用

在实际应用中,双轴旋钮传感器通常会通过与微控制器(如Arduino、STM32等)连接来进行控制。以下是一个简单的连接和使用示例:

硬件连接

  1. 旋转部分:通常通过3个引脚连接到控制器:VCC(电源)、GND(地线)、和数据输出引脚(通常有两个信号引脚A和B,负责读取旋转的方向和步数)。
  2. 按压开关:将按压开关的两个引脚连接到一个数字I/O引脚上,通过读取按键的状态来判断是否被按下。

三、资料获取

关注微信公众号--星之援工作室 发送关键字(双轴旋钮)

代码含重要注释,开源,可自行移植

➡️➡️452c0cf75b1d4e4895194df8a5022c34.png

四、设备使用

实现效果

连接好线 打开串口工具 即可输出获取的数据

接线

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

  • 联系方式.docx
    下载
点赞
收藏
评论
分享
加入交流群
举报

相关推荐

方案定制

去合作
方案开发定制化,2000+方案商即时响应!

方案定制,程序设计方案、单片机程序设计与讲解、APP定制开发。本公众号致力于向读者传递关于程序设计和开发的相关知识,并分享一些关于软件开发的最佳实践。如果您有什么问题或建议,请随时联系我们。我们将竭诚为您服务