当前位置: 首页 > news >正文

外设模块学习(18)——5针双轴按键摇杆模块(STM32)

引言

       本次,我们介绍一个相对有意思的模块——双轴按键摇杆模块,也叫PS2摇杆啊,这玩意像游戏手柄上的那种摇杆一样,只不过可能没那么精密吧,当然仍然能够在一些场景下广泛使用,最常见的肯定是遥控了。本次介绍的这个模块外观如下图所示。

       那么,下面我们就来介绍一下双轴按键摇杆模块的相关原理以及基于STM32的使用方法。


1、摇杆模块介绍

       PS2双轴按键游戏摇杆模块采用PS游戏手柄上金属按键摇杆电位器、模块特设二路模拟输出和一路数字输出接口、输出值分别对应(×、Y双轴偏移量、其类型为模拟量按键表示用户是否在z轴上按下、其类型为数字开关量

       也就是说,该摇杆模块是通过上下和左右摆动改动电位器阻值实现X、Y轴偏移量输出的,而按键其实结构上就是在底部多加了个轻触开关而已。

       双轴按键摇杆模块应用相对广泛。一般在航模、电玩、遥控车、云台等设备上应用为遥控器摇杆,同时很多带有屏幕的设备也经常使用摇杆作为菜单选择的输入控制


2、相关参数

名称PS2游戏金属摇杆
工作电压DC 5V
十字摇杆双向10K电位器
电路板尺寸26mm*34mm

3、硬件构成

       PS2双轴按键游戏摇杆模块主要由十字摇杆轻触按键以及机械结构组成。其中机械结构主要是用于固定十字摇杆和按键的,便于按下十字摇杆时能够按下底部侧方的轻触按键,实现既能四面滑动也能充当按键的效果。

3.1 十字摇杆

       十字摇杆外观如下图所示,也就是摇杆帽下方的组件:

       十字摇杆其实是一个双向的10K电阻器(也称电位器),随着摇杆的滑动,其方向会随之变化,此时抽头的阻值也会跟着变化。

       前面提到该模块工作电压为5V,即一般我们对其进行5V供电。在原始状态(也就是默认不手动滑动摇杆的情况)下,通过X、Y偏移量对应输出端口输出的电压为2.5V左右;当随着摇杆的特定方向滑动,读出的电压值会随着增加或减小,最大能达到5V,最小能达到0V

       单片机就能够用端口连接模块相应的引脚,然后读取对应引脚输出的模拟量,经过单片机内部的ADC外设进行一个转换,实时获取到转换得到的对应原始值以及电压值。

3.2 轻触按键

       该模块上带有一个轻触开关,如下图所示:

       这个轻触开关就是作为实现摇杆模块能够实现按键功能的核心部件,当然他还借助了一定的机械结构,否则摇杆按下的时候没法按下这个按键。

       当摇杆被按下时,这个轻触开关也随之被按下而闭合,此时模块上对应按键的输出引脚就会输出一个低电平信号,也就是输出0,反之没有被按下时就会输出高电平,也就是输出1。


4、引脚定义及功能

       该模块共有5个引脚,分别是GND、5V、VRX、VRY、SW引脚,详细描述如下表所示。

引脚名称功能描述
GND电源接地
+5V供电电压,接直流5V
VRXx方向模拟量输出
VRYy方向模拟量输出
SW按键输出,(z方向上的按键)

5、参考代码

       接下来,根据其原理基于STM32给出参考测试代码,该代码基于寄存器方式进行编写,当然由于传感器原理比较简单,因此逻辑应该容易理解。

        值得注意的是,本次给出的是最基础最直接的功能测试代码,也就是测试其本身的输出效果是否符合预期。而在实际使用该模块进行一定功能时还需要自行完善优化和增加相关处理逻辑。

5.1 joystick.h

#ifndef __JOYSTICK_H
#define __JOYSTICK_H#include <stm32f10x.h>
#include "Systick.h"/*** 双轴摇杆PS2引脚连接(未使用按键)* * VCC --> 5V* GND --> GND* VRX --> PA0* VRY --> PA1* */void Joystick_Init(void);
void Joystick_ConvXY(void);
uint32_t Joystick_GetX(void);
uint32_t Joystick_GetY(void);
uint8_t Joystick_GetSW(void);#endif /* __joystick_H__ */
/*** (C) COPYRIGHT 2025 END OF FILE ***/

5.2 joystick.c

       该代码读取电压值时使用的是ADC单通道单次采集,通过选择不同的ADC通道采集XY的各自的电压值。不过在实际复杂工程中不建议这样编写,最好是借助DMA,进行连续多通道的高速ADC采样,不经过CPU之手,提高采样效率,减少等待ADC处理对CPU造成的阻塞。

/** @Descripttion: 双轴摇杆驱动文件(.c)* @Author: JaRyon* @version: * @Date: 2025-11-07 18:44:51*/
#include "joystick.h"/*** @brief      双轴摇杆初始化* @param      void 无* @return     void* @example    Joystick_Init();* @attention*/
void Joystick_Init(void)
{// 1. 开启时钟RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;// 分频:6分频 12MHzRCC->CFGR |= RCC_CFGR_ADCPRE_1;RCC->CFGR &= ~RCC_CFGR_ADCPRE_0;// 2. GPIO工作模式// 2.1 PA2 上拉输入 mode-00 cnf-10GPIOA->CRL &= ~GPIO_CRL_MODE2;GPIOA->CRL |= GPIO_CRL_CNF2_1;GPIOA->CRL &= ~GPIO_CRL_CNF2_0;GPIOA->BSRR |= GPIO_BSRR_BS2;// 2.2 PA0 1 模拟输入 MODE-00 CNF-00GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0);GPIOA->CRL &= ~(GPIO_CRL_MODE1 | GPIO_CRL_CNF1);// 3. ADC配置// 3.1 工作模式-禁止扫描ADC1->CR1 &= ~ADC_CR1_SCAN;// 3.2 转换模式:禁止连续转换(单通道读取一次)ADC1->CR2 &= ~ADC_CR2_CONT;// 3.3 数据对齐-右对齐ADC1->CR2 &= ~ADC_CR2_ALIGN;// 3.4 通道采样时间:7.5周期ADC1->SMPR2 |= ADC_SMPR2_SMP0_0;ADC1->SMPR2 |= ADC_SMPR2_SMP1_0;ADC1->SMPR2 &= ~(ADC_SMPR2_SMP0_2 | ADC_SMPR2_SMP0_1);ADC1->SMPR2 &= ~(ADC_SMPR2_SMP1_2 | ADC_SMPR2_SMP1_1);// 3.5 规则通道组序列配置// 3.5.1 序列长度:2个通道(L = 1 => 表示2个)ADC1->SQR1 &= ~ADC_SQR1_L;ADC1->SQR1 |= (1 << 20);// 3.5.2 序列转换位置:sq1-通道0 sq2-通道1ADC1->SQR3 &= ~(ADC_SQR3_SQ1 | ADC_SQR3_SQ2);ADC1->SQR3 |= (0 << 0);ADC1->SQR3 |= (1 << 5);// 3.6 选择规则通道转换模式:软件触发-EXTSEL-111ADC1->CR2 |= ADC_CR2_EXTTRIG;ADC1->CR2 |= ADC_CR2_EXTSEL;
}/*** @brief      开始转换摇杆变化XY数值* @param      void 无* @return     void* @example    Joystick_ConvXY();* @attention  */
void Joystick_ConvXY(void)
{// 1. 上电唤醒ADC1->CR2 |= ADC_CR2_ADON;// 2. AD校准ADC1->CR2 |= ADC_CR2_CAL;// 轮询判断校准是否完毕,完成则清除while (ADC1->CR2 & ADC_CR2_CAL){}
}/*** @brief      读取ADC通道对应的转换数值* @param      uint8_t ch* @return     uint32_t* @example    Joystick_ReadChannel(0);* @attention  */
static uint32_t Joystick_ReadChannel(uint8_t ch)
{ADC1->SQR3 = ch;                    // 选择通道ADC1->CR2 |= ADC_CR2_SWSTART;       // 软件触发while ((ADC1->SR & ADC_SR_EOC) == 0);  // 等待完成return ADC1->DR;
}/*** @brief      获取转换得到的摇杆X值* @param      void* @return     uint32_t* @example    res_x = Joystick_GetX();* @attention  */
uint32_t Joystick_GetX(void)
{return Joystick_ReadChannel(0);
}/*** @brief      获取转换得到的摇杆Y值* @param      void* @return     uint32_t* @example    res_y = Joystick_GetY();* @attention  */
uint32_t Joystick_GetY(void)
{return Joystick_ReadChannel(1);    
}/*** @brief      获取双轴摇杆按键状态* @param      void* @return     uint8_t 返回的按键状态* @example    SW_State = Joystick_GetSW();* @attention  */
uint8_t Joystick_GetSW(void)
{static uint8_t stableState = 1; // 稳定时的状态,默认未按下static uint32_t lastChangeTime = 0;  // 上一次状态变化所处时间static uint8_t lastState = 1; // 上一次按键的状态// 获取当前按键状态uint32_t currentState = (GPIOA->IDR & GPIO_IDR_IDR2) ? 1 : 0;// 按键状态出现变化if (currentState != lastState){// 时间更新,准备消抖处理lastChangeTime = Systick_GetTick();// 更新按键状态lastState = currentState;}// 消抖处理if (Systick_GetTick() - lastChangeTime >= 10000){// 此时认为抖动消除,将当前所处状态作为稳定按键状态stableState = currentState;}return stableState;
}

5.3 main.c

       主程序的测试代码逻辑也比较简单,即使用OLED 屏幕实时显示当前读取的摇杆模块输出的XY模拟量转换值,然后显示当前摇杆的按键状态。当摇杆滑动时,OLED上会实时显示变化数值;当按键被按下时,OLED也会显示按键按下的特定字符串。

/** @Descripttion: 双轴PS2摇杆基础测试demo* @Author: JaRyon* @version:* @Date: 2025-11-07 18:43:01*/
#include "stm32f10x.h"
#include "Systick.h"
#include "oled.h"
#include "joystick.h"uint32_t Buffer[2] = {0, 0};
uint8_t SW_State = 1;
char *str = "SW is IDLE";int main(void)
{uint32_t waitTimes = 0;// 初始化Systick_Init();OLED_Init();OLED_ClearAll();Joystick_Init();Joystick_ConvXY();waitTimes = Systick_GetTick();while (1){OLED_ClearAll();if (Systick_GetTick() - waitTimes >= 1000){Buffer[0] = Joystick_GetX();Buffer[1] = Joystick_GetY();waitTimes = Systick_GetTick();}if (Joystick_GetSW() == 1){str = "SW is IDLE";}else{str = "SW is Pressed";}OLED_ShowDecNum(20, 27, Buffer[0], 4, 6);OLED_ShowDecNum(20 + 6 * 6, 27, Buffer[1], 4, 6);OLED_ShowString(2, 50, str, 6);OLED_Update();}
}

5.4 测试效果


6、总结

       本文介绍了PS2双轴按键摇杆模块的原理及应用,并提供了基于STM32的寄存器级驱动代码,包含ADC采样、按键消抖处理等功能。测试程序通过OLED实时显示摇杆位置和按键状态,适用于遥控器、游戏手柄等场景。


以上便是本次文章的所有内容,欢迎各位朋友在评论区讨论,本人也是一名初学小白,愿大家共同努力,一起进步吧!

鉴于笔者能力有限,难免出现一些纰漏和不足,望大家在评论区批评指正,谢谢!

http://www.dtcms.com/a/590360.html

相关文章:

  • 怎么做网站充值网站注册公司需要几个人员
  • 网站掉权重是怎么回事软件开发者模式怎么打开
  • ArrayList底层实现及源码分析
  • 河北建设集团有限公司网站企业公司有哪些
  • HarmonyOS黑马云音乐项目:全场景在线音乐播放的实现与优化
  • 804.唯一的摩尔斯密码词(uthash)
  • 公司做网站域名归谁大学生做兼职上什么网站好
  • 网站分类代码网站建设经营服务合同范本
  • 手机网站设计案例电子商务网站建设个人总结
  • 【算法】--位运算
  • 门户网站的案例分析开发游戏用什么软件
  • 网站建设目标个人博客dwzh-cn 安装wordpress
  • 长沙网站优化步骤哈尔滨网站建设渠道
  • 浏览器打开网站wordpress表情不显示
  • 网站图片都是站外连接对seo小公司做网站推广好不好
  • 网站配置到iis后读不了数据seo优化百度技术排名教程
  • 第7章树和二叉树:线索二叉树
  • 网站专题制作流程深圳建网站哪个好
  • java的tomcat源码的http的session
  • 黑河北京网站建设网站架构计划书
  • 局域网网站建设软件怎么自己开公司
  • 网站建设是系统工程广州网站建设 名片制作 网站管理
  • 静态网站做淘宝客如何做英文网站的外链
  • 企业二级网站怎么做建邺做网站价格
  • 【Envi遥感图像处理】018:envi编辑头文件的方法及具体应用
  • RHCE复习作业2
  • AUTOACT论文翻译
  • html5 做手机网站什么是做学院网站
  • ipad 建网站电商入门教学
  • e2ee网站开发框架2.23先行版wordpress小论坛小程序