ESP-01S WiFi模块在天空星GD32F407上的移植与应用实战:AP/STA模式与阿里云物联网平台接入
ESP-01S WiFi模块在天空星GD32F407上的移植与应用实战AP/STA模式与阿里云物联网平台接入最近在做一个智能家居的小项目需要让我的天空星GD32F407开发板能够联网。选来选去最终用了安信可的ESP-01S WiFi模块因为它价格便宜、资料多而且通过串口AT指令就能控制对单片机来说非常友好。今天我就把整个移植和开发过程整理出来从硬件接线到代码编写再到接入阿里云手把手带你走一遍。这篇文章适合正在使用或计划使用GD32F407与ESP-01S进行物联网开发的嵌入式工程师和学生。我会重点讲解如何通过串口AT指令驱动模块实现两种最常用的模式AP模式让手机直接连接开发板的热点和STA模式让开发板连接家里的路由器并接入阿里云物联网平台。跟着做下来你就能掌握让嵌入式设备“上网”的核心技能。1. 认识ESP-01S模块与准备工作1.1 模块简介与资料获取ESP-01S是安信可基于ESP8266芯片设计的一款WiFi模块它最大的特点就是“透传”。简单说你不需要懂复杂的网络协议只要会用串口发送AT指令就能让模块连接WiFi、收发网络数据相当于给你的单片机加了个“无线网卡”。它的核心参数如下参数规格核心芯片ESP8266工作电压3.0V - 3.6V (注意不是5V)工作电流最大170mA通信接口UART串口尺寸14.4mm x 24.7mm支持协议IEEE 802.11 b/g/n内置完整TCP/IP协议栈注意模块工作电压是3.3V直接接5V会烧坏天空星开发板的3.3V输出引脚可以给它供电。在开始之前你需要准备好模块的资料和固件。原始资料里提供了百度网盘链接里面包含了数据手册、AT指令集、以及最重要的——MQTT固件。这个固件是接入阿里云等物联网平台的关键不刷入的话后续的MQTT相关AT指令会一直失败。1.2 硬件连接与固件烧录ESP-01S模块引脚不多我们主要用到这四个VCC接3.3VGND接地TX模块的发送脚接单片机的RX接收RX模块的接收脚接单片机的TX发送在天空星GD32F407上我们使用串口1USART1与模块通信对应的引脚是PA2- USART1_TX (连接ESP-01S的RX)PA3- USART1_RX (连接ESP-01S的TX)接线时务必注意TX和RX要交叉连接。接好线后就可以用资料包里提供的烧录工具和固件文件通过USB转串口工具给ESP-01S刷入MQTT固件了。烧录步骤工具里一般都有说明这里就不赘述了。2. 驱动代码移植与核心函数解析移植代码到你的工程其实就是把bsp_esp01s.c和bsp_esp01s.h这两个文件加进去然后根据你的硬件修改引脚定义。这个过程和移植其他外设比如DHT11温湿度传感器是一样的。咱们重点来看看这些代码具体是怎么工作的。2.1 串口初始化与通信基础要让单片机通过串口和ESP-01S“对话”首先得把串口配置好。代码里的WIFI_USART_Init函数就是干这个的它设置了波特率默认115200、数据位、停止位并开启了接收中断和空闲中断。void WIFI_USART_Init(unsigned int bund) { /* 使能 USART1 和 GPIOA 的时钟 */ rcu_periph_clock_enable(RCU_USART1); rcu_periph_clock_enable(RCU_GPIOA); /* 配置PA2 (TX) 为复用推挽输出 */ gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_2); gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2); gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_2); // USART1复用功能是AF7 /* 配置PA3 (RX) 为复用上拉输入 */ gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_3); gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_3); /* 配置串口参数115200波特率8位数据无校验1位停止位 */ usart_baudrate_set(USART1, bund); usart_word_length_set(USART1, USART_WL_8BIT); usart_parity_config(USART1, USART_PM_NONE); usart_stop_bit_set(USART1, USART_STB_1BIT); usart_enable(USART1); usart_transmit_config(USART1, USART_TRANSMIT_ENABLE); usart_receive_config(USART1, USART_RECEIVE_ENABLE); /* 开启接收中断和空闲中断用于接收不定长数据 */ usart_interrupt_enable(USART1, USART_INT_RBNE); usart_interrupt_enable(USART1, USART_INT_IDLE); nvic_irq_enable(USART1_IRQn, 2, 2); }这里有个关键点空闲中断。AT指令的回复长度不固定用空闲中断来判断一帧数据是否接收完成是非常实用的方法。2.2 AT指令发送与应答检测和ESP-01S通信本质上就是单片机通过串口发送AT指令字符串然后等待模块回复。代码中的WIFI_Send_Cmd函数封装了这个过程。char WIFI_Send_Cmd(char *cmd, char *ack, unsigned int waitms, unsigned char cnt) { WIFI_USART_send_String((unsigned char*)cmd); // 1. 发送AT指令 while(cnt--) { delay_1ms(waitms); // 等待一段时间 // 检查是否收到回复 if( WIFI_RX_FLAG 1 ) { WIFI_RX_FLAG 0; // 在接收缓冲区中查找期待的应答字符串比如OK if( strstr((char*)WIFI_RX_BUFF, ack) ! NULL ) { return 1; // 成功收到预期回复 } // 没找到就清空缓冲区准备重试或返回 memset( WIFI_RX_BUFF, 0, sizeof(WIFI_RX_BUFF) ); } } // 重试次数用完还没成功返回失败 WIFI_RX_FLAG 0; return 0; }这个函数的思路是发送指令 - 等待 - 检查回复中是否包含预期的关键字如OK- 成功则返回失败则重试。waitms和cnt参数让你可以灵活控制等待时间和重试次数非常实用。3. 实战一AP模式——让手机直连开发板AP模式就是把ESP-01S变成一个WiFi热点让你的手机可以直接连接它实现短距离的无线控制和数据传输。这适合不需要互联网、设备间直接通信的场景比如智能开关、无线调试。3.1 AP模式初始化流程要让模块进入AP模式并开启服务器需要按顺序发送一系列AT指令。WIFI_MODE_AP_Init函数把这些步骤都封装好了。uint8_t WIFI_MODE_AP_Init(void) { uint8_t ret 0; char send_buff[128]; ret WIFI_Send_Cmd(AT\r\n, OK, 10, 3); // 测试模块是否正常 if( ret ! 1 ) return ret; ret WIFI_Send_Cmd(ATCWMODE2\r\n,OK,30,3); // 设置为AP模式 (2) if( ret ! 1 ) return ret; // 设置热点的名称(SSID)和密码 sprintf(send_buff, ATCWSAP\%s\,\%s\,11,4\r\n, AP_WIFISSID, AP_WIFIPASS ); ret WIFI_Send_Cmd(send_buff,OK,30,3); if( ret ! 1 ) return ret; ret WIFI_Send_Cmd(ATRST\r\n,ready,800,3); // 重启模块使设置生效 if( ret ! 1 ) return ret; ret WIFI_Send_Cmd(ATCIPMUX1\r\n,OK,50,3); // 开启多连接 if( ret ! 1 ) return ret; ret WIFI_Send_Cmd(ATCIPSERVER1,5000\r\n,OK,50,3); // 开启TCP服务器端口5000 return ret; }这里有几个关键指令ATCWMODE2设置模块为AP模式。ATCWSAP配置热点的名称和密码。AP_WIFISSID和AP_WIFIPASS需要在bsp_esp01s.h文件中定义。ATCIPMUX1允许多个客户端比如多部手机同时连接。ATCIPSERVER1,5000在模块上创建一个TCP服务器监听5000端口。手机APP就需要连接这个IP和端口。3.2 手机连接状态与数据收发服务器建好后我们需要知道有没有手机连上来以及手机发了什么数据过来。Get_Device_connection_status函数通过解析模块主动上报的信息来判断连接状态。当手机连接热点时模块会发送类似STA_CONNECTED:f0:6c:5d:d6:f6:18的信息连接服务器时会收到,CONNECT。我们在主循环里不断调用这个函数就能实时监控连接状态。数据接收则靠Get_WIFI_AP_Data函数。当手机通过APP发送数据时模块会通过串口发送格式如IPD,1,4:abcd的数据。这个函数就是用来解析这个字符串的1客户端的连接ID当有多个设备连接时用来区分。4发送过来的数据长度。abcd实际的数据内容。解析出来后我们就可以根据数据内容比如abcd代表开灯去执行相应的操作了。3.3 AP模式主程序示例把上面的功能组合起来一个简单的AP模式控制程序就出来了。#include board.h #include bsp_esp01s.h int main(void) { AP_PARAMETER ap_parameter{0}; // 用于保存解析出的数据 uint8_t test_ret 0; // 系统初始化 nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); board_init(); usart_gpio_config(115200U); printf(System Start\r\n); // WIFI初始化并设置为AP模式 WIFI_ESP01S_Init(); WIFI_MODE_AP_Init(); while(1) { // 不断检查是否有设备连接或断开 Get_Device_connection_status(); // 如果当前有设备连接了服务器即手机APP连上了 if( wifi_link_flag 2 ) { // 尝试获取手机发来的数据 if( Get_WIFI_AP_Data(ap_parameter) 1 ) { printf(Client ID %d\r\n, ap_parameter.device_id); printf(Data Length %d\r\n, ap_parameter.device_datalen); printf(Data Received: %s\r\n, ap_parameter.device_data); // 这里可以根据 ap_parameter.device_data 的内容来控制LED、继电器等 // 例如if(strcmp((char*)ap_parameter.device_data, ON)0) { LED_ON; } } } } }烧录这个程序用手机连接名为“ESP-01S”密码12345678的热点再用网络调试助手或专门的APP连接192.168.4.1:5000发送数据就能在串口助手上看到打印的信息了。4. 实战二STA模式——接入阿里云物联网平台STA模式是更常用的方式让ESP-01S像手机一样连接你家路由器从而接入互联网实现远程控制。这里我们以接入阿里云物联网平台为例。4.1 阿里云物联网平台配置在写代码之前需要在阿里云物联网平台做一些配置获取连接必需的“三元组”。这个过程在原始文章里有详细步骤我概括一下关键点登录阿里云物联网平台如果没有账号需要先注册。创建产品比如创建一个“智能灯”产品联网方式选“Wi-Fi”数据格式选“ICA标准数据格式Alink JSON”。添加设备在产品下为你手中的这个ESP-01S模块创建一个设备。创建成功后你会得到至关重要的三元组ProductKey产品密钥标识产品。DeviceName设备名称标识单个设备。DeviceSecret设备密钥用于生成连接密码。定义物模型为产品添加功能比如一个“布尔”类型的“LED开关”属性标识符设为LED_Switch。这决定了手机APP上能有什么控件。配置设备面板在“人机交互”中为产品选择一个或创建一个手机APP的控制面板并发布。完成这些后记下你的三元组我们马上要在代码里用到。4.2 代码配置与连接阿里云拿到三元组后需要修改bsp_esp01s.h文件中的几个宏定义/**************************** STA模式 ****************************/ // 改成你家的WiFi #define WIFISSID Your_WiFi_Name #define WIFIPASS Your_WiFi_Password // 阿里云三元组替换成你设备的信息 #define DeviceName Your_Device_Name // 例如 MyDevice_01 #define ProductKey Your_Product_Key // 例如 a1B2c3D4e5 #define DeviceSecret Your_Device_Secret // 一长串字符核心的连接函数是WIFI_MODE_STA_Aliyun_Init。它做的事情比较多设置STA模式ATCWMODE1。连接路由器ATCWJAP使用上面定义的SSID和密码。计算连接密码阿里云MQTT连接需要用户名和密码。密码不是直接填DeviceSecret而是用它和客户端ID、时间戳等信息通过HMAC-SHA1算法计算出来的签名。代码里的CalculateSha1函数就是干这个的。配置MQTT参数设置客户端ID、用户名、计算出的密码。连接MQTT服务器连接到阿里云指定的MQTT服务器地址和端口1883。订阅主题订阅手机下发指令的主题这样才能收到控制命令。这个函数流程较长如果某一步失败比如WiFi密码错误它会尝试复位模块并重连。4.3 解析云平台指令与控制执行手机通过阿里云APP下发指令时平台会以MQTT消息的形式推送到设备ESP-01S模块收到后会通过串口发送给单片机。消息是JSON格式的像这样MQTTSUBRECV:0,/sys/a1PJRLOWo3p/TEST/thing/service/property/set,100,{method:thing.service.property.set,id:367399823,params:{LED_Switch:1},version:1.0.0}我们需要从这一大串里提取出有用的信息params里面的LED_Switch和它的值1。Get_Aliyun_json_data函数就是专门做JSON解析的它会将键名如LED_Switch和键值如1提取出来存放到一个结构体里。在主程序中我们不断调用这个解析函数然后根据解析结果执行相应操作。int main(void) { board_init(); usart_gpio_config(115200U); JSON_PUBLISH sta_json_data{0}; // 用于保存解析出的JSON数据 nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); // 初始化一个LED灯用于测试 LED_GPIO_Init(); printf(System Start\r\n); // WIFI初始化并连接阿里云 WIFI_ESP01S_Init(); WIFI_MODE_STA_Aliyun_Init(); // 可以主动上报一次设备状态到手机APP // Publish_MQTT_message(sta_json_data,2); while(1) { // 获取并解析从阿里云发来的JSON数据 if( Get_Aliyun_json_data(sta_json_data) ) { // 如果解析到键名是LED_Switch if( strstr( sta_json_data.keyname, LED_Switch) ! NULL ) { if( strstr( sta_json_data.value, 0) ! NULL) { gpio_bit_write(GPIOD, GPIO_PIN_7, 0); // 关灯 printf(Turn LED OFF\r\n); } if( strstr( sta_json_data.value, 1) ! NULL) { gpio_bit_write(GPIOD, GPIO_PIN_7, 1); // 开灯 printf(Turn LED ON\r\n); } Clear_Aliyun_json_data(sta_json_data); // 处理完清除数据 } // 可以在这里添加其他功能键的判断比如亮度调节 // if( strstr( sta_json_data.keyname, brightness) ! NULL ) { ... } } } }4.4 数据上报与调试心得除了接收指令设备也可以主动上报数据比如温湿度传感器的读数。Publish_MQTT_message函数就是用来上报数据的。你需要按照阿里云物模型的定义构造一个特定的JSON字符串然后通过ATMQTTPUB指令发布到对应的主题。在实际调试中我强烈建议你先把bsp_esp01s.h文件中的DEBUG宏定义为1。这样所有通过串口和ESP-01S的交互数据以及一些调试信息都会通过单片机的另一个串口比如串口0打印到电脑的串口助手上。你能清楚地看到每条AT指令是否发送成功模块回复了什么连接阿里云每一步是否顺利这对于排查问题至关重要。几个常见的坑点电压问题ESP-01S必须用3.3V供电串口电平也必须是3.3V。固件问题务必烧录支持MQTT的AT固件否则连接阿里云会失败。三元组错误ProductKey、DeviceName、DeviceSecret一个字母都不能错特别是大小写。WiFi密码错误在代码里填写的WiFi密码必须正确且网络可正常连接互联网。JSON格式上报数据时构造的JSON字符串必须严格符合阿里云的标准格式转义字符\很容易出错。按照上面的步骤从硬件接线、刷固件到移植代码、修改配置最后在阿里云平台创建产品设备你就能完整地实现从本地AP控制到远程云端控制的全套功能。这套代码框架很清晰你可以很方便地修改热点的名称密码、WiFi账号、阿里云三元组以及添加更多的传感器和控制逻辑快速搭建起自己的物联网项目。