基于STM32单片机的汽车防撞与控制系统 - 嵌入式 物联网(含代码)

2023-10-25 11:58 浏览 1726人

基于STM32单片机的汽车防撞与控制系统

  • 难度系数:4分
  • 工作量:4分
  • 创新点:3分

1 简介

基于单片机的汽车防撞与控制系统设计

2 主要器件

  • STM32F103C8T6主控芯片
  • HC-SR04超声波模块
  • 光敏传感器
  • ESP-01S WIFI模块
  • 蜂鸣器
  • OLED屏
  • 红外传感器模块

3 实现效果

前后有两个HC-SR04超声波模块,可以检测车前和车后是否有障碍物,实验中拿手机挡住前面的超声波模块,蜂鸣器会报警。

红外感应模块可检测车前是否有人,当红外感应模块前面有障碍是,显示屏上由N->Y,代表检测到人。

显示屏上显示超声波模块探测距离

4 设计原理

4.1HC-SR04超声波模块

简介

HC-SR04超声波模块常用于机器人避障、物体测距、液位检测、公共安防、停车场检测等场所。HC-SR04超声波模块主要是由两个通用的压电陶瓷超声传感器,并加外围信号处理电路构成的。如图:

两个压电陶瓷超声传感器,一个用于发出超声波信号,一个用于接收反射回来的超声波信号。由于发出信号和接收信号都比较微弱,所以需要通过外围信号放大器提高发出信号的功率,和将反射回来信号进行放大,以能更稳定地将信号传输给单片机。模块整体电路如图:

模块参数

(1)模块主要电气参数

  • 使用电压:DC—5V
  • 静态电流:小于2mA
  • 电平输出:高5V
  • 电平输出:底0V
  • 感应角度:不大于15度
  • 探测距离:2cm-450cm
  • 高精度 可达0.2cm

(2)模块引脚
超声波模块有4个引脚,分别为Vcc、 Trig(控制端)、 Echo(接收端)、 GND;其中VCC、GND接上5V电源, Trig(控制端)控制发出的超声波信号,Echo(接收端)接收反射回来的超声波信号。模块如图

4.2 ESP-01S WIFI模块

简介

ESP8266 系列模组是深圳市安信可科技有限公司开发的一系列基于乐鑫ESP8266的低功耗UART-WiFi芯片模组,可以方便地进行二次开发,接入云端服务,实现手机3/4G全球随时随地的控制,加速产品原型设计。

尺寸、管脚定义

ESP8266的指令介绍

AT指令可以细分四种类型:
1.测试指令:AT+=?
该命令用于查询设置指令的参数以及取值的范围

2.查询指令:AT+?
该命令用于返回参数的当前值

3.设置指令:AT+=<’’’>
该命令用于设置用户自定义的参数

4.执行指令:AT+
该命令用于执行受模块内部程序控制的变参数不可变的功能

ESP8266的指令测试
可以通过STM开发板转为电平转换的功能连接上ESP8266模块在通过串口显示窗口在PC机上热输入AT指令来进行操作。

ESP8266的AT指令一览

4.3 光照传感器

简介
光敏传感器是最常见的传感器之一,它的种类繁多,主要有:光电管、光电倍增管、光敏电阻、光敏三极管、太阳能电池、红外线传感器、紫外线传感器、光纤式光电传感器、色彩传感器、CCD和CMOS图像传感器等。光传感器是目前产量最多、应用最广的传感器之一,它在自动控制和非电量电测技术中占有非常重要的地位。光敏传感器是利用光敏元件将光信号转换为电信号的传感器,它的敏感波长在可见光波长附近,包括红外线波长和紫外线波长。光传感器不只局限于对光的探测,它还可以作为探测元件组成其他传感器,对许多非电量进行检测,只要将这些非电量转换为光信号的变化即可。
总结:照射光敏二极管的光强不同,通过光敏二极管的电流大小就不同,所以可以通过检测电流大小,达到检测光强的目的。利用这个电流变化,我们串接一个电阻,就可以转换成电压的变化,从而通过ADC读取电压值,判断外部光线的弱。

优点

  • 采用灵敏型光敏电阻传感器
  • 比较器输出,信号干净,波形好,驱动能力超过15mA。
  • 配可调电位器可调节检测光线亮度
  • 工作电压3.3V-5V
  • 输出形式 :数字开关量输出(0和1)
  • 设有固定螺栓孔,方便安装

原理图

5 部分核心代码

//hc_sr04.c源文件: #include"stm32f10x.h" #include"hc_sr04.h" #include"stdio.h" //hc_sr04引脚初始化 void HC_SR04_Init(void)//初始化hc_sro4的连接引脚 {
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启GPIOB时钟 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;//将hc_sr04的Trig引脚连接到单片机的PB5引脚上,单片机给HC_SR04提供至少10us的脉冲 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;//将hc_sr04的Echo引脚连接到单片机的PB6引脚上,HC_SR04反馈高电平信号给单片机 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
} //通用定时器Tim2初始化 void Time2_Init(u32 Period , u32 Prescaler) {
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//开启定时器TIM2的时钟 TIM_TimeBaseStructure.TIM_Period = Period;//自动重装载寄存器的值 TIM_TimeBaseStructure.TIM_Prescaler = Prescaler;//时钟预分频数 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//采样分频 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数 TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
	TIM_ClearFlag(TIM2,TIM_FLAG_Update);//清除溢出中断标志位 TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//TIM2中断使能 //	TIM_Cmd(TIM2,ENABLE);//使能定时器Tim2  } //NVIC配置 void NVIC_Config(void) {
	NVIC_InitTypeDef NVIC_InitStructure;
	
	NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;//中断通道号配置为TIM2 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//无占先优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//无副优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//中断使能 NVIC_Init(&NVIC_InitStructure);//NVIC初始化 } //给hc_sr04一个启动信号 void hc_sr04_start(void) {
	Trig=1;
	delay_us(20);
	Trig=0;
} //计算hc_sr04测出来的值 void hc_sr04_calculate(void) { float temp; while(Echo==1);
	hc_sr04_start();//启动hc_sr04超声波传感器 while(Echo==0); printf("收到20us的脉冲,开始发送8个40KHz的方波信号!\r\n");
	delay_ms(500); printf("hc_sr04正在开始测距.......\r\n");
	TIM_SetCounter(TIM2,0);//清空计数器 TIM_Cmd(TIM2,ENABLE);//开启定时器 while(Echo==1);//如果hc_sr04返回低电平说明还未检测到前面有障碍物,就一直执行该程序 TIM_Cmd(TIM2,DISABLE);//停止计数 temp=TIM_GetCounter(TIM2)*340/(2*1000); printf("距离:%6.2fm\n",temp);
} //hc_sr04.h头文件: #ifndef _HC_SRO4_H #define _HC_SR04_H #include "stm32f10x.h" #include "delay.h" #define Trig PBin(5) #define Echo PBout(6) void HC_SR04_Init(void); void Time2_Init(u32 Period , u32 Prescaler); void NVIC_Config(void); void hc_sr04_start(void); void hc_sr04_calculate(void); void delay_init(); void uart_init(u32 bound); #endif 
//wifi模块部分 #include "esp8266.h" #include "string.h" #include "usart.h" #include "usart3.h" #include "stm32f10x.h" #include "sys.h"  #include "delay.h" //ESP8266模块和PC进入透传模式 void esp8266_start_trans(void) { //设置工作模式 1:station模式   2:AP模式  3:兼容 AP+station模式 esp8266_send_cmd("AT+CWMODE=1","OK",50); //让Wifi模块重启的命令 esp8266_send_cmd("AT+RST","ready",20);
	
	delay_ms(1000); //延时3S等待重启成功 delay_ms(1000);
	delay_ms(1000);
	delay_ms(1000); //让模块连接上自己的路由 while(esp8266_send_cmd("AT+CWJAP=\"111\",\"11111111\"","WIFI GOT IP",600)); //=0:单路连接模式     =1:多路连接模式 esp8266_send_cmd("AT+CIPMUX=0","OK",20); //建立TCP连接  这四项分别代表了 要连接的ID号0~4   连接类型  远程服务器IP地址   远程服务器端口号 while(esp8266_send_cmd("AT+CIPSTART=\"TCP\",\"xxx.xxx.xxx.xxx\",xxxx","CONNECT",200)); //是否开启透传模式  0:表示关闭 1:表示开启透传 esp8266_send_cmd("AT+CIPMODE=1","OK",200); //透传模式下 开始发送数据的指令 这个指令之后就可以直接发数据了 esp8266_send_cmd("AT+CIPSEND","OK",50);
} //ESP8266退出透传模式   返回值:0,退出成功;1,退出失败 //配置wifi模块,通过想wifi模块连续发送3个+(每个+号之间 超过10ms,这样认为是连续三次发送+) u8 esp8266_quit_trans(void) {
	u8 result=1;
	u3_printf("+++");
	delay_ms(1000); //等待500ms太少 要1000ms才可以退出 result=esp8266_send_cmd("AT","OK",20);//退出透传判断. if(result) printf("quit_trans failed!"); else printf("quit_trans success!"); return result;
} //向ESP8266发送命令 //cmd:发送的命令字符串;ack:期待的应答结果,如果为空,则表示不需要等待应答;waittime:等待时间(单位:10ms) //返回值:0,发送成功(得到了期待的应答结果);1,发送失败 u8 esp8266_send_cmd(u8 *cmd,u8 *ack,u16 waittime) {
	u8 res=0; 
	USART3_RX_STA=0;
	u3_printf("%s\r\n",cmd); //发送命令 if(ack&&waittime) //需要等待应答 { while(--waittime) //等待倒计时 {
			delay_ms(10); if(USART3_RX_STA&0X8000)//接收到期待的应答结果 { if(esp8266_check_cmd(ack))
				{ printf("ack:%s\r\n",(u8*)ack); break;//得到有效数据  }
					USART3_RX_STA=0;
			} 
		} if(waittime==0)res=1; 
	} return res;
} //ESP8266发送命令后,检测接收到的应答 //str:期待的应答结果 //返回值:0,没有得到期待的应答结果;其他,期待应答结果的位置(str的位置) u8* esp8266_check_cmd(u8 *str) { char *strx=0; if(USART3_RX_STA&0X8000) //接收到一次数据了 { 
		USART3_RX_BUF[USART3_RX_STA&0X7FFF]=0;//添加结束符 strx=strstr((const char*)USART3_RX_BUF,(const char*)str);
	} return (u8*)strx;
} //向ESP8266发送数据 //cmd:发送的命令字符串;waittime:等待时间(单位:10ms) //返回值:发送数据后,服务器的返回验证码 u8* esp8266_send_data(u8 *cmd,u16 waittime) { char temp[5]; char *ack=temp;
	USART3_RX_STA=0;
	u3_printf("%s",cmd); //发送命令 if(waittime) //需要等待应答 { while(--waittime) //等待倒计时 {
			delay_ms(10); if(USART3_RX_STA&0X8000)//接收到期待的应答结果 {
				USART3_RX_BUF[USART3_RX_STA&0X7FFF]=0;//添加结束符 ack=(char*)USART3_RX_BUF; printf("ack:%s\r\n",(u8*)ack);
				USART3_RX_STA=0; break;//得到有效数据  } 
		}
	} return (u8*)ack;
} 

完整代码可进群免费领取。

嵌入式物联网的学习之路非常漫长,不少人因为学习路线不对或者学习内容不够专业而错失高薪offer。不过别担心,我为大家整理了一份150多G的学习资源,基本上涵盖了嵌入式物联网学习的所有内容。点击下方链接,0元领取学习资源,让你的学习之路更加顺畅!记得点赞、关注、收藏、转发哦!

点击这里找小助理0元领取:扫码进群领资料