外包公司做网站怎么样传智播客培训机构官网
外包公司做网站怎么样,传智播客培训机构官网,重庆电脑网站建设,百度小程序ESP-01S WiFi模块在梁山派GD32F470上的移植与物联网应用实战
最近在做一个智能家居的小项目#xff0c;需要让我的梁山派开发板连上网络#xff0c;实现手机远程控制。选来选去#xff0c;安信可的ESP-01S WiFi模块是个不错的选择#xff0c;价格便宜#xff0c;资料也多 uint8_t WIFI_MODE_AP_Init(void); void WIFI_MODE_STA_Aliyun_Init(void); // ... 其他函数声明 #endif接着在bsp_esp01s.c中实现最基础的串口初始化和数据收发函数。这是和模块通信的桥梁。#include bsp_esp01s.h #include string.h // 接收缓冲区 unsigned char WIFI_RX_BUFF[200]; unsigned char WIFI_RX_FLAG 0; // 接收完成标志 unsigned char WIFI_RX_LEN 0; // 接收数据长度 // 串口初始化函数 void WIFI_USART_Init(unsigned int baudrate) { // 1. 使能时钟 rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_USART1); // 2. 配置GPIO为复用功能 gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_2); // PA2: USART1_TX gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_3); // PA3: USART1_RX gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_2 | GPIO_PIN_3); gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2 | GPIO_PIN_3); // 3. 配置串口参数115200, 8N1 usart_baudrate_set(USART1, baudrate); usart_word_length_set(USART1, USART_WL_8BIT); usart_stop_bit_set(USART1, USART_STB_1BIT); usart_parity_config(USART1, USART_PM_NONE); // 4. 使能串口收发 usart_enable(USART1); usart_transmit_config(USART1, USART_TRANSMIT_ENABLE); usart_receive_config(USART1, USART_RECEIVE_ENABLE); // 5. 使能接收中断和空闲中断用于判断一帧数据接收完成 usart_interrupt_enable(USART1, USART_INT_RBNE); usart_interrupt_enable(USART1, USART_INT_IDLE); nvic_irq_enable(USART1_IRQn, 2, 2); // 设置中断优先级 } // 发送一个字符 void WIFI_USART_Send_Bit(unsigned char ch) { usart_data_transmit(USART1, ch); while(RESET usart_flag_get(USART1, USART_FLAG_TBE)); } // 发送字符串 void WIFI_USART_send_String(unsigned char *str) { while(str *str) { WIFI_USART_Send_Bit(*str); } } // 串口中断服务函数核心是接收数据 void WIFI_USART_IRQHandler(void) { // 接收缓冲区非空中断 if(usart_interrupt_flag_get(USART1, USART_INT_FLAG_RBNE) ! RESET) { WIFI_RX_BUFF[WIFI_RX_LEN] usart_data_receive(USART1); if(WIFI_RX_LEN 200) WIFI_RX_LEN 0; // 防止溢出 } // 空闲中断表示一帧数据接收完毕 if(usart_interrupt_flag_get(USART1, USART_INT_FLAG_IDLE) SET) { usart_data_receive(USART1); // 读DR寄存器清除空闲中断标志 WIFI_RX_BUFF[WIFI_RX_LEN] \0; // 添加字符串结束符 WIFI_RX_FLAG 1; // 设置接收完成标志 } }3.2 AT指令收发核心函数和ESP-01S沟通全靠AT指令。我写了一个通用的发送指令并等待响应的函数后面所有操作都基于它。/** * brief 发送AT指令并等待应答 * param cmd: 要发送的AT指令字符串如 AT\r\n * param ack: 期望收到的应答关键字如 OK * param waitms: 每次等待应答的毫秒数 * param cnt: 重试次数 * return 1:成功收到期望应答 0:失败 */ char WIFI_Send_Cmd(char *cmd, char *ack, unsigned int waitms, unsigned char cnt) { WIFI_USART_send_String((unsigned char*)cmd); // 发送指令 while(cnt--) { delay_1ms(waitms); // 等待一段时间让模块响应 if(WIFI_RX_FLAG 1) { // 如果收到数据 WIFI_RX_FLAG 0; // 在接收缓冲区中查找期望的应答 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; }这个函数是驱动层的核心它完成了“发送-等待-检查”的流程。实际使用时模块响应可能需要时间所以waitms参数要根据指令调整比如连接WiFi可能需要设置3000ms3秒。4. 实战应用一AP模式手机直连控制AP模式下ESP-01S自己变成一个WiFi热点你的手机直接连接这个热点然后通过TCP连接与开发板通信。适合短距离、无需互联网的局域网控制比如智能车、室内遥控器。4.1 AP模式初始化流程初始化就是通过一系列AT指令把模块配置成热点并开启TCP服务器。uint8_t WIFI_MODE_AP_Init(void) { uint8_t ret 0; char send_buff[200]; ret WIFI_Send_Cmd(AT\r\n, OK, 100, 3); // 测试AT指令 if(ret ! 1) return ret; ret WIFI_Send_Cmd(ATCWMODE2\r\n, OK, 300, 3); // 设置为AP模式 if(ret ! 1) return ret; // 设置热点名称和密码信道11加密方式4(WPA2_PSK) sprintf(send_buff, ATCWSAP\%s\,\%s\,11,4\r\n, AP_WIFISSID, AP_WIFIPASS); ret WIFI_Send_Cmd(send_buff, OK, 300, 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); // 开启服务器端口5000 return ret; }流程解读AT测试通信是否正常。ATCWMODE2设置模式为AP。ATCWSAP配置热点的SSID和密码。ATRST重启模块使配置生效。ATCIPMUX1允许多个客户端比如多部手机连接。ATCIPSERVER1,5000在端口5000上启动TCP服务器。4.2 手机连接状态与数据解析模块在AP模式下当有设备连接或断开时会自动通过串口上报信息。我们需要在中断接收的数据中解析这些信息。// 在串口中断收到的数据中解析连接状态 uint8_t Get_Device_connection_status(void) { if(WIFI_RX_FLAG 1) { WIFI_RX_FLAG 0; // 有设备连接了热点 if(strstr((char*)WIFI_RX_BUFF, STA_CONNECTED) ! NULL) { printf(有设备连接了热点.\r\n); return 1; } // 有设备断开了热点 if(strstr((char*)WIFI_RX_BUFF, STA_DISCONNECTED) ! NULL) { printf(有设备断开了热点.\r\n); return 2; } // 有设备连接了服务器TCP连接建立 if(strstr((char*)WIFI_RX_BUFF, ,CONNECT) ! NULL) { printf(有设备连接了服务器.\r\n); return 3; } // 有设备断开了服务器 if(strstr((char*)WIFI_RX_BUFF, ,CLOSED) ! NULL) { printf(有设备断开了服务器.\r\n); return 4; } } return 0; }当手机APP通过TCP发送数据过来时模块会以IPD,连接ID,数据长度:数据的格式上报。我们需要解析这个格式。typedef struct { uint8_t device_id; // 连接ID (哪个客户端发的) uint8_t device_datalen; // 数据长度 uint8_t device_data[200]; // 数据内容 } AP_PARAMETER; uint8_t Get_WIFI_AP_Data(AP_PARAMETER *ap_parameter) { char *test; // 判断是否收到数据帧 if(strstr((char*)WIFI_RX_BUFF, IPD,) ! NULL) { test strstr((char*)WIFI_RX_BUFF, IPD,); // 解析ID、长度和数据 ap_parameter-device_id atoi(test 5); // IPD,后的第一个字符是ID // 找到长度和数据的起始位置进行解析... // ... (具体解析代码见原始文章原理是字符串分割) Clear_WIFI_RX_BUFF(); // 解析完清空缓冲区 return 1; } return 0; }4.3 主程序逻辑AP模式在主函数里我们初始化模块为AP模式然后循环检查连接状态并处理手机发来的数据。#include bsp_esp01s.h int main(void) { AP_PARAMETER ap_parameter {0}; systick_config(); // 初始化系统滴答定时器 usart_gpio_config(115200U); // 初始化调试串口 printf(System Start (AP Mode)...\r\n); WIFI_ESP01S_Init(); // 初始化WIFI串口 WIFI_MODE_AP_Init(); // 配置为AP模式并开启服务器 while(1) { Get_Device_connection_status(); // 更新连接状态 // 假设我们用一个全局变量 wifi_link_flag 记录服务器连接状态 if(wifi_link_flag 2) { // 有设备连接了服务器 if(Get_WIFI_AP_Data(ap_parameter) 1) { printf(来自客户端[%d]的数据: %s\r\n, ap_parameter.device_id, ap_parameter.device_data); // 这里可以根据接收到的数据控制LED、继电器等 // 例如if(strcmp((char*)ap_parameter.device_data, LED_ON)0) { ... } } } delay_1ms(10); // 简单延时 } }手机端操作手机WiFi设置中连接名为ESP-01S密码为12345678的热点。打开网络调试助手等TCP客户端APP。连接服务器地址192.168.4.1端口5000。发送数据即可在梁山派的串口调试助手中看到。5. 实战应用二STA模式连接阿里云物联网平台STA模式下ESP-01S作为客户端连接你家路由器从而接入互联网再连接到阿里云物联网平台。这样就可以实现真正的远程控制人在外面也能控制家里的设备。5.1 阿里云平台准备注册与登录访问阿里云官网注册并登录。进入物联网平台在控制台找到“物联网平台”或“生活物联网平台”。创建产品与设备创建一个新产品比如“智能灯”联网方式选“Wi-Fi”。在产品下添加一个设备得到至关重要的三元组ProductKey产品密钥、DeviceName设备名称、DeviceSecret设备密钥。定义物模型在产品中定义设备的功能。例如添加一个“开关”属性标识符为LED_Switch数据类型为bool型。获取连接信息记录下产品的ProductKey和设备的DeviceName、DeviceSecret后面代码里要用。5.2 STA模式连接阿里云初始化连接阿里云需要经过几个步骤连接WiFi、计算密码HMAC-SHA1签名、配置MQTT客户端、连接MQTT服务器阿里云、订阅主题。void WIFI_MODE_STA_Aliyun_Init(void) { char AT_CMD[250] {0}; uint8_t PassWord[50] {0}; // 存放计算出的密码 RST: // 1. 测试AT指令 WIFI_Send_Cmd(AT\r\n, OK, 100, 3); // 2. 设置为STA模式 WIFI_Send_Cmd(ATCWMODE1\r\n, OK, 300, 3); // 3. 连接路由器WiFi sprintf(AT_CMD, ATCWJAP\%s\,\%s\\r\n, WIFISSID, WIFIPASS); if(WIFI_Send_Cmd(AT_CMD, OK, 3000, 3) 0) { printf(WiFi连接失败重启重试...\r\n); WIFI_Send_Cmd(ATRST\r\n, ready, 1000, 1); goto RST; // 连接失败跳回开头重试 } // 4. 计算连接阿里云所需的密码HMAC-SHA1签名 // 这里调用了 CalculateSha1 函数利用 DeviceSecret 对特定字符串进行加密 CalculateSha1(PassWord); // 结果存放在PassWord数组中 // 5. 配置MQTT客户端参数用户名、密码、客户端ID memset(AT_CMD, 0, sizeof(AT_CMD)); sprintf(AT_CMD, ATMQTTUSERCFG0,1,\NULL\,\%s%s\,\%s\,0,0,\\\r\n, DeviceName, ProductKey, PassWord); WIFI_Send_Cmd(AT_CMD, OK, 2000, 3); // 6. 设置客户端ID memset(AT_CMD, 0, sizeof(AT_CMD)); sprintf(AT_CMD, ATMQTTCLIENTID0,\123|securemode3,signmethodhmacsha1|\\r\n); WIFI_Send_Cmd(AT_CMD, OK, 1000, 3); // 7. 连接到阿里云MQTT服务器 memset(AT_CMD, 0, sizeof(AT_CMD)); sprintf(AT_CMD, ATMQTTCONN0,\%s\,1883,1\r\n, 203.107.45.14); // 阿里云公共MQTT地址 if(WIFI_Send_Cmd(AT_CMD, OK, 2000, 3) 0) { printf(连接阿里云失败系统复位...\r\n); WIFI_Send_Cmd(ATRST\r\n, ready, 1000, 2); NVIC_SystemReset(); // 连接失败复位单片机 } // 8. 订阅主题用于接收云平台下发的指令 memset(AT_CMD, 0, sizeof(AT_CMD)); sprintf(AT_CMD, ATMQTTSUB0,\/sys/%s/%s/thing/service/property/set\,1\r\n, ProductKey, DeviceName); WIFI_Send_Cmd(AT_CMD, OK, 1000, 3); printf(连接阿里云成功\r\n); }注意CalculateSha1函数涉及HMAC-SHA1加密算法需要引入相关代码库。原始资料中包含了hmacsha1.h和对应的实现移植时务必一起拷贝到工程中。5.3 解析云端指令与控制执行手机通过阿里云APP下发指令时平台会向设备发送MQTT消息消息是JSON格式。我们需要解析这个JSON提取出控制命令。// 用于存储解析出的JSON键值对 typedef struct { char keyname[50]; // 例如 LED_Switch char value[20]; // 例如 1 } JSON_PUBLISH; uint8_t Get_Aliyun_json_data(JSON_PUBLISH *data) { char *buff 0; if(WIFI_RX_FLAG 1) { WIFI_RX_FLAG 0; // 在接收到的数据中查找 params:{ 字段 if(strstr((char*)WIFI_RX_BUFF, params\:) ! NULL) { // 找到功能标识符keyname buff strstr((char*)WIFI_RX_BUFF, params\:); buff strlen(params\:{\); strcpy(data-keyname, strtok(buff, \)); // 提取引号内的key // 找到对应的值value buff strstr((char*)WIFI_RX_BUFF, params\:); buff strlen(params\:{\) strlen(data-keyname) 2; // 跳过key和引号、冒号 strcpy(data-value, strtok(buff, })); // 提取值 printf(收到指令: %s %s\r\n,>#include bsp_esp01s.h // 简单的LED初始化函数 void LED_GPIO_Init(void) { rcu_periph_clock_enable(RCU_GPIOD); gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7); gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7); gpio_bit_write(GPIOD, GPIO_PIN_7, 0); // 初始状态熄灭 } int main(void) { JSON_PUBLISH sta_json_data {0}; systick_config(); usart_gpio_config(115200U); LED_GPIO_Init(); printf(System Start (STA Mode - AliYun)...\r\n); WIFI_ESP01S_Init(); // 初始化WIFI串口 WIFI_MODE_STA_Aliyun_Init(); // 连接WiFi并接入阿里云 // 可以在这里主动上报一次设备状态到云端 // Publish_MQTT_message(...); while(1) { // 不断检查并解析云端下发的JSON指令 if(Get_Aliyun_json_data(sta_json_data) 1) { // 判断是否是控制LED开关的指令 if(strstr(sta_json_data.keyname, LED_Switch) ! NULL) { if(strstr(sta_json_data.value, 1) ! NULL) { gpio_bit_write(GPIOD, GPIO_PIN_7, 1); // 开灯 printf(LED ON\r\n); } else if(strstr(sta_json_data.value, 0) ! NULL) { gpio_bit_write(GPIOD, GPIO_PIN_7, 0); // 关灯 printf(LED OFF\r\n); } // 清除已处理的数据结构准备接收下一条 Clear_Aliyun_json_data(sta_json_data); } // 可以继续解析其他指令如亮度调节等 } delay_1ms(10); } }操作流程将代码中的WIFISSID、WIFIPASS以及阿里云三元组信息修改为你自己的。编译程序并下载到梁山派。在阿里云物联网平台控制台看到设备状态变为“在线”。在阿里云APP云智能或平台提供的调试工具中对设备属性LED_Switch进行设置开/关即可远程控制梁山派上的LED。6. 调试心得与常见问题波特率问题ESP-01S默认AT指令波特率是115200如果通信不上首先检查双方波特率是否一致。供电要足ESP8266在发射WiFi信号时瞬时电流较大可达170mA确保你的3.3V电源能提供足够电流最好单独供电或使用开发板上的稳压输出避免因供电不足导致模块不断重启。指令响应等待时间不同的AT指令执行时间差异很大。ATCWJAP连接WiFi可能需要几秒而AT测试指令瞬间完成。在WIFI_Send_Cmd函数中要根据指令合理设置waitms参数。JSON解析云端下发的JSON数据格式固定但较长确保你的接收缓冲区WIFI_RX_BUFF足够大原始代码中是200字节。如果遇到解析失败可以先用printf打印出完整的接收缓冲区看看数据是否完整。固件版本务必确认ESP-01S烧录的是支持MQTT的AT固件。可以在串口助手发送ATGMR查看版本信息。通过以上步骤你应该已经成功将ESP-01S WiFi模块移植到了梁山派GD32F470上并实现了局域网和云平台两种物联网控制方式。这套代码框架清晰稍加修改就能应用到你的实际项目中比如控制继电器、读取传感器数据上报等。