基于stm32的避障/蓝牙/遥控小车

一、功能介绍

         该小车有遥控模式和避障模式,可以通过手机端蓝牙APP输入指定的指令切换对应的模式。小车进入工作前,有实现语音播报,根据语音播报指示,来实现小车的工作模式。小车在避障模式所执行的动作都会有对应的语音播报和上传对应的数据到蓝牙。小车的避障是通过超声波测距,来实现判断前方是否有障碍物,如果有障碍物就进行避障。小车也可以切换到遥控模式,由遥控对小车进行控制,小车执行的动作也会发送到蓝牙端。

二、项目模块

超声波、舵机、led灯、继电器、蓝牙、syn6288(语音模块)、433m、遥控、稳压模块、开关、stm32f103c8t6、L298n(电机驱动模块)、18650电池

三、代码演示

        1.蓝牙代码

        

        

2.语音模块代码
#ifndef __SYN6288_H
#define __SYN6288_H

#include "sys.h"


void SYN_FrameInfo(u8 Music, u8 *HZdata);
void YS_SYN_Set(u8 *Info_data);

#endif
#ifndef __USART3_H
#define __USART3_H
#include "stdio.h"	
#include "sys.h" 

#define USART3_REC_LEN  			200  	//定义最大接收字节数 200
#define EN_USART3_RX 			1		//使能(1)/禁止(0)串口1接收
	  	
extern u8  USART3_RX_BUF[USART3_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern u16 USART3_RX_STA;         		//接收状态标记	
//如果想串口中断接收,请不要注释以下宏定义
void USART3_SendString(u8 *DAT,u8 len);
void USART3_SendData(u8 data);
void USART3_Init(u32 bound);
#endif
#include "tim.h" 
#include "usart3.h"
#include "stm32f10x.h"
//通用定时器7中断初始化
//这里时钟选择为APB1的2倍,而APB1为42M
//arr:自动重装值。
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz 
//通用定时器中断初始化
//这里始终选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数		 
void TIM1_Int_Init(u16 arr,u16 psc)
{	
	NVIC_InitTypeDef NVIC_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//TIM3时钟使能    
	
	//定时器TIM1初始化
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE ); //使能指定的TIM1中断,允许更新中断
	
	TIM_Cmd(TIM1,ENABLE);//开启定时器1
	
	NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;		//子优先级2
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
	
}


//定时器7中断服务程序		    
void TIM1_IRQHandler(void)
{ 	
	if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)//是更新中断
	{	 			   
		USART3_RX_STA|=1<<15;	//标记接收完成
		TIM_ClearITPendingBit(TIM1, TIM_IT_Update  );  //清除TIM1更新中断标志    
		TIM_Cmd(TIM1, DISABLE);  //关闭TIM1 
	}	    
}












3.433m代码
#ifndef _433M_H
#define _433M_H
#include "stm32f10x.h"
//读取遥控433M的引脚和定义
#define Port_433M_B 	GPIOB
#define Port_433M_A 	GPIOA
#define GPIO_433M_D0 GPIO_Pin_6		//433M 左转--B
#define GPIO_433M_D1 GPIO_Pin_4		//433M 后退--C
#define GPIO_433M_D2 GPIO_Pin_5		//433M 右转--D
#define GPIO_433M_D3 GPIO_Pin_15	//433M 直走--A

//读取遥控433M的状态
#define D0_State	GPIO_ReadInputDataBit(Port_433M_B, GPIO_433M_D0)
#define D1_State	GPIO_ReadInputDataBit(Port_433M_B, GPIO_433M_D1)
#define D2_State	GPIO_ReadInputDataBit(Port_433M_B, GPIO_433M_D2)
#define D3_State	GPIO_ReadInputDataBit(Port_433M_A, GPIO_433M_D3)


void Init_433M_GPIO(void);


#endif
4.遥控模式的代码
#ifndef SIGNAL_H
#define SIGNAL_H
#include "stm32f10x.h"

//输入信号口的引脚
#define GPIO_IN_1 GPIO_Pin_6	//A6
#define GPIO_IN_2 GPIO_Pin_7	//A7
#define GPIO_IN_3 GPIO_Pin_0	//B0
#define GPIO_IN_4 GPIO_Pin_1	//B1

#define SignalPort_A   GPIOA 
#define SignalPort_B   GPIOB 


void InputSignalInitGPIO(void);
void Car_Go(void);
void Car_Back(void);
void Car_Left(void);
void Car_Right(void);
void Car_Stop(void);

#endif


4.避障模式代码
5.超声波代码
#include "wave.h"
#include "usart.h"

uint16_t mscount;  //毫秒的计数

//Trig(PB13)  Echo(PB12)
//超声波的配置
void wave_config(void)
{
	
	GPIO_InitTypeDef GPIO_WaveInit;  		 //定义GPIO结构的名字
	TIM_TimeBaseInitTypeDef TIM_WaveInit;	 //定义定时器的结构体名
	NVIC_InitTypeDef TIM_NVIC_WaveInit;		 //定义定时器中断的结构体名
	//配置时钟
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE); //打开GPIO的时钟
	RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM4, ENABLE); //打开定时器的时钟
	
	//2.配置GPIO
	//(1)PB13
	GPIO_WaveInit.GPIO_Mode  = GPIO_Mode_Out_PP;
	GPIO_WaveInit.GPIO_Pin   = Trig_Pin;
	GPIO_WaveInit.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(Wave_Port, &GPIO_WaveInit);
	//(2)PB12
	GPIO_WaveInit.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
	GPIO_WaveInit.GPIO_Pin   = Echo_Pin;
	GPIO_Init(Wave_Port, &GPIO_WaveInit);

	
	//3.定时器配置(TIM4),一个周期是1us
	TIM_WaveInit.TIM_ClockDivision  = TIM_CKD_DIV1;  		//配置分频系数为1
	TIM_WaveInit.TIM_CounterMode    = TIM_CounterMode_Up;	//配置成向上模式
	TIM_WaveInit.TIM_Period         = 1000-1;				//自动重装载值
	TIM_WaveInit.TIM_Prescaler      = 72-1;				    //预分频值
	TIM_TimeBaseInit(TIM4, &TIM_WaveInit);					//调用初始化定时器的函数
	TIM_Cmd(TIM4, DISABLE);									//失能定时器,是为了等待高电平再去打开定时器
	 //0.001S
	TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
	TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);       		//定时器4的中断配置
	
	//4.配置中断结构体
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);					//配置优先级组
	TIM_NVIC_WaveInit.NVIC_IRQChannel                   = TIM4_IRQn;//配置中断通道 
	TIM_NVIC_WaveInit.NVIC_IRQChannelCmd        		= ENABLE;	//打开中断
	TIM_NVIC_WaveInit.NVIC_IRQChannelPreemptionPriority = 0;		//配置抢占优先级
	TIM_NVIC_WaveInit.NVIC_IRQChannelSubPriority        = 2;		//设置响应优先级
	NVIC_Init(&TIM_NVIC_WaveInit);									//调用中断初始化函数
	

	
}
//打开定时器
void TIM_OPen(void)
{
	TIM_SetCounter(TIM4, 0);   //设置定时器计数值,初始化为0
	mscount = 0;
	TIM_Cmd(TIM4, ENABLE);		//打开定时器开始计数
}

//关闭定时器
void TIM_Close(void)
{
	TIM_Cmd(TIM4, DISABLE);
}

//中断服务函数,函数的作用是发生了多少次中断就去计数多少次的值
//定时器打开之后才会有中断
void TIM4_IRQHandler(void)
{
	//上面配置是1Ms一个周期,也就是说检查有没有高电平就是1ms的间隔
	// 开启定时器更新中断(即定时时间到了)
	//该函数的作用是,判断定时器TIMx的中断类型TIM_IT是否发生中断。
	if(TIM_GetITStatus( TIM4,TIM_IT_Update) == SET)//更新达到一个arr的时候就会产生一个更新中断(此时高电平)
	{
		TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
		mscount++;
	}
	
}

//得到高电平的时间,获取定时器的计数值
int getEchoTim(void)
{
	uint32_t t =0;
	t = mscount*1000;     		//转换成us
	t += TIM_GetCounter(TIM4);//获取定时器的计数值(定时时间+一次中断的检测时间),每获取成功一次定时器的计数值是1ms
	TIM4->CNT = 0;			//当前值置零
	ms_delay(50);
	return t;
}

//计算距离
float getLen(void)
{
	uint32_t t =0;
	uint8_t i = 0;
	float len = 0;
	float sum = 0;
	while(i != 5)//计算5次 取平均值 得到更准确的值
	{
		Trig_Send(1);	
		us_delay(20);	//此时超声波开始工作
		Trig_Send(0); 
		
		//echo等待高电平
		while(ECHO_STATUS == 0);
		TIM_OPen();//打开定时器
		 
		//echo等待低电平
		while(ECHO_STATUS==1);
		TIM_Close();
		i = i+1;
		t = getEchoTim();
		sum = ((float)t/58.0);
		len += sum;
		
	}
	 return (len/5.0); 
	
}
#ifndef __WAVE_H
#define __WAVE_H

//Trig(PB13)  Echo(PB12)
#define Trig_Pin GPIO_Pin_13
#define Echo_Pin GPIO_Pin_12
#define Wave_Port GPIOB

#include "stm32f10x.h"
#include "SystemTick.h"
void wave_config(void);
void TIM_Close(void);
void TIM_OPen(void);
void TIM4_IRQHandler(void);
int getEchoTim(void);
float getLen(void);

#define ECHO_STATUS GPIO_ReadInputDataBit(Wave_Port,Echo_Pin)
#define Trig_Send(a) if(a)\
					 GPIO_SetBits(Wave_Port, Trig_Pin);\
					 else\
					 GPIO_ResetBits(Wave_Port, Trig_Pin)

#endif

6.舵机代码
#include "motor.h"
#include "stm32f10x.h"


//具体的周期计算公式为:周期=(arr+1)*(psc+1)/CLK。其中CLK为计数器的时钟频率,
//我的是72MHZ,也就是72000000。最后计算结果单位为秒,结果为0.02s,也就是20ms。

//PWM周期为20ms = (7200*200)/72000000=0.02s
//所以TIM_Period = 199,TIM_Prescaler = 7199
//t = 0.5ms——————-舵机会转动 0 °
//t = 1.0ms——————-舵机会转动 45°
//t = 1.5ms——————-舵机会转动 90°
//t = 2.0ms——————-舵机会转动 135°
//t = 2.5ms——————-舵机会转动180°
//PWM占空比是指在一个周期内,信号处于高电平的时间占据整个信号周期的百分比,
//由于PWM周期为20ms,所以(以舵机会转动 45°为例),占空比就应该为1ms/20ms = 5%,
//所以TIM_SetCompare2的 TIMx 捕获比较 2 寄存器值就为200-200*5% = 190
/*
*功能:配置舵机的初始化,复用到TIM2的通道2
*参数:无
*返回值:无
*/
void Confige_S90_Init(void)
{
	GPIO_InitTypeDef S90_GPIO_Init_Struct;				//舵机引脚结构体名
	TIM_TimeBaseInitTypeDef S90_TIM2_OC2_Init_Struct;	//定时器2通道2的结构体名
	TIM_OCInitTypeDef S90_OC_Init_Struct;				//通道结构体初始化
	
	//打开时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	//初始化舵机引脚
	S90_GPIO_Init_Struct.GPIO_Mode 	= GPIO_Mode_AF_PP;
	S90_GPIO_Init_Struct.GPIO_Pin	= S90_Pin;
	S90_GPIO_Init_Struct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(S90_Port, &S90_GPIO_Init_Struct);
	
	//定时器的配置
	S90_TIM2_OC2_Init_Struct.TIM_ClockDivision = TIM_CKD_DIV1;		//不分频
	S90_TIM2_OC2_Init_Struct.TIM_CounterMode   = TIM_CounterMode_Up;//向上计数模式
	S90_TIM2_OC2_Init_Struct.TIM_Period		   = 200-1;				//重装载值
	S90_TIM2_OC2_Init_Struct.TIM_Prescaler	   = 7200-1;			//分频系数值
	TIM_TimeBaseInit(TIM2, &S90_TIM2_OC2_Init_Struct);				//初始化结构体
	//200*7200/72000000=0.02s=20ms
	//定时器通道的配置
	S90_OC_Init_Struct.TIM_OCMode		= TIM_OCMode_PWM1;			//PWM1模式
	S90_OC_Init_Struct.TIM_OutputState	= TIM_OutputState_Enable;	//输出比较使能
	S90_OC_Init_Struct.TIM_OCPolarity	= TIM_OCPolarity_Low;		//低电平有效
	TIM_OC2Init(TIM2,&S90_OC_Init_Struct);							//TIM2通道2初始化
	TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);				//使能TIM2通道2
	
	
	TIM_Cmd(TIM2, ENABLE);											//打开定时器TIM2
}
#ifndef MOTOR_H
#define MOTOR_H
#include "stm32f10x.h"

#define S90_Pin  GPIO_Pin_1		//舵机的引脚
#define S90_Port	GPIOA		//舵机的端口


#define   SG90_Right_90     TIM_SetCompare2(TIM2, 195)		
#define   SG90_Right_45		TIM_SetCompare2(TIM2, 192)		
#define   SG90_Front		TIM_SetCompare2(TIM2, 185)		
#define   SG90_Left_45		TIM_SetCompare2(TIM2, 178)		
#define   SG90_Left_90		TIM_SetCompare2(TIM2, 175)


void Confige_S90_Init(void);
#endif
7.选择模式代码
#ifndef MODE_H
#define MODE_H
#include "stm32f10x.h"
void Bizhang_Mode(void);
void Yaokong_Mode(void);
void xunji_Mode(void);
#endif

8.led代码
#include "led.h"
#include "stm32f10x.h"



//初始化引脚的函数
/*
typedef struct
{
  uint16_t GPIO_Pin;             引脚
                                     
  GPIOSpeed_TypeDef GPIO_Speed; 	引脚的输出速度
                                      
  GPIOMode_TypeDef GPIO_Mode;   	引脚的功能模式
                                      
}GPIO_InitTypeDef;
*/

/*
typedef enum
{ GPIO_Mode_AIN = 0x0, 模拟输入
  GPIO_Mode_IN_FLOATING = 0x04,浮空输入
  GPIO_Mode_IPD = 0x28, 下拉输入
  GPIO_Mode_IPU = 0x48, 上拉输入
  GPIO_Mode_Out_OD = 0x14, 开漏输出
  GPIO_Mode_Out_PP = 0x10, 推挽输出
  GPIO_Mode_AF_OD = 0x1C,  复用开漏
  GPIO_Mode_AF_PP = 0x18   复用推挽
}GPIOMode_TypeDef;

*/
/*
void GPIO_DeInit(GPIO_TypeDef* GPIOx);去初始化
void GPIO_AFIODeInit(void);
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct); GPIO初始化
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//读取单个输入的引脚
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);					//读取一排引脚的输入
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//读取输出单个的引脚
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);						//读取一排引脚的输出
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);	//设置高电平
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//设置低电平
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
void GPIO_EventOutputCmd(FunctionalState NewState);
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);//外部中断线的配置
void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);

*/
//初始化灯的函数
void INIT_LED(void)
{
	//定义初始化引脚的结构体
	GPIO_InitTypeDef init_led; 

	//初始化时钟
	//void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
	//第一个是外设,第二个参数是状态
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

		//初始化引脚
	init_led.GPIO_Pin = GPIO_Pin_7;		//设置引脚
	init_led.GPIO_Speed = GPIO_Speed_2MHz;	//设置输出的速度
	init_led.GPIO_Mode = GPIO_Mode_Out_PP;	//设置输出模式为推挽输出
	GPIO_Init(GPIOB, &init_led);//真正的初始化到引脚结构体中
	//第一个参数是GPIO寄存器,第二个参数是初始化引脚结构体的地址
	//初始化GPIOA1 哞哞板的led在A1
	

}

9.主函数
#include "stm32f10x.h"
#include "main.h"
#include "led.h"
#include "switch.h"
#include "exit.h"
#include "usart.h"
#include <stdio.h>
#include "tim.h"
#include "motor.h"
#include "SystemTick.h"
#include "wave.h"
#include "spi.h"
#include "signal.h"
#include "_433m.h"
#include "pwm.h"
#include "xunji.h"
#include "bluetooth.h"
#include "sys.h"
#include "delay.h"
#include "stdio.h"
#include "usart3.h"
#include "syn6288.h"
#include "mode.h"



char tmp; //存放蓝牙串口的字符



/**************芯片设置命令*********************/
u8 SYN_StopCom[] = {0xFD, 0X00, 0X02, 0X02, 0XFD}; //停止合成
u8 SYN_SuspendCom[] = {0XFD, 0X00, 0X02, 0X03, 0XFC}; //暂停合成
u8 SYN_RecoverCom[] = {0XFD, 0X00, 0X02, 0X04, 0XFB}; //恢复合成
u8 SYN_ChackCom[] = {0XFD, 0X00, 0X02, 0X21, 0XDE}; //状态查询
u8 SYN_PowerDownCom[] = {0XFD, 0X00, 0X02, 0X88, 0X77}; //进入POWER DOWN 状态命令
int  main()
{
	
	unsigned char bizhang_Flag = 1;
//	unsigned char xunji_Flag = 	1;
	unsigned char yaokong_Flag = 1;
	unsigned char tingche_Flag = 1;

	initSysTick();	//定时器初始化
	usart_init();	//串口初始化
	USART2_Init();	//蓝牙串口的初始



//	
//	InputSignalInitGPIO();	//遥控模式输出控制电机引脚信号初始化
//	xunji_GPIO_Init();		//循迹函数初始化
	wave_config();			//超声波的初始化
	TIM3_GPIO_PWM_Init();	//PWM模式控制电机引脚的初始化
	Confige_S90_Init();		//舵机初始化
	SG90_Front;				//摆正舵机位置
	ms_delay(300);			//让舵机完全到位
	
	//语音模块的初始化
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	delay_init();
	USART3_Init(9600);

	SYN_FrameInfo(0, "[v7][m1][t5]请通过蓝牙YBS字符来控制对应的模式");
	ms_delay(1000);
	ms_delay(1000);
	ms_delay(1000);
	ms_delay(1000);
	ms_delay(1000);
	ms_delay(1000);
	ms_delay(1000);
	INIT_LED();				//车灯初始化
	SYN_FrameInfo(0, "[v7][m1][t5]开启车灯");
	GPIO_ResetBits(GPIOB,  GPIO_Pin_7);
	ms_delay(200);



   while(1)
	 {
		 
//		Bizhang_Mode();//不断避障
//		printf("wave = %f\r\n",getLen());
		//遥控模式
		while(tmp == 'Y')
		{
			
			if(yaokong_Flag)
			{
				TIM3_GPIO_PWM_Init();	//PWM模式控制电机引脚的初始化
				ms_delay(5);
//				Init_433M_GPIO();		//遥控433M初始化
//				InputSignalInitGPIO();	//遥控模式输出控制电机引脚信号初始化
				SYN_FrameInfo(0, "[v7][m1][t5]开启遥控模式");
				ms_delay(500);
				ms_delay(1000);
				bizhang_Flag = 1;
//				xunji_Flag =1;
				tingche_Flag = 1;
				yaokong_Flag--;
			}
			Yaokong_Mode();
		}
		
		
		//避障模式
		while(tmp == 'B')
		{  
			if(bizhang_Flag)
			{
				TIM3_GPIO_PWM_Init();	//PWM模式控制电机引脚的初始化
				ms_delay(5);
				SYN_FrameInfo(0, "[v7][m1][t5]开启避障模式");
				ms_delay(1000);
				ms_delay(1000);
//				xunji_Flag = 1;
				yaokong_Flag = 1;
				tingche_Flag = 1;
				bizhang_Flag--;
			}
			Bizhang_Mode();//不断避障
		}
		
//		while(ch == 'X')
//		{  
//			while(xunji_Flag--)
//			{
				TIM3_GPIO_PWM_Init();	//PWM模式控制电机引脚的初始化
//				SYN_FrameInfo(0, "[v7][m1][t5]开启避障模式");
//				ms_delay(1000);
//				ms_delay(1000);
//				tingche_Flag = 1;
//			}
//			
//			xunji_Mode();//不断避障
//		}
		
		if(tmp == 'S')
		{
			if(tingche_Flag)
			{
				SYN_FrameInfo(0, "[v7][m1][t5]开启停车模式");
				PWM_CarStop();
				ms_delay(1000);
				ms_delay(1000);
				tingche_Flag--;
			}
			
		}
	 }
	 
		 
   
}



/*
*功能:蓝牙通过串口2中断接收,之后发给串口1(上位机)
*参数:无
*返回值:无
*/

void USART2_IRQHandler(void)
{ 
	if(USART_GetITStatus(USART2, USART_IT_RXNE) ==SET )
	{
		USART_ClearITPendingBit(USART2, USART_IT_RXNE);
		tmp = USART_ReceiveData(USART2);
		USART_SendData(USART1, tmp);
		while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);//等待发送完成
	}
	
}


/*
*功能:上位机通过串口1中断接收,之后发给串口2(蓝牙)
*参数:无
*返回值:无
*/

//void USART1_IRQHandler(void)
//{
//	char tmp; 
//	
//	if(USART_GetITStatus(USART1, USART_IT_RXNE) ==SET )
//	{
//		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
//		tmp = USART_ReceiveData(USART1);
//		USART_SendData(USART2, tmp);
//		while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);//等待发送完成
//		
//	}
//	
//}

四.视频演示/图片

需要源码加v:YX_CFZ_3454

视频地址https://live.csdn.net/v/376427

  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32F407VET6是一款基于ARM Cortex-M4内核的32位微控制器,具有丰富的外设资源和高性能。蓝牙遥控避障小车是一种利用STM32F407VET6控制的小车,通过蓝牙无线通信和避障传感器实现遥控和避障功能。 首先,需要将STM32F407VET6与蓝牙模块进行连接,通过UART通信方式实现与蓝牙模块的数据传输。可以利用STM32的串口功能来实现与蓝牙模块的通信,并编写相关的驱动程序和数据处理逻辑。 其次,小车需要安装避障传感器,用于检测前方有无障碍物。可以选择适合的红外避障传感器或超声波传感器,并将其与STM32F407VET6连接,通过GPIO引脚读取传感器的输出信号。 在软件设计方面,可以采用无线通信协议,如蓝牙串口协议,在手机上编写相应的蓝牙遥控应用程序,实现对小车的前进、后退、左转、右转等控制操作。手机通过蓝牙STM32F407VET6建立连接,将相应的控制指令发送给控制器,由控制器将指令解析并控制小车的动作。 同时,通过不断的读取避障传感器的输出信号,判断前方是否有障碍物。当检测到障碍物时,控制器会根据事先设计好的避障逻辑对小车进行相应的动作,如停车、后退、左转或右转,以避免撞击障碍物。 综上所述,STM32F407VET6蓝牙遥控避障小车是一种利用STM32F407VET6控制的小车,通过蓝牙无线通信和避障传感器实现遥控和避障功能。这种小车可以用于各种场景,如智能家居、无人物流等领域。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值