• 正文
    • 一模块来源
    • 二规格参数
    • 三移植过程
    • 四移植验证
  • 相关推荐
申请入驻 产业图谱

【CW32模块使用】双轴按键摇杆模块:CW32F030C8T6开发板控制电机旋转速度

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

双轴按键游戏摇杆模块,采用 PS2游戏手柄上金属按键摇杆电位器。模块特设二路模拟输出和一路数字输出接口、输出值分别对应(X、Y)双轴偏移量、其类型为模拟量、按键表示用户是否在Z轴上按下、其类型为数字开关量、用其可以轻松控制物体,在二维空间运动、因此可以通控制器编程、传感器扩展板插接、完成具有创意性遥控互动作品。

模块来源

模块实物展示:

规格参数

驱动电压:3.3V~5V

控制方式:ADC+GPIO

以上信息见厂家资料文件

移植过程

我们的目标是将例程移植至CW32F030C8T6开发板上【能够控制电机旋转速度的功能】。首先要获取资料,查看数据手册应如何实现读取数据,再移植至我们的工程。

3.1查看资料

输出信号:模块特设二路模拟输出(VRX,VRY)和一路数字输出接口(SW),二路模拟输出值分别对应(X,Y)双轴偏移量,其类型为模拟量;按键表示用户是否在Z轴上按下,其类型为数字开关量。

十字摇杆为一个双向的10K电阻器,随着摇杆方向不同,抽头的阻值随着变化。本模块如果使用5V供电,原始状态下X,Y读出电压为2.5V左右,当随箭头方向按下,读出电压值减少,限小为0V。

3.2引脚选择

VRX与VRY使用ADC功能。

想要使用ADC,需要确定使用的引脚是否有ADC外设功能。

当前只有AO引脚需要使用到ADC接口,所以DO引脚可以使用开发板上其他的GPIO。这里选择使用PA1和PA2的附加ADC功能。使用ADC的第1道和2通道。

ADC功能引脚

模块接线图

3.3移植至工程

移植步骤中的导入.c和.h文件与【CW32模块使用】DHT11温湿度传感器相同,只是将.c和.h文件更改为bsp_joystick.c与bsp_joystick.h。这里不再过多讲述,移植完成后面修改相关代码。

在文件bsp_joystick.c中,编写如下代码。

/* * Change Logs: * Date           Author       Notes * 2024-06-21     LCKFB-LP    first version */
#include "drv_spi.h"


/** 硬件SPI */#define SPI_WAIT_TIMEOUT       ((uint16_t)0xFFFF)
/**  * @brief :SPI初始化(硬件)  * @param :无  * @note  :无  * @retval:无  */void drv_spi_init( void ){        GPIO_InitTypeDef GPIO_InitStruct1;             // GPIO初始化结构体        GPIO_InitTypeDef GPIO_InitStruct2;             // GPIO初始化结构体
        SPI_GPIO_RCC();                                // 使能GPIO时钟        RCC_SPI_HARDWARE_ENABLE();                     // 使能SPI1时钟
        // GPIO复用为SPI1        BSP_SPI_AF_SCK();        BSP_SPI_AF_MISO();        BSP_SPI_AF_MOSI();
        GPIO_InitStruct1.Pins = SPI_NSS_GPIO_PIN|                                                        SPI_CLK_GPIO_PIN|                                                        SPI_MOSI_GPIO_PIN;      // GPIO引脚        GPIO_InitStruct1.Mode = GPIO_MODE_OUTPUT_PP;    // 推挽输出        GPIO_InitStruct1.Speed = GPIO_SPEED_HIGH;       // 输出速度高        GPIO_Init(SPI_GPIO_PORT, &GPIO_InitStruct1);    // 初始化
        GPIO_InitStruct2.Pins = SPI_MISO_GPIO_PIN;      // GPIO引脚        GPIO_InitStruct2.Mode = GPIO_MODE_INPUT_PULLUP; // 上拉输入        GPIO_Init(SPI_GPIO_PORT, &GPIO_InitStruct2);    // 初始化
        spi_set_nss_high();  // 片选拉高
        SPI_InitTypeDef  SPI_InitStructure; // SPI 初始化结构体
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;    // 双线全双工        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                         // 主机模式        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                     // 帧数据长度为8bit        SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                            // 时钟空闲电平为低        SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                          // 第1个边沿采样        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                             // 片选信号由SSI寄存器控制        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;    // 波特率为PCLK的8分频        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                    // 最高有效位 MSB 收发在前        SPI_InitStructure.SPI_Speed = SPI_Speed_Low;                          // 低速SPI
        SPI_Init(PORT_SPI, &SPI_InitStructure);   // 初始化        SPI_Cmd(PORT_SPI, ENABLE);   // 使能SPI1}
/**  * @brief :SPI收发一个字节  * @param :  * @TxByte: 发送的数据字节  * @note  :非堵塞式,一旦等待超时,函数会自动退出  * @retval:接收到的字节  */uint16_t drv_spi_read_write_byte( uint8_t TxByte ){        uint16_t l_Data = 0;        uint16_t l_WaitTime = 0;
    while(RESET == SPI_GetFlagStatus(PORT_SPI, SPI_FLAG_TXE))//等待发送缓冲区为空        {                if( SPI_WAIT_TIMEOUT == ++l_WaitTime )                {                        break;                        //如果等待超时则退出                }        }        l_WaitTime = SPI_WAIT_TIMEOUT / 2;                //重新设置接收等待时间(因为SPI的速度很快,正常情况下在发送完成之后会立即收到数据,等待时间不需要过长)        SPI_SendData(PORT_SPI, TxByte);//发送数据
    while(RESET == SPI_GetFlagStatus(PORT_SPI, SPI_FLAG_RXNE))//等待接收缓冲区非空        {                if( SPI_WAIT_TIMEOUT == ++l_WaitTime )                {                                break;                        //如果等待超时则退出                }        }    l_Data = SPI_ReceiveData(PORT_SPI);//读取接收数据
        return l_Data;                //返回}
/**  * @brief :SPI收发字符串  * @param :  * @ReadBuffer: 接收数据缓冲区地址  * @WriteBuffer:发送字节缓冲区地址  * @Length:字节长度  * @note  :非堵塞式,一旦等待超时,函数会自动退出  * @retval:无  */void drv_spi_read_write_string( uint8_t* ReadBuffer, uint8_t* WriteBuffer, uint16_t Length ){    spi_set_nss_low( );//拉低片选        while( Length-- )        {                *ReadBuffer = drv_spi_read_write_byte( *WriteBuffer ); //收发数据                ReadBuffer++;                WriteBuffer++;                                //读写地址加1        }    spi_set_nss_high( );//拉高片选}

在文件bsp_joystick.h中,编写如下代码。

/* * Change Logs: * Date           Author       Notes * 2024-06-21     LCKFB-LP    first version */
#ifndef __DRV_SPI_H__#define __DRV_SPI_H__
#include "board.h"

//SPI引脚定义#define SPI_GPIO_RCC()           __RCC_GPIOA_CLK_ENABLE() // GPIO时钟
#define SPI_GPIO_PORT            CW_GPIOA
#define SPI_CLK_GPIO_PIN         GPIO_PIN_5#define SPI_MISO_GPIO_PIN        GPIO_PIN_6#define SPI_MOSI_GPIO_PIN        GPIO_PIN_7#define SPI_NSS_GPIO_PIN         GPIO_PIN_4

#define spi_set_nss_high( )      GPIO_WritePin(SPI_GPIO_PORT, SPI_NSS_GPIO_PIN, GPIO_Pin_SET)   //片选置高#define spi_set_nss_low( )       GPIO_WritePin(SPI_GPIO_PORT, SPI_NSS_GPIO_PIN, GPIO_Pin_RESET) //片选置低


/******** 硬件SPI修改此次 ********/#define RCC_SPI_HARDWARE_ENABLE()         __RCC_SPI1_CLK_ENABLE()#define PORT_SPI                          CW_SPI1
//GPIO AF#define BSP_SPI_AF_SCK()                  PA05_AFx_SPI1SCK()#define BSP_SPI_AF_MISO()                 PA06_AFx_SPI1MISO()#define BSP_SPI_AF_MOSI()                 PA07_AFx_SPI1MOSI()

void drv_spi_init( void );uint16_t drv_spi_read_write_byte( uint8_t TxByte );void drv_spi_read_write_string( uint8_t* ReadBuffer, uint8_t* WriteBuffer, uint16_t Length );
#endif

移植验证

在自己工程中的main主函数中,编写如下。

/* * Change Logs: * Date           Author       Notes * 2024-06-25     LCKFB-LP    first version */#include "board.h"#include "stdio.h"#include "bsp_uart.h"#include "bsp_joystick.h"
int32_t main(void){    board_init();
    uart1_init(115200);
    ADC_Joystick_Init();
    printf("Demo Start.....rn");
    while(1)    {        if( Get_SW_state() == 0 )        {            printf("按钮按下!!rn");        }
        printf("X = [%d]rn",Get_Joystick_Percentage_value(0));        printf("Y = [%d]rn",Get_Joystick_Percentage_value(1));        printf("n");
        delay_ms(200);    }}

移植现象:移动摇杆并且按下,输出摇杆移动的数据。

模块移植成功案例代码:

链接:https://pan.baidu.com/s/1tubySHCtuFABDPQ1RjK40g?pwd=LCKF

提取码:LCKF

点赞
收藏
评论
分享
加入交流群
举报

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录

以开放、共享、互助为理念,致力于构建武汉芯源半导体CW32系列MCU生态社区。无论是嵌入式MCU小自还是想要攻破技术难题的工程师,亦或是需求解决方案的产品经理都可在CW32生态社区汲取营养、共同成长。

B站