nucleo-f411re学习记录-9,双轴XY摇杆传感器

代码仓库

双轴XY摇杆传感器是一种能将物理推摇动作,转换为控制二维空间移动(如上下、左右)电信号的装置

--deepseek

该双轴XY摇杆传感器配备5个引脚,分别是:

  • GND(地线)
  • +5V(电源)
  • VRx(X轴模拟信号输出)
  • VRy(Y轴模拟信号输出)
  • SW(按键数字信号输出)

使用注意事项:

  1. GPIO配置时需将SW引脚设为输入模式
  2. VRx和VRy分别输出X/Y轴的模拟信号

通过主控芯片的ADC功能读取VRx和VRy引脚的电压值,就能确定摇杆的位置。当摇杆处于极限位置时,电压值会显示为0或最大值。

查看数据手册发现仅有一个ADC,且挂载在APB2上,不过可使用的通道还是挺多的。

我使用的是PC2和PC3,对应的通道号为12和13。至于SW(开关),只需选用任意一个空闲的IO口即可。

1,初始化代码

复制代码
void Rocker_Init(void)
{
    GPIO_InitTypeDef        GPIO_InitStructure;     // GPIO配置结构体
    ADC_InitTypeDef         ADC_InitStruct;         // ADC配置结构体
    ADC_CommonInitTypeDef   ADC_CommonInitStruct;   // ADC公共配置结构体

    // 使能GPIOB和GPIOC时钟,使能ADC1时钟
    RCC_AHB1PeriphClockCmd(ROCKER_SW_GPIO_CLK, ENABLE);     // 使能摇杆按键引脚所在的时钟
    RCC_AHB1PeriphClockCmd(ROCKER_URX_GPIO_CLK, ENABLE);    // 使能摇杆X/Y轴引脚所在的时钟
    RCC_APB2PeriphClockCmd(ROCKER_ADC_CLK, ENABLE);         // 使能ADC1外设时钟

    // 配置摇杆开关引脚 (PB7)
    GPIO_InitStructure.GPIO_Pin   = ROCKER_SW_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP; // 上拉输入
    GPIO_Init(ROCKER_SW_GPIO_PORT, &GPIO_InitStructure);
    
    // 配置摇杆X轴引脚 (PC2) / Y轴引脚 (PC3)
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AN; // 模拟输入
    GPIO_InitStructure.GPIO_Pin   = ROCKER_URX_GPIO_PIN | ROCKER_UTY_GPIO_PIN;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL; // 模拟输入不需要上下拉
    GPIO_Init(ROCKER_URX_GPIO_PORT, &GPIO_InitStructure);
    
    // ADC公共配置
    ADC_CommonInitStruct.ADC_Mode               = ADC_Mode_Independent;         // 独立模式(只使用ADC1)
    ADC_CommonInitStruct.ADC_Prescaler          = ADC_Prescaler_Div4;           // ADC时钟分频
    ADC_CommonInitStruct.ADC_DMAAccessMode      = ADC_DMAAccessMode_Disabled;   // 不使用DMA
    ADC_CommonInitStruct.ADC_TwoSamplingDelay   = ADC_TwoSamplingDelay_5Cycles; // 两个采样阶段之间的延迟周期
    ADC_CommonInit(&ADC_CommonInitStruct);

    ADC_InitStruct.ADC_Resolution           = ADC_Resolution_12b;               // 12位分辨率(转换值范围0~4095)
    ADC_InitStruct.ADC_ScanConvMode         = DISABLE;                          // 禁止扫描模式(只转换1个通道)
    ADC_InitStruct.ADC_ContinuousConvMode   = DISABLE;                          // 禁止连续转换模式(每次转换需要软件触发)
    ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;    // 不使用外部触发(使用软件触发)
    ADC_InitStruct.ADC_DataAlign            = ADC_DataAlign_Right;              // 数据右对齐(转换结果存放在低12位)
    ADC_InitStruct.ADC_NbrOfConversion      = 1;                                // 转换序列中的通道数量为1
    ADC_Init(ROCKER_ADC, &ADC_InitStruct);

    ADC_Cmd(ROCKER_ADC, ENABLE);

}

2,建议在获取指定通道ADC值时,对于包含while循环的代码段,应当增加超时处理机制以防止程序死锁。

复制代码
static uint16_t Rocker_Read_ADC(uint32_t channel)
{
    // 配置转换通道
    ADC_RegularChannelConfig(ROCKER_ADC, channel, 1, ADC_SampleTime_56Cycles);
    
    // 启动软件转换
    ADC_SoftwareStartConv(ROCKER_ADC);
    
    uint8_t timeout = 50; // 超时计数,避免死循环
    // 等待转换完成
    while(ADC_GetFlagStatus(ROCKER_ADC, ADC_FLAG_EOC) == RESET)
    {
        vTaskDelay(pdMS_TO_TICKS(2)); // 等待2ms,避免死循环占用CPU
        timeout--;
        if(timeout == 0)
        {
            // 超时处理
            return 0; // 返回0表示读取失败
        }
    }
    
    // 返回转换结果
    return ADC_GetConversionValue(ROCKER_ADC);
}

3,封装获取X轴与Y轴的接口

复制代码
uint16_t Rocker_Read_X(void)
{
    return Rocker_Read_ADC(ROCKER_X_ADC_CHANNEL);
}

uint16_t Rocker_Read_Y(void)
{
    return Rocker_Read_ADC(ROCKER_Y_ADC_CHANNEL);
}
相关推荐
吃好睡好便好17 小时前
在Matlab中绘制阶梯图
开发语言·人工智能·学习·算法·机器学习·matlab
Restart-AHTCM18 小时前
LangChain学习之提示词模板 (Prompts) - 练习(2/8)
学习·langchain
YangYang9YangYan18 小时前
2026产品专员学习数据分析的价值与路径
学习·数据挖掘·数据分析
淘矿人18 小时前
【AI大模型】AI 大模型推理平台完整测评:8 家主流聚合服务对比分析
人工智能·sql·gpt·学习·github·php
我想我不够好。19 小时前
2026.5.20 消防监控学习 1.5hour
学习
爱喝水的鱼丶19 小时前
SAP-ABAP:数据类型与数据对象(8篇) 第七篇:进阶优化篇——基于类型与对象特征的性能优化技巧
运维·数据库·学习·性能优化·sap·abap·开发交流
知识分享小能手19 小时前
Flask入门学习教程,从入门到精通, 认识Flask路由 — 知识点详解 (2)
python·学习·flask
清平乐的技术专栏19 小时前
【Flink学习】(六)Flink 三大时间语义 + 水位线 Watermark
大数据·学习·flink
楼兰公子19 小时前
《深入理解Linux网络技术内幕》配套学习大纲 + 源码Demo + 进阶实战实例
linux·arm开发·学习
楼田莉子19 小时前
C++17新特性:结构化绑定/inline变量/if相关的变化
c++·后端·学习