一、环境介绍
小车主控MCU: STM32F103ZET6
STM32程序开发IDE: keil5
STM32程序风格: 采用寄存器方式开发,注释齐全,执行效率高,方便移植
手机APP: 采用QT设计,程序支持跨平台编译运行(Android、IOS、Windows、Linux都可以编译运行,对应平台上QT的环境搭建,之前博客已经发了文章讲解)
硬件包含: 淘宝购买的完整一套4轮遥控小车(采用STM32F103ZET6作为主控板)、DHT11温湿度传感器、中科微GPS模块、ESP8266
小车完整源码下载地址:https://download.csdn.net/download/xiaolong1126626497/19557040
APP完整源码下载地址: https://download.csdn.net/download/xiaolong1126626497/19557009
二、功能介绍
这是基于STM32设计的4轮遥控小车,支持通过Android手机APP、Windows上位机完成对小车遥控;支持前进、后退、左转、右转、停止等操作。
小车上会实时采集温度、湿度、GPS经纬度、通过ESP8266 WIFI上传至手机APP,手机APP收到数据之后,会将温湿度实时显示出来,经纬度收到后会调用百度地图,显示小车的位置,并且数据也会存放到数据库里,方便查看历史数据;支持范围内温湿度查询、最高温湿度、最低温湿度查询。
小车电机驱动模块采用L298N、WIFI模块采用ESP8266、MCU采用STM32F103C8T6、温湿度模块采用DTH11、GPS模块采用北斗GPS+BDS。
三、相关硬件介绍
四、程序源码
硬件连接说明: GPS接的串口1: PA3(RX) –5V~3.3VWIFI接的串口3: PB10(TX)—>接ESP8266的RX PB11(RX)—>接ESP8266的TX –3.3VDHT11温湿度接: PA7
4.1 STM32小车端: main.c源码
#include \"stm32f10x.h\"#include \"led.h\"#include \"delay.h\"#include \"key.h\"#include \"usart.h\"#include #include \"timer.h\"#include \"bluetooth.h\"#include \"esp8266.h\"#include \"dht11.h\"#include \"gps.h\"#include \"motor.h\"/*硬件连接说明: GPS接的串口1: PA3(RX) --5V~3.3VWIFI接的串口3: PB10(TX)--->接ESP8266的RX PB11(RX)--->接ESP8266的TX --3.3VDHT11温湿度接: PA7 */u8 ESP8266_SendBuff[50];char Buffer[1024];int main(){ u32 time_cnt=0; double Longitude=120.086199; double latitude=30.139219; u8 temp=20; u8 humi=70; //延时2秒保证系统稳定 delay_ms(1000); delay_ms(1000); LED_Init(); BEEP_Init(); USART1_Init(115200); //串口调试 USART2_Init(9600); //接GPS模块 TIMER2_Init(72,20000); USART3_Init(115200); //串口-WIFI ESP8166_01默认波特率9600 ESP8266_12F默认波特率115200 TIMER3_Init(72,20000); //超时时间20ms printf(\"正在初始化请稍等.\\r\\n\"); printf(\"DHT11_Init:%d\\r\\n\",DHT11_Init());//温湿度传感器初始化 printf(\"准备检测WIFI硬件,请稍等...\\r\\n\"); //初始化WIFI硬件 if(ESP8266_Init())printf(\"WIFI硬件错误.\\r\\n\"); else { printf(\"WIFI设备正常....\\r\\n\"); //配置WIFI的模式 192.168.4.1 printf(\"WIFI配置状态:%d\\r\\n\",ESP8266_AP_TCP_Server_Mode(\"esp8266_666\",\"12345678\",8089)); } MotorInit(); //电机初始化 //电机脉冲控制 TIMER4_Init(72,1000); while(1) { //接收到GPS的数据 if(USART2_RX_FLAG) { USART2_RX_BUFFER[USART2_RX_CNT]=\'\\0\'; //解析经纬度 GPS_GNRMC_Decoding((char*)USART2_RX_BUFFER,&Longitude,&latitude); USART2_RX_CNT=0; USART2_RX_FLAG=0; //打印到串口调试助手 printf(\"GPS:%f,%f\\r\\n\",Longitude,latitude); } //接收到WIFI的数据 if(USART3_RX_FLAG) { USART3_RX_BUFFER[USART3_RX_CNT]=\'\\0\'; printf(\"WIFI:%s\\r\\n\",USART3_RX_BUFFER); strcpy(Buffer,(char*)USART3_RX_BUFFER); USART3_RX_CNT=0; USART3_RX_FLAG=0; BEEP=1; delay_ms(50); BEEP=0; if(strstr((char*)Buffer,\":a\")) { printf(\"向前...\\r\\n\"); CarGo(); } else if(strstr((char*)Buffer,\":b\")) { printf(\"后退...\\r\\n\"); CarBack(); } else if(strstr((char*)Buffer,\":c\")) { printf(\"向左...\\r\\n\"); CarLeft(); } else if(strstr((char*)Buffer,\":d\")) { printf(\"向右...\\r\\n\"); CarRight(); } else if(strstr((char*)Buffer,\":e\")) { printf(\"停止...\\r\\n\"); CarStop(); } } time_cnt++; delay_ms(10); //判断轮询时间 if(time_cnt>=100*2) { time_cnt=0; //读取温湿度数据 DHT11_Read_Data(&temp,&humi); sprintf((char*)ESP8266_SendBuff,\"#%d,%d,%f,%f\",temp,humi,Longitude,latitude); //向服务器上传数据 ESP8266_ServerSendData(0,ESP8266_SendBuff,strlen((char*)ESP8266_SendBuff)); //打印到串口调试助手 printf(\"ESP8266_SendBuff:%s\\r\\n\",(char *)ESP8266_SendBuff); //运行状态 Motor_LED=!Motor_LED; } }}
4.2 STM32小车端: 电机控制源码
#include \"motor.h\"//全局变量定义unsigned int speed_count=0;//占空比计数器 50次一周期int front_left_speed_duty=SPEED_DUTY;int front_right_speed_duty=SPEED_DUTY;int behind_left_speed_duty=SPEED_DUTY;int behind_right_speed_duty=SPEED_DUTY;unsigned char continue_time=0;//根据占空比驱动电机转动void CarMove(void){ BEHIND_RIGHT_EN;//右前轮if(front_right_speed_duty > 0)//向前{if(speed_count < front_right_speed_duty){FRONT_RIGHT_GO;}else //停止{FRONT_RIGHT_STOP;}}else if(front_right_speed_duty < 0)//向后{if(speed_count 0)//向前{if(speed_count < behind_left_speed_duty){BEHIND_LEFT_GO;}else //停止{BEHIND_LEFT_STOP;}}else if(behind_left_speed_duty < 0)//向后{if(speed_count APB2ENR|=1<APB2ENR|=1<APB2ENR|=1<CRH&=0xFF0F0F0F; GPIOG->CRH|=0x00303030; GPIOD->CRL&=0xF0F0F0F0; GPIOD->CRL|=0x03030303; GPIOC->CRH&=0xFFFF0FFF; GPIOC->CRH|=0x00003000; CarStop();}
4.3 STM32小车端: ESP8266 WIFI源码
#include \"esp8266.h\"u8 ESP8266_IP_ADDR[16]; //255.255.255.255u8 ESP8266_MAC_ADDR[18]; //硬件地址/*函数功能: ESP8266命令发送函数函数返回值:0表示成功 1表示失败*/u8 ESP8266_SendCmd(char *cmd){ u8 i,j; for(i=0;i<10;i++) //检测的次数--发送指令的次数 { USART3_RX_FLAG=0; USART3_RX_CNT=0; USARTx_StringSend(USART3,cmd); delay_ms(200); if(USART3_RX_FLAG) { USART3_RX_BUFFER[USART3_RX_CNT]=\'\\0\'; USART3_RX_FLAG=0; USART3_RX_CNT=0; if(strstr((char*)USART3_RX_BUFFER,\"OK\")) { return 0; } } } return 1;}/*函数功能: ESP8266硬件初始化检测函数函数返回值:0表示成功 1表示失败*/u8 ESP8266_Init(void){ ESP8266_SendCmd(\"+++\"); delay_ms(200); ESP8266_SendCmd(\"+++\"); delay_ms(200); return ESP8266_SendCmd(\"AT\\r\\n\");}/*函数功能: 一键配置WIFI为AP+TCP服务器模式函数参数:char *ssid 创建的热点名称char *pass 创建的热点密码 (最少8位)u16 port 创建的服务器端口号函数返回值: 0表示成功 其他值表示对应错误值*/u8 ESP8266_AP_TCP_Server_Mode(char *ssid,char *pass,u16 port){ char *p; u8 i; char tmp_buff[100]; /*1. 测试硬件*/ if(ESP8266_SendCmd(\"AT\\r\\n\"))return 1; /*2. 关闭回显*/ if(ESP8266_SendCmd(\"ATE0\\r\\n\"))return 2; /*3. 设置WIFI模式*/ if(ESP8266_SendCmd(\"AT+CWMODE=2\\r\\n\"))return 3; /*4. 复位*/ ESP8266_SendCmd(\"AT+RST\\r\\n\"); delay_ms(1000); delay_ms(1000); delay_ms(1000); /*5. 关闭回显*/ if(ESP8266_SendCmd(\"ATE0\\r\\n\"))return 5; /*6. 设置WIFI的AP模式参数*/ sprintf(tmp_buff,\"AT+CWSAP=\\\"%s\\\",\\\"%s\\\",1,4\\r\\n\",ssid,pass); if(ESP8266_SendCmd(tmp_buff))return 6; /*7. 开启多连接*/ if(ESP8266_SendCmd(\"AT+CIPMUX=1\\r\\n\"))return 7; /*8. 设置服务器端口号*/ sprintf(tmp_buff,\"AT+CIPSERVER=1,%d\\r\\n\",port); if(ESP8266_SendCmd(tmp_buff))return 8; /*9. 查询本地IP地址*/ if(ESP8266_SendCmd(\"AT+CIFSR\\r\\n\"))return 9; //提取IP地址 p=strstr((char*)USART3_RX_BUFFER,\"APIP\"); if(p) { p+=6; for(i=0;*p!=\'\"\';i++) { ESP8266_IP_ADDR[i]=*p++; } ESP8266_IP_ADDR[i]=\'\\0\'; } //提取MAC地址 p=strstr((char*)USART3_RX_BUFFER,\"APMAC\"); if(p) { p+=7; for(i=0;*p!=\'\"\';i++) { ESP8266_MAC_ADDR[i]=*p++; } ESP8266_MAC_ADDR[i]=\'\\0\'; } //打印总体信息 printf(\"当前WIFI模式:AP+TCP服务器\\n\"); printf(\"当前WIFI热点名称:%s\\n\",ssid); printf(\"当前WIFI热点密码:%s\\n\",pass); printf(\"当前TCP服务器端口号:%d\\n\",port); printf(\"当前TCP服务器IP地址:%s\\n\",ESP8266_IP_ADDR); printf(\"当前TCP服务器MAC地址:%s\\n\",ESP8266_MAC_ADDR); return 0;}/*函数功能: TCP服务器模式下的发送函数发送指令: */u8 ESP8266_ServerSendData(u8 id,u8 *data,u16 len){ u8 i,j,n; char ESP8266_SendCMD[100]; //组合发送过程中的命令 for(i=0;i\")) { //继续发送数据 USARTx_DataSend(USART3,data,len); //等待数据发送成功 delay_ms(200); if(USART3_RX_FLAG) { USART3_RX_BUFFER[USART3_RX_CNT]=\'\\0\'; USART3_RX_FLAG=0; USART3_RX_CNT=0; if(strstr((char*)USART3_RX_BUFFER,\"SEND OK\")) { return 0; } } } } } return 1;}
4.4 QT软件端代码布局
<!–