基于stm32的智能小车作品(循迹避障蓝牙)(下)


基于stm32的智能小车作品(循迹避障蓝牙)(上)的链接:点击此处
工程文件的网盘链接:点击此处 提取码:pdqg


五、避障小车制作

1.超声波模块接线

在这里插入图片描述
从商家的资料知道,TRIG和ECHO接单片机引脚,而OUT口,在我学习这个模块的过程中发现很多文章都没用这个东西,因此在这里我也不打算用,VCC口接5V。

从上篇的原理图看,我本来打算超声波的TRIG和ECHO引脚分别接PB8和PB9的,但在上篇中我也提到了我的c8t6的PB引脚有问题。所以在接线时,我放弃了接PB引脚改为接PA11、PA12。
如图,通过飞线的方法从PA11、PA12中引出两条线在连接超声波,于是超声波就可以用了。
在这里插入图片描述

2.工作原理

在这里插入图片描述
还是商家的资料,我们就知道了超声波模块的大致原理。更加详细的超声波介绍可以看看这个文章:STM32的超声波测距程序

3. 超声波避障程序

cs.c

#include "cs.h"

#include "stm32f10x.h"
#include "delay.h"

/*记录定时器溢出次数*/
uint overcount=0;

/*设置中断优先级*/
void NVIC_Config(void)
{
	NVIC_InitTypeDef NVIC_InitStructer;

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

	NVIC_InitStructer.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStructer.NVIC_IRQChannelSubPriority=0;
	NVIC_InitStructer.NVIC_IRQChannel=TIM4_IRQn;
	NVIC_InitStructer.NVIC_IRQChannelCmd=ENABLE;

	NVIC_Init(&NVIC_InitStructer);
}

/*初始化模块的GPIO以及初始化定时器TIM2*/
void CH_SR04_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructer;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructer;

	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

	/*TRIG触发信号*/
	GPIO_InitStructer.GPIO_Speed=GPIO_Speed_50MHz;				//原来接PB 8、PB 9不能用,后改为PA 11,PA 12就能用
	GPIO_InitStructer.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructer.GPIO_Pin=GPIO_Pin_11;
	GPIO_Init(GPIOA, &GPIO_InitStructer);

	/*ECHO回响信号*/
	GPIO_InitStructer.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_InitStructer.GPIO_Pin=GPIO_Pin_12;
	GPIO_Init(GPIOA, & GPIO_InitStructer);
	
	GPIO_ResetBits(GPIOA,GPIO_Pin_4);

	/*定时器TIM2初始化*/
	TIM_DeInit(TIM4);
	TIM_TimeBaseInitStructer.TIM_Period=999;//定时周期为1000
	TIM_TimeBaseInitStructer.TIM_Prescaler=71; //分频系数72
	TIM_TimeBaseInitStructer.TIM_ClockDivision=TIM_CKD_DIV1;//不分频
	TIM_TimeBaseInitStructer.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructer);

	TIM_ClearFlag(TIM4,TIM_FLAG_Update);
	TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);//开启更新中断
	NVIC_Config();
	TIM_Cmd(TIM4,DISABLE);//关闭定时器使能

}



float Senor_Using(void) //测距函数
{
	float length=0,sum=0;
	u16 tim;
	uint i=0;
	/*测5次数据计算一次平均值*/
	while(i!=5)
	{
		PAout(11)=1; //拉高信号,作为触发信号
		delay_us(20); //高电平信号超过10us
		PAout(11)=0;
		/*等待回响信号*/
		while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_12)==RESET);
		TIM_Cmd(TIM4,ENABLE);//回响信号到来,开启定时器计数

		i+=1; //每收到一次回响信号+1,收到5次就计算均值
		while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_12)==SET);//回响信号消失
		TIM_Cmd(TIM4,DISABLE);//关闭定时器

		tim=TIM_GetCounter(TIM4);//获取计TIM4数寄存器中的计数值,一边计算回响信号时间

		length=(tim+overcount*1000)/58.0;//通过回响信号计算距离

		sum=length+sum;
		TIM4->CNT=0; //将TIM4计数寄存器的计数值清零
		overcount=0; //中断溢出次数清零
		delay_ms(10);
	}
	length=sum/5;
	return length;//距离作为函数返回值
}



void TIM4_IRQHandler(void) //中断,当回响信号很长是,计数值溢出后重复计数,用中断来保存溢出次数
{
	if(TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET)
	 {
	TIM_ClearITPendingBit(TIM4,TIM_IT_Update);//清除中断标志
	overcount++;

	 }
}

cs.h

#ifndef __CS_H
#define __CS_H 	

#include "stm32f10x.h"
#include "delay.h"

#include "sys.h"
#define uint unsigned int
#define TRIG_Send PBout(8)
#define ECHO_Reci PBin(9)

void CH_SR04_Init(void);  //超声波模块相关配置初始化
float Senor_Using(void);  //测距函数,返回值即为距离
void NVIC_Config(void);   //中断配置


#endif

避障主函数
注意因为我没用舵机,所以自己打算通过小车自身的转动来代替舵机,于是就有了这样奇怪的代码。

//头文件
#include "stm32f10x.h"
#include "moter.h"
#include "cs.h"
#include "xunji.h"  
#include "delay.h"
#include "sys.h"
#include "lanya.h"

 int main(void)
{	
	float  length_res[5];  //用来存放测距结果
	
	SystemInit();	// 配置系统时钟为72M 
    delay_init();    //延时初始化		
	xunji_config();   //循迹初始化
	TIM3_PWM_Init();	//电机pwm   TIM3
	CH_SR04_Init();  //超声波定时器    TIM4
	USART_Config();	//蓝牙串口
	
//避障循环	
		
while(1)
{
		length_res[0] =Senor_Using();  //测前方距离放在数组里
		delay_ms(100);
		
		if(length_res[0]>30.00)       //如果前方距离大于30cm  前进
			{
			CarGo();
			}	
				
		if(length_res[0]<30.00)     //如果前方距离小于30厘米  停车测左右距离
			{
			CarStop();
			delay_ms(100);
			CarRightAround();		//掉头
			delay_ms(1000);		
			CarStop();
			delay_ms(100);
			
			CarLeftAround();
			delay_ms(370);			//检测左边约45度的距离
			CarStop();
			delay_ms(100);	
			length_res[1] =Senor_Using();    //把测量结果放进数组
			
			CarRightAround();
			delay_ms(600);				//检测右边约45度的距离
			CarStop();
			delay_ms(100);		
         length_res[4] =Senor_Using();     //把测量结果放进数组				
				
			CarLeftAround();
			delay_ms(370);			//回正
			CarStop();
			delay_ms(100); 

				if(length_res[1]>length_res[4])    //如果左边的距离大于右边的距离
				{
					do                       
					{
					length_res[0] =Senor_Using();	//重复测前方的距离同时左转
					delay_ms(10);						
					CarLeft();
					delay_ms(100);						

					}
					while(length_res[0]<30.00);		//一直转到前方距离大于30cm		
				}
		   if(length_res[1]<length_res[4])    //如果右边的距离大于左边的距离
				{
					do
					{
					length_res[0] =Senor_Using();  //重复测前方的距离同时右转
					delay_ms(10);						
					CarRight();
					delay_ms(100);						
					}
					while(length_res[0]<30.00);		//一直转到前方距离大于30cm
				}
				
			}			
}
}

六、蓝牙遥控小车制作

1.模块介绍+接线

我用的时JDY-31,它与JDY-30非常像所以你们也可以看看这篇文章基于stm32蓝牙智能小车设计在这里插入图片描述
如图,JDY-31有六个脚我只用了这四个就可以实现蓝牙控制。
引脚说明
1 、 TXD 串口输出,接开发板上的UART-Rx
2 、 RXD 串口输入,接开发板上的UART-Tx
3、 GND接地
4、 VCC接3.6V-6V(我接了5V)

接线
RXD接PA9
TXD接PA10

3.蓝牙遥控小车程序

lanya.c

#include "lanya.h"


static void NVIC_Configuration(void)		//中断配置
{
     NVIC_InitTypeDef NVIC_InitStructure;
  
     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
     NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	  NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
}


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

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

//  USART1_TX   PA.9
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9
   
    //USART1_RX	  PA.10
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA10     
	
	    /* USARTx configured as follow:
       - BaudRate = 9600 baud  波特率
       - Word Length = 8 Bits  数据长度
       - One Stop Bit          停止位
       - No parity             校验方式
       - Hardware flow control disabled (RTS and CTS signals) 硬件控制流
       - Receive and transmit enabled                         使能发送和接收
    */

	
	// 配置串口的工作参数
	// 配置波特率
		USART_InitStructure.USART_BaudRate = 9600;
		USART_InitStructure.USART_WordLength = USART_WordLength_8b;
		USART_InitStructure.USART_StopBits = USART_StopBits_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);
	
	// 串口中断优先级配置
	NVIC_Configuration();
	
	// 使能串口接收中断
		USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断	
	// 使能串口
      USART_Cmd(USART1, ENABLE);                  
  // 清除发送完成标志
	//USART_ClearFlag(USART1, USART_FLAG_TC);     
}

//串口的中断服务函数
void USART1_IRQHandler(void)  
  
{  
     if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)      //检查指定的 USART1 中断发生与否
      { 
			USART_ClearITPendingBit(USART1, USART_IT_RXNE);   //清除 USART1 的中断待处理位


		  }
		  
}


lanya.h

#ifndef __LANYA_H
#define	__LANYA_H


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

void USART_Config(void);

#endif 

主函数

//头文件
#include "stm32f10x.h"
#include "moter.h"
#include "cs.h"
#include "xunji.h"  
#include "delay.h"
#include "sys.h"
#include "lanya.h"

u8 flag;  //定义一个蓝牙的标志位
int main(void)
{
	SystemInit();	// 配置系统时钟为72M 
    delay_init();    //延时初始化		
	xunji_config();   //循迹初始化
	TIM3_PWM_Init();	//电机pwm   TIM3
	CH_SR04_Init();  //超声波定时器    TIM4
	USART_Config();	//蓝牙串口
	
	  //蓝牙数据接收判断函数
	  while(1)
	  {
		  flag=  USART_ReceiveData(USART1);                    //返回 USART1 最近接收到的数据
		  switch(flag)
              {
					case '0':  CarStop();         break  ;
					case '1':  CarLeft();     break  ;
					case '2':  CarRight();    break  ;
					case '3':  CarBack();     break  ;
					case '4':  CarGo();    break  ;
					case '5':  CarLeftAround();   break  ;
					case '6':  CarRightAround();  break  ;
                    default: CarStop();         break  ;                                                                                                
	          }		  
	  }


}

4.蓝牙串口APP

注意这个app只能安卓手机使用
下载链接:蓝牙串口提取码:7v4v

APP设置介绍
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结

至此,制作智能小车的经历就记录和分享完了。
请记住:本文的智能小车的代码都只是为了实现每个模块能使用,所以这些代码只处于能用的水准。

基于stm32的智能小车作品(循迹避障蓝牙)(上)的链接:点击此处
工程文件的网盘链接:点击此处 提取码:pdqg

  • 27
    点赞
  • 199
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值