第一篇:STM32F103ZET6单片机双串口互发程序设计与实现
第二篇:最简单DIY基于STM32单片机的蓝牙智能小车设计方案
第三篇:最简单DIY基于STM32F407探索者开发板的MPU6050陀螺仪姿态控制舵机程序
第四篇:最简单DIY基于STM32F407探索者开发板和PCA9685舵机控制模块的红外遥控机械臂控制程序
第五篇:注释最详细、代码最简单的STM32+摄像头+显示屏的颜色跟踪电路软硬件方案
第六篇:最简单DIY基于STM32单片机的WIFI智能小车设计方案
daodanjishui物联网核心原创技术之最简单DIY基于STM32单片机的WIFI智能小车设计方案。
市面上有各种开源STM32+ESP8266-01S的无线WIFI控制小车,但是有复杂的有简单的,如果想快速入门STM32+ESP8266AT固件开发,这个方案会给你一个快捷高效的方案。
我记得本栏的第二篇博文:最简单DIY基于STM32单片机的蓝牙智能小车设计方案 的设计中大量使用了库函数和别人的开源代码,鲁迅先生的“拿来主义”表现的淋漓尽致,这也是STM32库函数开发的魅力所在,完成了串口蓝牙通信实现了无线蓝牙控制的小车。为了实现WIFI高速通信和物联网技术的融合,所以诞生第六篇博文。
这次的方案主要是:STM32F103C8T6单片机通过串口2发送AT指令控制ESP8266-1S与笔记本电脑的网络调试助手通信,从而实现用网络调试助手无线遥控单片机执行小车行进。下面请看全家福:
下图中,左上角的是串口WIFI看模块,右上角的是串口蓝牙模块,代码风格有一点变动,不过照样是同一个作者的劳动成果。
网络调试助手控制小车的指令收发如下:
单片机串口1打印调试信息如下图。(使用到本栏第一篇原创串口互发技术)
优酷视频演示地址:https://v.youku.com/v_show/id_XNTE2NTg5OTM2MA==.html
最简单DIY基于STM32单片机的WIFI智能小车设计方案
采用双层透明亚克力板结构,使用带有数码管显示的电源,带有独立开关的L298N模块,一片STM32F103C8T6作为主控,两个18650高能锂电池供电,一个ESP8266-01S串口WIFI模块,三根铜柱把第二层的亚克力板撑起来了,整个小车结构都由我手工设计和搭建,看起来就像是一个艺术品。这次的小车功能拓展提高了很多,首先支持三个串口同时使用,我定义串口一作为串口调试使用,串口二作为与ESP8266进行通信使用,串口三留给买家自行扩展,需要注意的是:stm32触发串口中断需要加入 \r\n,串口2是与ESP8266模块链接的,stm32的串口2中断必须接收到\r\n 才能触发串口中断,十六进制就是 0d 0a,串口2收到的数据会通过串口1输出到电脑串口调试助手,这样用串口1可以调试程序,看看串口2的WIFI模块是否接收到数据另外给串口1发送数据的话,串口1会返回相同的数据,同时串口1也往串口2发送数据,这样也可以测试WIFI模块是否能回复给电脑网络调试助手服务器。
根据上面两个截图的
连接说明:串口1作为调试打印输出,可以不接
串口2作为ESP8266-01S与STM32F103C8T6通信的接口,必须接入
所以STM32 的PA2作为TX端 连接8266的RX端
所以STM32 的PA3作为RX端 连接8266的TX端
ESP8266必须与STM32共地,ESP8266模块供电3.3V
ESP8266的EN接3.3V
ESP8266的RST、IO0、IO2都不需要接线
STM32的 PA4 接L298N的第一个管脚PIN0
STM32的 PA5 接L298N的第一个管脚PIN1
STM32的 PA6 接L298N的第一个管脚PIN2
STM32的 PA7 接L298N的第一个管脚PIN3
或者是(不同的L298N模块的编号可能不一样)
STM32的 PA4 接L298N的第一个管脚PIN1
STM32的 PA5 接L298N的第一个管脚PIN2
STM32的 PA6 接L298N的第一个管脚PIN3
STM32的 PA7 接L298N的第一个管脚PIN4
代码都是daodanjishui原创开源和亲自测试验证,保证了代码精简易懂,适合快速入门上手二次开发,核心技术知识点足够多。为了这个作品,曾经的我把正点原子开源论坛关于ESP8266的帖子都看遍了!但是后面我上手SDK开发了,这电路是我对以前走的弯路进行一次致敬!
为了发布小车开源方案,daodanjishui疯狂闭门造车,每一个开源方案就造一部车,就有点像钢铁侠那样疯狂,一个成年人造这种车,要么是想挣钱,要么就是想玩。每次造车我都会用新的模块去搭建,因为实在不想去拆解重装了,还有一个原因就是:总有一天我会像钢铁侠电影那样,用一个眼镜或者是头盔去同时集群控制这些玩意儿。这些小车的构造和程序都比较简单,尽量不要涉及到过于复杂的编码,但是又要体现出万物互联的精髓。一个人不管做什么事情,只要不断重复做成一个体系那么就容易成功。
说说这次电路的功能和特点:这次用网络调试助手作为服务器控制WIFI智能小车,所以需要组建一个局域网,再也不用以前AP热点的模式了,因为用STA模式,小车具有的功能更加容易扩展,后期我要加上WebSocket技术实现集群控制的,现在是在酝酿一个大招。代码的风格沿用MDK5串口互发的基本框架,这个框架以前我作为免费开源的资料上传电路城。最简单DIY基于STM32单片机的蓝牙智能小车设计方案 用的是串口1和2互发进行调试,这次也不例外,不过这次代码复杂了很多,虽然也是用串口1和串口2,但是串口2控制ESP8266的程序移植和改进了正点原子的源码,可以完美实现断线重连服务器,摒弃了显示屏的优点,还有心跳程序检测连接的功能。特别是在心跳程序的地方 详细注释了如何使用定时器来检测WIFI传输过程中出现问题的逻辑处理。WIFI开发采用了串口AT指令控制,这也是正点原子刚开始出WIFI教程时候的方式,虽然现在广泛用Arduino 的ESP8266集成开发环境来开发,但是这个源码是非常值得学习的,因为涉及到非常多的知识点。小车控制使用网络调试助手指令去触发小车运动,这样更加直观看到调试信息和减少买家掌握这个电路的难度。利用串口1的打印功能,读者很容易掌握着代码的精髓。
为了快速掌握读者STM32串口通信,最后附上STM32串口库函数源码免费下载链接。
代码如下(示例):
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "usart2.h"
//串口实验
//技术支持:daodanjishui
int main(void)
{
u8 t;
u8 len;
u8 len2;
delay_init(); //延时函数初始化
NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(9600); //串口初始化为9600
uart2_init(9600);
//LED_Init(); //LED端口初始化
//KEY_Init(); //初始化与按键连接的硬件接口
while(1)
{
if(USART_RX_STA&0x8000)
{
len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
/* //因为我这里要把气象站的数据传回来,所以不能直接返回数据给气象站,否则可能出错
printf("电脑 send to串口1的数据为:\r\n");
for(t=0;t
u2_printf("电脑 send to串口2的数据为:\r\n");
for(t=0;t<len;t++)
{
USART_SendData(USART2, USART_RX_BUF[t]);//将串口1收到的数据转发给串口2输出
while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET);//等待发送结束
}
u2_printf("\r\n");//插入换行
USART_RX_STA=0;
}
if(USART2_RX_STA&0x8000)
{
len2=USART2_RX_STA&0x3fff;//得到此次接收到的数据长度
u2_printf("电脑 send to串口2的数据为:\r\n");
for(t=0;t<len2;t++)
{
USART_SendData(USART2, USART2_RX_BUF[t]);//单片机通过串口2给电脑发数据
while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET);//等待发送结束
}
u2_printf("\r\n");//插入换行
//printf("电脑 send to串口1的数据为:\r\n");
printf("\r\n");//作为指令响应的开头
for(t=0;t<len2;t++)
{
USART_SendData(USART1, USART2_RX_BUF[t]);//将串口2收到的数据转发给串口1输出
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
}
printf("\r\n");//插入换行
USART2_RX_STA=0;
}
}
}
先看看代码截图:
代码修改的地方如下:
工程目录如下:
重点编写串口2中断处理程序(这里说明一下,跟本栏的蓝牙控制小车的代码和控制风格差不多):
if(USART2_RX_STA&0X8000) //接收到一次数据了
{
rlen=USART2_RX_STA&0X7FFF; //得到本次接收到的数据长度
USART2_RX_BUF[rlen]=0; //添加结束符
//printf("%s",USART2_RX_BUF); //发送到串口
printf("收到%d字节,内容如下\r\n",rlen);
printf("---%s\r\n",USART2_RX_BUF);
//sprintf((char*)p,"收到%d字节,内容如下",rlen);//接收到的字节数
//在这里写控制小车的逻辑
if(strstr((const char*)USART2_RX_BUF,"FFF")!=NULL){
flag=0;
}else if(strstr((const char*)USART2_RX_BUF,"BBB")!=NULL){
flag=1;
}else if(strstr((const char*)USART2_RX_BUF,"LLL")!=NULL){
flag=2;
}else if(strstr((const char*)USART2_RX_BUF,"RRR")!=NULL){
flag=3;
}else if(strstr((const char*)USART2_RX_BUF,"SSS")!=NULL){
flag=4;
}else flag=4;
switch (flag)
{
case 0: {
front();
printf("FFF\r\n");
//测试发送一个字符串
sprintf((char*)p,"FFF\r\n");
u2_printf("AT+CIPSEND=0,%d\r\n",strlen((char*)p));//发送数据的AT指令,先写指令后发送数据
delay_ms(200);
atk_8266_send_data(p,"OK",100); //发送指定长度的数据
break;
}//串口收到前进
case 1: {
back();
printf("BBB\r\n");
//测试发送一个字符串
sprintf((char*)p,"BBB\r\n");
u2_printf("AT+CIPSEND=0,%d\r\n",strlen((char*)p));//发送数据的AT指令,先写指令后发送数据
delay_ms(200);
atk_8266_send_data(p,"OK",100); //发送指定长度的数据
break;
}
case 2: {
left();
printf("LLL\r\n");
//测试发送一个字符串
sprintf((char*)p,"LLL\n");
u2_printf("AT+CIPSEND=0,%d\r\n",strlen((char*)p));//发送数据的AT指令,先写指令后发送数据
delay_ms(200);
atk_8266_send_data(p,"OK",100); //发送指定长度的数据
break;
}
case 3: {
right();
printf("RRR\r\n");
//测试发送一个字符串
sprintf((char*)p,"RRR\r\n");
u2_printf("AT+CIPSEND=0,%d\r\n",strlen((char*)p));//发送数据的AT指令,先写指令后发送数据
delay_ms(200);
atk_8266_send_data(p,"OK",100); //发送指定长度的数据
break;
}
case 4: {
stop();
printf("SSS\r\n");
//测试发送一个字符串
sprintf((char*)p,"SSS\r\n");
u2_printf("AT+CIPSEND=0,%d\r\n",strlen((char*)p));//发送数据的AT指令,先写指令后发送数据
delay_ms(200);
atk_8266_send_data(p,"OK",100); //发送指定长度的数据
break;
}
default:{
stop();
printf("SSS\r\n");
//测试发送一个字符串
sprintf((char*)p,"SSS\r\n");
u2_printf("AT+CIPSEND=0,%d\r\n",strlen((char*)p));//发送数据的AT指令,先写指令后发送数据
delay_ms(200);
atk_8266_send_data(p,"OK",100); //发送指定长度的数据
break;
}
}
//车控制结束
USART2_RX_STA=0;
//receive_flag=1;
//if(constate!='+')t=1000; //状态为还未连接,立即更新连接状态
//if(constate!='+')t=300; //状态为还未连接,立即更新连接状态
//if(constate!='+')t=3; //状态为还未连接,立即更新连接状态
if(constate!='+')t=10; //状态为还未连接,立即更新连接状态
else t=0; //状态为已经连接了,10秒后再检查
}
说明:以上就是我关键的代码,根据工程代码截图来看,代码量大,另外也请读者尊重原创,编写源码也花了不少的宝贵的时间的,尊重劳动成果,请下载我最后附录上的工程代码,工程代码注释详细,代码精简。
(2)电脑打开一个网络调试助手,并且提前创建一个局域网热点,保证让小车和电脑都能连上。如下:
(3)修改MDK网络连接的参数编译代码烧录代码:服务器的IP地址根据网络调试助手生成的填写,端口号写死为8080,热点名称和密码跟买家实际的参数修改
(4)打开串口调试助手调试小车的串口1,上电看看串口调试打印信息:
(5)看到连上服务器之后,在服务器发送一个指令:FFF 注意要发送换行回车\r\n作为结束符号,代码就是这样识别指令传输结束的。
(6)拔掉串口1调试线,小车下地测试远程遥控。FFF前进,BBB后退,LLL左转,RRR右转,SSS停止。读者可以亲自测试,都是简单的指令,很好入门的。
根据上面的调试与仿真,证明了该设计满足了博文提出的要求。
总结:用ESP8266AT指令来连接服务器有一个好处是可以让STM32做控制算法的处理,如果用ESP8266做通信又做算法处理,那么可能导致性能发挥有限。虽然ESP8266与STM32直接采用串口2相连速度有点慢,但是好处就是稳定,ESP8266跑的是网络协议栈,STM32跑的是裸机程序,相互配合,程序相当稳定。做物联网控制的买家可以很好参考我这个代码来改造成智能WIFI插座、WIFI机器人、智能家居等等,如果你自己想自己去写这种基础性代码,你会发现困难重重一点小问题就能困住你一整天,如果用我搭好的环境去开发将会事半功倍,可能全网还真找不到像我这样WIFI智能小车的程序。
下个智能小车专题,我会加入手机上位机和网页上位机或者C# 上位机实现一些方便快捷的控制,再也不用网络助手或者是串口调试助手去控制小车了。原创开源值得期待。
最后附上本博文代码下载地址:https://www.cirmall.com/circuit/24707/
直接跳转
STM32串口库函数源码相关代码免费下载:https://www.cirmall.com/circuit/19782/
直接跳转