STM32F103C8T6驱动XY摇杆并打印在串口上

1. 引言

在嵌入式开发中,模拟量输入设备是实现人机交互的重要组件。本文以常见的HW504双轴摇杆模块为例,详细介绍如何在STM32F103C8T6微控制器上实现摇杆数据采集,并通过串口实时显示X/Y轴坐标和按键状态,下面代码每一行都有注释讲解,用户可以根本代码注释来进行理解

源码链接:文件分享

2. 硬件介绍

2.1 硬件清单

  • STM32F103C8T6核心板

  • HW504双轴摇杆模块(5引脚)

    • VRX:X轴模拟输出

    • VRY:Y轴模拟输出

    • SW:按键数字输出

    • +5V:电源正极

    • GND:电源地

2.2 硬件连接

摇杆引脚STM32引脚
VRXPA0
VRYPA1
SWPB9
+5V3.3V/5V
GNDGND

3. 代码实现

代码设计外设:

1.ADC

2.XY摇杆模块

3.串口

3.1 ADC初始化AD.c源文件配置

#include "stm32f10x.h"                  // Device header

/*******************************

 @函数:ADC初始化
 @参数:void
 返回值:void

*******************************/

void AD_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);		//开启ADC1内部时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);		//开启GPIOA内部时钟
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);	//ADC时钟:72/6=12Mz, 配置ADC分频(*2、*4、6、8)
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		//模拟输入,ADC专属
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);   //ADC输入的引脚的GPIO的配置
	
	
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;		//工作模式,独立
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;		//数据对齐,右对齐
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;		//外部触发源选择,此处为不使用外部触发,使用软件触发
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;		//连续或单次模式,ENABLE为连续
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;		//扫描或单次,ENABLE为扫描		
	ADC_InitStructure.ADC_NbrOfChannel = 1;		//0——16,通道数目,选择1哥通道
	ADC_Init(ADC1, &ADC_InitStructure);	//初始化ADC
	
	ADC_Cmd(ADC1, ENABLE);		//开启ADC电源
	
	ADC_ResetCalibration(ADC1);		//复位校准
	while(ADC_GetResetCalibrationStatus(ADC1) == SET);	//等待校准完成
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1) == SET);       //等待开启完成
}


/*******************************

 @函数:获取ADC的值
 @参数:ADC_Channel
 返回值:uint16_t

*******************************/
uint16_t AD_GetValue(uint8_t ADC_Channel)
{
	ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_55Cycles5);		//ADC_Channel_0,通道0,对应PA0, “1”代表序列1,ADC_SampleTime_55Cycles5代表采样时间55.5*ADCCLK(T)
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//软件触发ADC转换
	while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);		//等待转换完成
	return ADC_GetConversionValue(ADC1);		//获取转换值
	  
}
ADC的AD.h头文件
#ifndef __AD_H
#define __AD_H

void AD_Init();
uint16_t AD_GetValue(uint8_t ADC_Channel);

#endif

关键点说明

  • 采用单次转换模式降低功耗

  • 校准过程确保ADC精度

  • 采样时钟设置为12MHz(主频72MHz / 6)

3.2 摇杆模块驱动实现

摇杆HW504.C

#include "stm32f10x.h"                  // Device header
#include "AD.h"

/**************
引脚连接:

VRX - A0

VRY - A1

SW - PB12

5V- 5V

GND - GND

by: 普普通通

***************/

/*******************************

 @函数:HW504摇杆的初始化
 @参数:void
 返回值:void

*******************************/

void HW504_Init(void)
{
	AD_Init();  //ADC初始化
	RCC_APB1PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  //打开SW引脚对应的I/O口的时钟
	
	GPIO_InitTypeDef GPIO_InitStructure;     //SW引脚对应的I/O口的配置
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  //数字量输出引脚,为高低电平,配置成浮空输入
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	GPIO_ResetBits(GPIOB, GPIO_Pin_9);   //复位
	
}

/*******************************

 @函数:获取HW504_SW引脚的值
 @参数:void
 返回值:uint8_t

*******************************/

uint8_t HW504_R_SW()
{
   return GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_9);
	
}

/*******************************

 @函数:获取HW504_X引脚的值
 @参数:void
 返回值:uint16_t

*******************************/

uint16_t HW504_R_X()
{
	uint16_t DataX = AD_GetValue(ADC_Channel_0);  //PA0
	return DataX;
	
}

/*******************************

 @函数:获取HW504_Y引脚的值
 @参数:void
 返回值:uint16_t

*******************************/

uint16_t HW504_R_Y()
{
	uint16_t DataY = AD_GetValue(ADC_Channel_1);  //PA1
	return DataY;
	
}

串口USART.C

/***************STM32F103C8T6**********************
 * 文件名  :usart1.c
 * 描述    :将printf函数重定向到USART1。
 * 硬件连接:------------------------
 *          | PA9  - USART1(Tx)      |
 *          | PA10 - USART1(Rx)      |
 *           ------------------------
 * 库版本  :ST3.0.0  *

********************LIGEN*************************/

#include "usart.h"
#include <stdarg.h>


void USART1_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	/* 使能 USART1 时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); 

	/* USART1 使用IO端口配置 */    
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);    
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);   //初始化GPIOA
	  
	/* USART1 工作模式配置 */
	USART_InitStructure.USART_BaudRate = 115200;	//波特率设置:115200
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;	//数据位数设置:8位
	USART_InitStructure.USART_StopBits = USART_StopBits_1; 	//停止位设置:1位
	USART_InitStructure.USART_Parity = USART_Parity_No ;  //是否奇偶校验:无
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//硬件流控制模式设置:没有使能
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//接收与发送都使能
	USART_Init(USART1, &USART_InitStructure);  //初始化USART1
	USART_Cmd(USART1, ENABLE);// USART1使能
}


 /* 描述  :重定向c库函数printf到USART1*/ 
 /*
 
 注意:
即使编写了 fputc 函数,若未在 Keil 中启用 MicroLib,printf 将无法正确重定向到串口。

解决方案:
右键工程 → Options for Target → Target 标签。

 勾选 Use MicroLib(确保标准库支持 printf 重定向)。
 */
int fputc(int ch, FILE *f)
{
/* 将Printf内容发往串口 */
  USART_SendData(USART1, (unsigned char) ch);
  while (!(USART1->SR & USART_FLAG_TXE));
 
  return (ch);
}


串口usart.h

#ifndef __USART1_H
#define	__USART1_H

#include "stm32f10x.h"
#include <stdio.h>

void USART1_Config(void);
int fputc(int ch, FILE *f);
void USART1_printf(USART_TypeDef* USARTx, uint8_t *Data,...);

#endif /* __USART1_H */

主函数main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "HW504.h"
#include "usart.h"
#include <stdio.h>

uint16_t X, Y;
uint8_t SW;

int main(void)
{
//	OLED_Init();
	HW504_Init();
    USART1_Config();

	while (1)
	{
		X = HW504_R_X();   
		SW = HW504_R_SW();
		Y = HW504_R_Y();
        printf("\r\ntest:\n");
        printf("\r\nX:%d\n",X);
        printf("\r\nY:%d\n",Y);
        printf("\r\nSW:%d\n",SW);
        Delay_ms(500);
        
        
		
	}
}

最后看效果:

​​

你好!对于使用STM32的蓝牙通信小车的开发,您可以按照以下步骤进行: 1. 硬件准备: - STM32开发板(如:STM32F103C8T6) - 蓝牙模块(如:HC-05、HC-06) - 直流电机驱动模块(如:L298N) - 直流电机和轮子 - 摇杆模块(如:XY-JOYSTICK) - 杜邦线等其他所需部件 2. 连接硬件: - 将STM32与蓝牙模块连接,使其能够进行串口通信。 - 将STM32与直流电机驱动模块连接,通过PWM信号控制电机的速度和方向。 - 连接摇杆模块,获取摇杆的位置信息。 3. 编写代码: - 使用STM32的开发环境(如:Keil、STM32CubeIDE)编写代码。 - 配置串口通信,并实现与蓝牙模块的数据交互。 - 读取摇杆的位置信息,并将其转换为电机的速度和方向。 - 控制直流电机驱动模块,实现小车的运动。 4. 蓝牙通信: - 在代码中实现蓝牙模块的初始化和数据传输功能。 - 使用蓝牙串口协议(如:AT指令、透明传输等)实现与手机或其他蓝牙设备的通信。 5. 测试和调试: - 烧录代码到STM32开发板。 - 运行程序,测试小车的运动控制和蓝牙通信功能。 - 根据实际情况进行调试和优化。 请注意,以上步骤仅为一般参考,具体实现方式可能因您使用的硬件和开发工具而有所不同。在实际开发过程中,您可能需要参考相关文档和资料,并进行适当的修改和调整。祝您开发顺利!如有更多问题,欢迎随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值