一、前言
雙軸旋鈕傳感器(也稱為二維旋鈕、2D旋鈕)是一種集成了旋轉(zhuǎn)和推壓功能的輸入設(shè)備,能夠在兩個軸(X軸和Y軸)上進行旋轉(zhuǎn)或推壓操作。它通常由旋轉(zhuǎn)編碼器和一個按壓開關(guān)(按鈕)組成,能夠提供豐富的交互方式,廣泛應(yīng)用于電子產(chǎn)品、工業(yè)設(shè)備、家電控制等領(lǐng)域。
二、簡介
雙軸旋鈕傳感器的構(gòu)造與工作原理
- 旋轉(zhuǎn)編碼器:雙軸旋鈕的旋轉(zhuǎn)部分通常使用增量編碼器或旋轉(zhuǎn)電位器。當(dāng)旋鈕旋轉(zhuǎn)時,編碼器會產(chǎn)生一定的電信號,表示旋轉(zhuǎn)的角度或方向。旋轉(zhuǎn)編碼器有兩個主要的電信號(A、B通道),根據(jù)這兩個信號的相對變化來判斷旋轉(zhuǎn)的方向和步數(shù)。
- 按壓開關(guān):雙軸旋鈕傳感器通常還集成了一個按壓開關(guān),用戶可以按下旋鈕來觸發(fā)操作。這個按鍵信號是一個簡單的開關(guān)操作,常用于確認選擇或切換模式。
- 兩個軸:旋轉(zhuǎn)可以分別控制水平(X軸)和垂直(Y軸)兩個方向的輸入。例如,可以通過旋轉(zhuǎn)控制音量(X軸)和亮度(Y軸),而按下旋鈕則用來確認選擇或進入設(shè)置菜單。
雙軸旋鈕傳感器的應(yīng)用
- 音量控制:在許多音響、電視、車載系統(tǒng)等設(shè)備中,雙軸旋鈕傳感器被用來同時控制音量和音效模式(如平衡、低音、高音等),提供更直觀的操作體驗。
- 界面操作:在數(shù)字儀表盤、液晶顯示器或嵌入式設(shè)備中,雙軸旋鈕傳感器常用于菜單導(dǎo)航、參數(shù)調(diào)節(jié)、光標(biāo)控制等。
- 工業(yè)控制:雙軸旋鈕可以在設(shè)備的控制面板中用于調(diào)節(jié)設(shè)備的工作狀態(tài)、溫度、速度等,例如在空調(diào)、機械設(shè)備和電梯的控制面板中應(yīng)用。
- 游戲控制器:某些游戲設(shè)備或模擬器中,也會使用雙軸旋鈕傳感器來提供更加精細的控制體驗。
雙軸旋鈕傳感器的使用
在實際應(yīng)用中,雙軸旋鈕傳感器通常會通過與微控制器(如Arduino、STM32等)連接來進行控制。以下是一個簡單的連接和使用示例:
硬件連接
- 旋轉(zhuǎn)部分:通常通過3個引腳連接到控制器:VCC(電源)、GND(地線)、和數(shù)據(jù)輸出引腳(通常有兩個信號引腳A和B,負責(zé)讀取旋轉(zhuǎn)的方向和步數(shù))。
- 按壓開關(guān):將按壓開關(guān)的兩個引腳連接到一個數(shù)字I/O引腳上,通過讀取按鍵的狀態(tài)來判斷是否被按下。
三、資料獲取
關(guān)注微信公眾號--星之援工作室 發(fā)送關(guān)鍵字(雙軸旋鈕)
代碼含重要注釋,開源,可自行移植
????
四、設(shè)備使用
實現(xiàn)效果
連接好線 打開串口工具 即可輸出獲取的數(shù)據(jù)
?
接線
VCC - 5.0
GND - GND
X???? - PB12
Y???? - PB13
SWD - PB14
?
四、代碼編寫
main.c
?實現(xiàn)函數(shù)調(diào)用
/*--------------------------------------------------------*
*
* 星之援網(wǎng)絡(luò)科技工作室學(xué)習(xí)資料v1.0
* 時間:2023.7.14
* 程序介紹:模擬按鍵
* 實現(xiàn)效果:雙軸旋鈕
* 需求請聯(lián)系: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); //設(shè)置NVIC中斷分組2:2位搶占優(yōu)先級,2位響應(yīng)優(yōu)先級
delay_init();
// 串口初始化
uart_init(115200);
// LED 端口初始化
LED_GPIO_Config();
// 雙軸初始化
Key_GPIO_Config();
printf("init okn");
while(1)
{
i++;
if(i % 30 ==0){
//監(jiān)測旋鈕
i=0;
Check_Key_ON_OFF();
}
delay_ms(10);
}
}
rotary.c
實現(xiàn)端口為輸入模式 ,實現(xiàn)按鍵讀取
#include "rotary.h"
#include "delay.h"
#include "usart.h"
// 協(xié)議文件
/*********************************************************************************
* @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;
// 設(shè)置按鍵的引腳為浮空輸入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
// 使用結(jié)構(gòu)體初始化按鍵
GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure);
// 選擇按鍵的引腳
GPIO_InitStructure.GPIO_Pin = KEY2_GPIO_PIN;
// 設(shè)置按鍵的引腳為浮空輸入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
// 使用結(jié)構(gòu)體初始化按鍵
GPIO_Init(KEY2_GPIO_PORT, &GPIO_InitStructure);
// 選擇按鍵的引腳
GPIO_InitStructure.GPIO_Pin = KEY3_GPIO_PIN;
// 設(shè)置按鍵的引腳為浮空輸入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
// 使用結(jié)構(gòu)體初始化按鍵
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 : 按鍵處理函數(shù)
* @Input : Gmode:0,不支持連續(xù)按;1,支持連續(xù)按;
* @Output : None
* @Return : 0,沒有任何按鍵按下
* 1,KEY1按下
* 2,KEY2按下
* 3,KEY3按下
* @Others : 注意此函數(shù)有響應(yīng)優(yōu)先級,KEY0>KEY1>KEY2>KEY3!!
* @Date : 2022-07-23
**********************************************************************************/
u8 KEY_Scan(u8 mode)
{
static u8 key_up = 1; // 按鍵按松開標(biāo)志
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
配置函數(shù)
#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 // 短按時長時間判斷
/** 按鍵按下標(biāo)置宏
* 按鍵按下為高電平,設(shè)置 KEY_ON=1, KEY_OFF=0
* 若按鍵按下為低電平,把宏設(shè)置成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 : 按鍵處理函數(shù)
* @Input : Gmode:0,不支持連續(xù)按;1,支持連續(xù)按;
* @Output : None
* @Return : 0,沒有任何按鍵按下
* 1,KEY1按下
* 2,KEY2按下
* 3,KEY3按下
* @Others : 注意此函數(shù)有響應(yīng)優(yōu)先級,KEY0>KEY1>KEY2>KEY3!!
* @Date : 2022-07-23
**********************************************************************************/
u8 KEY_Scan(u8 mode);
/*********************************************************************************
* @Function : 按鍵事件返回
* @Input : None
* : None
* @Output : None
* @Return : None
* @Others : 注意此函數(shù)有響應(yīng)優(yōu)先級,KEY0>KEY1>KEY2>KEY3!!
* @Date : 2022-07-23
**********************************************************************************/
void Send_Cmd(void);
void Check_Key_ON_OFF(void);
#endif /* __KEY_H */
五、參考
STM32 -- 實現(xiàn)按鍵的長按與短按檢測(其他單片機可移植)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
聯(lián)系方式 微信號:13648103287