admin管理员组文章数量:1530913
无线通讯(WIFI模块)
ESP8266系列模组
ESP8266 系列模组是深圳市安信可科技有限公司开发的一系列基于乐鑫ESP8266EX的低功耗UART-WiFi芯片模组,可以方便地进行二次开发,接入云端服务,实现手机3/4G全球随时随地的控制,加速产品原型设计。
模块核心处理器 ESP8266 在较小尺寸封装中集成了业界领先的 Tensilica L106 超低功耗 32 位微型 MCU,带有 16 位精简模式,主频支持 80 MHz 和 160 MHz,支持 RTOS,集成 Wi-Fi MAC/ BB/RF/PA/LNA,板载天线。支持标准的 IEEE802.11 b/g/n 协议,完整的 TCP/IP 协议栈。用户可以使用该模块为现有的设备添加联网功能,也可以构建独立的网络控制器。
ESP8266 是高性能无线 SoC,以最低成本提供最大实用性,为 Wi-Fi 功能嵌入其他系统提供无限可能。
SoC称为系统级芯片,也有称片上系统,意指它是一个产品,是一个有专用目标的集成电路,其中包含完整系统并有嵌入软件的全部内容。同时它又是一种技术,用以实现从确定系统功能开始,到软/硬件划分,并完成设计的整个过程
ESP-12S
开发板上的WIFI模块使用的是安信可公司的ESP-12S型号
WIFI模块的规格书可以在安信可官网上找到
乐鑫和安信可
乐鑫和安信可的关系,其实大可理解为ARM与ST、NXP的关系,ARM负责设计CPU内核,然后将设计授权给ST、NXP这些芯片厂商,芯片厂商在内核之上添加必要的外设和自己家有特色的外设,就可以生产我们每天都用的MCU了。
乐鑫是芯片原厂,在研制ESP系列芯片(eg. ESP8266)之外,提供了上层的ESP-IDF操作系统及各类应用框架,以及国内外常用的云平台对接方案。
安信可则是乐鑫的大客户,负责生产基于ESP系列芯片的模组,开发者到手就能进行开发,所以一般我们手里的ESP系列模组都是安信可科技的。同时,乐鑫也提供自己的模组。
程序
实现功能
开发板每隔500ms获取PCB板的温度,并且在数码管上显示
长按按键1进入配网模式,可在安信可公众号进行配网
当WIFI模块连接上TCP服务器后,开启透传模式,发送PCB板的温度到服务器上
当WIFI模块没连接上TCP服务器时,每隔10s自动重连
文件结构
main.c ->主函数文件,包含main函数等,程序主要逻辑控制;
Public.c ->公共函数文件,包含Delay延时函数,Memory_Clr内存清除函数,Error_Handler错误处理函数,Sys_Soft_Reset系统软件复位函数;
Sys_init ->系统初始化函数,包含GPIO初始化函数等;
KEY1.c->按键1检测函数;
UART1.c->串口1初始化函数;
ADC.c ->ADC初始化,采集ADC值等;
NTC.c ->NTC外设函数,包含查表,获取环境温度等;
TM1620.c ->驱动IC初始化,协议,温度显示等函数;
UART2.c->串口2初始化函数,发送字符,字符串,数组函数,串口2中断服务函数;
ESP8266.c->WIFI模块函数,包含模块初始化、配网、通过TCP连接服务器、传送PCB板温度、接收信息
代码量太大,只对关键的地方和要注意的点进行记录
STC15L2K32S2单片机串口2配置
与串口1的头文件代码一样,要注意串口2的引脚跟串口1不同,TX是P11,RX是P10;串口2的使用方法与串口1相同
在UART2.c源文件中,可以将串口1的先全部复制过来,然后再修改为串口2的相关寄存器
因为P_SW2的BIT0位默认是0,所以串口2默认映射到P10和P11口,刚好接的是WiFi模块的TXD0和RXD0,所以P_SW2不用配置;其他寄存器就根据数据手册进行配置即可,定时器2的高8位和低8位是T2H和T2L,这个也要注意改
注意:所有的UART1都要改为UART2
SBUF改为S2BUF
后面发送一个字节、发送字符串和发送数组的函数与串口1的一样,只是把UART1改为UART2即可
/*
* @name Init
* @brief 串口2初始化
* @param None
* @retval None
*/
static void Init()
{
/*P_SW2 外围设备功能切换控制寄存器2(不可位寻址)的BIT0位默认为0,即串口2切换位S2_S为0
默认串口2映射到P10和P11上,所以P_SW2寄存器不用配置*/
S2CON = 0x50; //8位数据,可变波特率,第4位S2REN位置1,开启中断
//AUXR = 0000 0100,AUXR不可位寻址,T2x12为定时器2速度选择位,置1则定时器2的速度是传统8051的12倍,不分频
AUXR |= 0x04;
switch (UART2.ucBandRate)
{
case Band_4800: T2L = 0xCD; T2H = 0xFD; break;
case Band_9600: T2L = 0xE0; T2H = 0xFE; break;
case Band_19200: T2L = 0x70; T2H = 0xFF; break;
case Band_115200: T2L = 0xE8; T2H = 0xFF; break;
default: T2L = 0xCD; T2H = 0xFD; break;
}
AUXR |= BIT4; //启动定时器2 0001 0000,T2R位置为1,允许定时器2运行
}
串口2的中断处理函数中,判断接收标志位和发送标志位与串口1的不同,因为寄存器S2CON是不能位寻址的,所以不能单独拿接收标志位S2RI或者发送标志位S2TI来判断,要对S2CON寄存器进行与操作,取出BIT0的S2RI和BIT1的S2TI分别进行判断,清除标志位也是用寄存器操作
串口2的中断号是8
#define S2RI BIT0 //串口2接收中断请求标志位
#define S2TI BIT1 //串口2发送中断请求标志位
……………………
/*
* @name UART1_isr
* @brief 串口2中断处理函数
* @param None
* @retval None
*/
void UART2_isr() interrupt 8
{
//接收
if(S2CON & S2RI) //取出S2CON的BIT0位进行判断,如果是1则是接收中断,如果为0则不是
{
S2CON &= ~S2RI; //清除接收中断标志
/*UART1_Rec_LENGTH宏定义为10,所以接收的数据不能超过10个字节
UART1.ucRec_Cnt表示数组下标,初始化为0*/
if(UART2.ucRec_Cnt < UART2_Rec_LENGTH)
{
ucRec_Buffer[UART2.ucRec_Cnt++] = S2BUF;
}
UART2.ucRec_Flag = TRUE; //接收完成标志位
}
//发送
if(S2CON & S2TI)
{
S2CON &= ~S2TI; //清除发送中断标志
UART2.ucTX_Busy_Flag = FALSE; //清除忙碌标志
}
}
在Sys_Init.c系统初始化源文件的IE_Init()中断函数中,要打开串口2的中断
因为IE2寄存器是不能位寻址的,所以要对IE2寄存器进行赋值,将最低位SE2置1,允许串口2中断
IE2 |= BIT0; //打开串口2中断
主函数main.c
程序的主要逻辑,串口1是负责往串口助手打印调式信息,比如输出单片机发送的AT指令,以及WIFI模块回复的应答;串口2就负责单片机与WIFI模块的通信
/*
* @name main
* @brief 主函数
* @param void
* @retval int
*/
int main(void)
{
static idata uint16_t i = 0;
//系统初始化
Hradware.Sys_Init();
//串口1发送初始化信息
#ifdef Monitor_Run_Code
printf("Initialization completed,system startup!\r\n\r\n");
#endif
//系统主循环
while(1)
{
//连接服务器
/*一开始TCP连接标志位为FALSE,TCP_Reconnect_Timer初始化为10S,上电进行一次TCP连接*/
if(ESP8266.TCP_Connect_Status == FALSE)
{
if(ESP8266.TCP_Reconnect_Timer >= TIMER_10S)
{
ESP8266.TCP_Connect_Server();
}
}
//接收TCP服务器的信息
ESP8266.Receive_Information();
//获取PCB板温度
NTC.Get_Temperature_Value();
//数码管显示温度
TM1620.Disp_Tempareture();
//将温度通过TCP传输到服务器
ESP8266.Transfer_Tempareture(NTC.fTemperature);
//延时500ms
i = 500;
while (i--)
{
Public.Delay_ms(1);
//如果按键1被按下
if(KEY1.KEY_Flag == TRUE)
{
break;
}
}
//通过外部中断改变按键1标志位,然后进行按键1检测
KEY1.KEY_Detect();
//模块配网
ESP8266.SmartConfig();
}
}
Hradware.Sys_Init():系统初始化函数,GPIO初始化时要把串口2的引脚TXD2配置成推挽输出,RXD2配置成高阻输入,WIFI模块重启引脚RST和使能引脚EN都配置成推挽输出;要加上串口2和WIFI模块的初始化函数,WIFI模块初始化函数中会使能EN引脚启动WIFI模块,然后发送AT指令,待WIFI模块回应,如果10s内没有回应,则进行错误处理,PWM灯会一直闪烁
ESP8266.TCP_Connect_Server():WIFI 模块连接服务器函数,上电时标志位判断和定时器判断都为真,则进行TCP服务器连接,如果WIFI模块没有进行配网的话,是连接不上服务器的,因为WIFI模块还没联网,所以烧录后第一次上电,先进行模块配网操作,待联网成功后,模块会再次进行连接服务器;该函数里会通过串口2发送AT指令给WIFI模块,发送ATE0关闭回显,发送AT+CWMODE_CUR=1\r\n设置为station模式,发送AT+CIFSR\r\n不断查询IP地址,如果连接到WIFI则发送AT+CIPSTART=“TCP”,“172.29.168.61”,8888\r\n连接服务器,成功后发送AT+CIPMODE=1\r\n和AT+CIPSEND\r\n,开启透传模式以及开始发送数据
ESP8266.Receive_Information():WIFI模块接收服务器数据函数,先判断服务器连接状态标志位是否被置位,是则判断串口2的接收数组中是否有PWM = 100%的数据,可以用strstr函数来查找,有则设置PWM灯占空比为100%,并备份占空比;如果接收数组中有PWM = 0%,则设置PWM灯占空比为0%,也备份占空比
ESP8266.Transfer_Tempareture(NTC.fTemperature):将计算出来的浮点型PCB板温度传入该函数中,如果温度是个位,则转为字符型后调用串口2发送函数发送到服务器上,如果温度是十位,则分别提取个位和十位,再转为字符型,发送到服务器上显示,连同提示信息一起发送
KEY1.KEY_Detect():按键1检测,主要检测长按,通过外部中断0改变按键1的标志位,再进行判断是单击还是长按,函数退出前不清零长按标志位,要进行后面的模块配网操作
ESP8266.SmartConfig():WIFI 模块配网函数,函数中会检测按键1长按标志位是否被置为TRUE,是的话则进行配网,如果此时WIFI 模块已经处于透传模式,则先发送“+++”退出透传模式,再进行配网操作,主要是发送指令“AT+CWSTARTSMART\r\n”开启配网,开发板的运行指示灯会不断闪烁,在3分钟内,可以用手机打开安信可的公众号,找到微信配网选项,然后输入手机已连接的路由器WIFI信号密码,WIFI模块抓取网络信号,并通过串口1可在串口助手中看到配网过程,如果WIFI模块回应“Smart get wifi info”,则表示配网成功,随后重启单片机,再进行连接TCP服务器的操作
本次实验中使用到的AT指令以及其功能
AT指令 | 响应 | 功能以及参数说明 |
---|---|---|
AT | OK | 测试AT启动 |
ATE0 | OK | 关闭回显 |
AT+CWMODE_CUR=1 | OK | 设置当前Wi-Fi模式(sta/AP/sta+AP),不保存到flash; 参数说明:1 : station模式;2 : softAP模式;3 : softAP + station模式 |
AT+CIFSR | + CIFSR: < IP address > + CIFSR: < IP address > OK | 查询本地IP地址; 参数说明:< lP address> ESP8266 softAP的IP地址 ESP8266 station的IP地址 |
AT+CWAUTOCONN=1 | OK | 上电是否自动连接AP 参数说明: 0:上电不自动连接AP 1:上电自动连接AP ESP8266 station默认上电自动连接AP |
AT+CWSTARTSMART | OK | 开启SmartConfig SmartConfig类型为ESP-Touch + AirKiss |
AT+CIPMODE=1 | OK | 设置传输模式 参数说明: 0:普通传输模式 1:透传模式,仅支持TCP单连接和UDP固定通信对端的情况 |
AT+CIPSEND | 收到此命令后先换行返回">“ 进入透传模式发送数据,每包最大2048字节,或者每包数据以20ms间隔区分。 当输入单独一包”+++“时,返回普通AT指令模式。发送”+++"退出透传时,请至少间隔1秒再发下一条AT指令。 | 发送数据 |
注意:
1.AT指令打开回显以及关闭回显的作用是什么?
回显的含义是:发送什么指令,返回给你结果的时候,会把发送的指令再显示一遍 如 AT+E=ON时 发送 AT+VER?查询版本号 返回的数据是 AT+VER?(会把下发的指令再显示一遍) +VER:V1.2.6 若是关闭回显,即AT+E=OFF 发送 AT+VER? 返回的是 +VER:V1.2.6
2.开启SmartConfig(配网)的指令AT+CWSTARTSMART = < type >:
如果指令指定参数< type >,则参数分别表示为:1 : ESP-Touch;2 : AirKiss;3 : ESP-Touch + AirKiss
该指令仅支持在ESP8266单station模式下调用。
消息“Smart get WiFi info”表示 Smart Config成功获取到AP信息,之后ESP8266尝试连接AP,打印连接过程。
消息"Smartconfig connected WiFi”表示成功连接到AP,此时可以调用"AT+CWSTOPSMART”停止SmartConfig再执行其他指令。注意,在 SmartConfig过程中请勿执行其他指令。
从AT_v1.0开始,SmartConfig可以自动获取协议类型,AirKiss或者ESP-TOUCH
实验现象以及连接步骤
注意:手机和电脑连的都是同一个路由器或者同一个手机热点,因为配过一次网后,WIFI模块会自动连接上AP,如果更换了路由器或者手机热点,那就要重新再进行配网
实现功能1
把TCP服务器IP地址改为手机端的,再编译烧录
//#define TCP_Server "AT+CIPSTART=\"TCP\",\"172.29.168.77\",8888\r\n" //电脑端模拟的TCP服务器
#define TCP_Server "AT+CIPSTART=\"TCP\",\"172.29.168.66\",8888\r\n" //手机端模拟的TCP服务器
手机安装一个网络助手,这里用安信可的,打开后点击创建TCP Server
输入端口号,然后点击CONFIRM
给开发板上电,可以在串口助手打印信息上看到WIFI模块连接TCP服务器过程,AT+CIPSEND后便开启了透传模式
然后就可以看到手机服务器上接收到了WIFI模块通过TCP协议传来的PCB板温度信息
服务器也可以发送信息控制开发板PWM灯的亮灭
实现功能2
先把TCP服务器IP地址改为电脑端的,再编译烧录
#define TCP_Server "AT+CIPSTART=\"TCP\",\"172.29.168.77\",8888\r\n" //电脑端模拟的TCP服务器
//#define TCP_Server "AT+CIPSTART=\"TCP\",\"172.29.168.66\",8888\r\n" //手机端模拟的TCP服务器
打开电脑的网络调试助手,选择TCP服务器IP地址,并设置端口号,打开服务器(电脑和手机连接的都是同一个路由器,这样就不用重新配网)
注意:电脑的防火墙要先关闭
开发板上电,同时串口助手可看到WIFI模块连接TCP服务器的情况,与手机端的串口输出信息一样
然后网络调试助手就可以看到WIFI模块发来的数据了
同样,服务器发送PWM = 100%可以点亮开发板的PWM灯,发送PWM = 0%熄灭PWM灯
实现功能3
微信配网
长按按键1三秒以上,WIFI模块进入配网模式,开发板的运行指示灯会闪烁,提示正处于配网状态;如果此时WIFI模块已经开启透传模式,单片机会先发送“+++”退出透传模式,不然后续发送的配网AT指令就会被发送到服务器上,控制不了WIFI模块
然后打开安信可的公众号,点击微信配网,进入WIFI配置界面,按要求连接WIFI和开启定位,点击开始配置
开始配置后,会获取并显示当前手机连接到的WIFI,输入WIFI密码,然后点击连接
如果该页面没有出现WIFI名称,如下图的情况,则要等待一会,等识别到后再输入密码,没识别到WIFI名称前输入密码也是没用的,会提示错误信息
输入密码点击连接后,等待配网,过一会后会看到WIFI模块回应一连串的数据并传到串口助手上显示,回应的数据是:smartconfig type:AIRKISS,表示配网使用的类型是AIRKISS协议,配网成功后,单片机会重启,这是代码里设置单片机系统重启的,并不是WIFI模块,系统重启后,WIFI模块也重新被使能启动,自动连接TCP服务器
同时也可以在手机公众号上看到配网成功的提示信息,这样说明配置成功,WIFI模块已经能自动连接上路由器,然后单片机就发送AT指令控制WIFI模块连接TCP服务器,并传输PCB板的温度到服务器上,服务器可以是在电脑端也可以在手机端
假如家里没有路由器,则用手机热点也是可以的
这时候就要有两台手机了,
手机B:开热点,相当于路由器的WiFi信号
手机A:连接手机B的热点,然后打开安信可公众号进行一键配网
此时手机B的热点连接又可以分为两种情况,一种是手机A连接,另一种是电脑连接
手机A 连接 手机B 的热点
手机A控制界面,已连接手机B 的热点
点击WIFI信息,查看手机B热点的IP地址,为172.20.10.1
手机A打开SocketAssistant软件,可看到调试助手的本地IP地址为172.20.10.3,与连接的热点处于同一个网段,然后就可选择创建TCP server,输入端口号,等待客户端ESP-12S的连接
此时,如果是第一次连接手机热点,则需要进行一次配网,将WIFI模块也连上手机B的热点,微信配网过程与上面的一样,此时公众号获取到的WIFI名称是连接到的手机B的热点名称,待WIFI模块连接上热点后,就可以进一步连接服务器了
电脑连接手机B的热点
如果服务器是在电脑上的话,那电脑要连接上手机B的热点,手机A也要连接手机B的热点,用手机A的安信可公众号进行微信配网,将WIFI模块接入热点网络
配网成功后,单片机发送AT指令控制WIFI模块连接上电脑的服务器,并发送PCB板的温度,服务器发送PWM = 100%可点亮开发板的PWM灯,发送PWM = 0%熄灭PWM灯
遇到的疑惑
原本按键1的单击和长按动作要注释掉,并且单击和长按标志位清0的操作也要取消,因为main函数中按键检测完后的下一个函数就是配网函数 ,配网函数里第一条语句就先判断长按标志位是否为TRUE,为TRUE才进行后续配网操作,如果按键检测函数结束前把长按标志位清0了,则后面没法配网;
其次就是长按3秒成功后,标志位在按键检测中没有被清零,在配网函数完成后也没有看到被清零,全局搜索该长按标志后,也没有看到KEY1.Press = FALSE(在长按检测的循环内清0是判断有没有超过3秒,并不是标志位置位后的清零)那标志位是在哪里被清零了呢?如果不清零,则配网函数就会一直检测到长按标志位为TRUE,则一直进行配网操作
答:在配网函数的最后,调用了Public.Sys_Soft_Reset()函数,进行了系统复位,单片机重启了,所以按键1的长按标志位也重新初始化为0了,所以不用再额外写长按标志位清零的操作
粗心导致的BUG
配网函数SmartConfig()中,发送完AT指令后等待WIFI模块返回回应时,if(strstr(UART2.pucRec_Buffer,“Smart get wifi info”) != NULL)这一句的"Smart get wifi info"应答信息一定要写对,不要写错,大小写不对都不行,不然微信这边显示配网成功,但程序没捕捉到退出条件,就一直在循环里跑,一直往串口助手打印串口2的接收缓存,系统软件重启也不行,已经错了两次
//等待配网,超过3分钟则进行退出
Timer0.usDelay_Timer = 0;
while(Timer0.usDelay_Timer <= TIMER_3MIN)
{
Run_LED.Run_LED_Flip();
Public.Delay_ms(100);
if(strstr(UART2.pucRec_Buffer,"Smart get wifi info") != NULL) //注意待匹配的子串要写对,wifi是全小写
{
Public.Delay_ms(1000);
Public.Delay_ms(1000);
Public.Delay_ms(1000);
Public.Delay_ms(1000);
Public.Delay_ms(1000);
Public.Delay_ms(1000);
break;
}
#ifdef Monitor_Run_Code
printf(UART2.pucRec_Buffer);
#endif
}
//系统软件复位
Public.Sys_Reset();
下图是写错时串口打印的信息
看教程时需要注意的点
微信配网原理跟用单片机串口发送热点名称和密码一样,微信配网去到其他地方都可以将硬件设备连接到当地的网络中,这就是优势;而用串口发送的话,换个地方就不行了,需要重新修改代码,更新热点名称和密码,重新烧录才能联网;先配网连接上网络后,才能连接服务器
程序功能的配网模式是指,把路由器的wifi密码发送给开发板,ESP-12S就连接上路由器,然后就可以通过路由器与手机进行连接
联网的方式有:wifi、GPRS、3G/4G、NBIOT、有线
正常产品与TCP服务器之间是有心跳包的,检测两者的连接是否断开
主循环内如果联网状态是FALSE的话,就每隔10S进行一次联网,当联网成功后就不再连接
接收TCP服务器的信息,也就是通过指令控制PWM灯的亮度
AT指令中,开启SmartConfig功能,执行的指令是AT+CWSTARTSMART;AirKiss叫做“飞吻”协议,多用于微信配网;开启时如果不带参数指定协议类型,则默认设置为3,即ESP-Touch和AirKiss协议都支持
按键1是通过外部中断来检测按下的
ESP8266.c中初始化结构体变量时,重连定时器初始化为10S,这样的话在主函数中,一上电就进行一次连接,如果重连定时器初始化为0,则上电后要等10S才开始连接
串口2初始化,串口2中断允许寄存器2(不可位寻址)IE2 |= BIT0,最低位ES2置1,允许串口2中断
P_SW2:外围设备功能切换控制寄存器2(不可位寻址)
注意:串口2的配置中,因为是复制串口1的代码,一开始是串口1的寄存器,要全都改为串口2的寄存器,不能有遗漏
ESP8266的重连定时器变量记得要在定时器0中断中++,用来实现连接服务器失败后,10s再次执行连接服务器函数
按键1 KEY_Detect()检测中,要检测按键1长按超过3秒,for循环的 i 是小于300的,原来检测是两秒,所以 i 的类型为uint8_t,最大只能是256,所以是检测不了3秒的,要将变量 i 的类型改为uint16_t才能检测到长按3秒
串口2的接收数组长度为100,所以数组要声明为xdata,放在片外RAM,不然编译时会提示栈溢出
配网函数中,退出透传模式可用调用三次UART_SendData(‘+’)退出,也可以调用UART_SendString(“+++”)发送字符串退出
如果是用自己手机开热点给电脑连接,则电脑上的网络调试助手可以识别手机网络的IPv4地址,可以开启服务器,但在安信可公众号中却不能微信配网,因为微信配网只能配连接到的WIFI,如果是手机自己开的热点的则配不了,会显示没有搜索到WiFi信号,要求开启WiFi接收功能;也就是说,只有一台手机,没有连接WIFI或者其他手机热点的情况下,是没法微信配网的,想要设备连接手机的热点,只能在代码中添加连接AP的AT指令,用单片机控制WIFI模块连接手机热点
版权声明:本文标题:STC15单片机-无线通讯(WIFI模块) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1726808258a1085249.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论