1. 硬件准备与环境搭建第一次接触STM32和ESP-01s的配网开发时我花了两天时间才把开发环境折腾明白。现在回想起来其实只要准备好这几样东西就能快速开工核心硬件STM32F103C8T6最小系统板某宝20块钱就能买到、ESP-01s WiFi模块注意要买带金属屏蔽罩的版本下载工具ST-LINK V2编程器建议买带SWD接口的版本连接线材杜邦线至少需要6根建议买现成的母对母线束电源供应ESP-01s需要3.3V供电千万别接5V软件环境方面我强烈建议使用Keil MDK 5.25以上版本这个版本对STM32F1系列的支持最稳定。安装时记得勾选Device Family Pack里的STM32F1xx_DFP否则新建工程时会找不到芯片型号。我第一次安装时就漏了这个选项结果新建工程时列表里空空如也还以为软件装坏了。2. 工程框架搭建实战2.1 创建干净的Keil工程很多教程直接给现成工程文件但我建议新手一定要自己从头建一次工程。打开Keil后点击Project → New μVision Project选择保存路径建议用英文路径芯片型号选择STM32F103C8注意不是STM32F103C8T6Keil里没有带T6的选项这时会弹出运行时环境管理窗口需要勾选CMSIS → COREDevice → StartupSTM32F1xx_DFP → STM32F103 → Device → STM32Cube FW_F1 V1.8.02.2 添加必要外设驱动在工程里新建以下分组Hardware放LED、按键等外设驱动Middlewares放机智云协议栈User放main.c等用户代码右键点击Target 1选择Options for Target在C/C选项卡的Include Paths里添加.\User .\Middlewares .\Hardware3. 关键外设配置详解3.1 串口配置的坑与技巧ESP-01s默认波特率是115200但实际测试发现9600更稳定。在usart.c里修改初始化参数void USART3_Init(u32 bound) { // 时钟使能 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // GPIO配置 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin GPIO_Pin_10; // TX GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOB, GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin GPIO_Pin_11; // RX GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB, GPIO_InitStructure); // 串口参数配置 USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate bound; USART_InitStructure.USART_WordLength USART_WordLength_8b; USART_InitStructure.USART_StopBits USART_StopBits_1; USART_InitStructure.USART_Parity USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART3, USART_InitStructure); // 使能串口 USART_Cmd(USART3, ENABLE); }特别注意STM32F103C8T6的USART3是挂在APB1总线上的时钟频率只有36MHz计算波特率时要注意。3.2 定时器配置的玄机机智云协议需要1ms定时中断我最初用TIM2总是出现通信超时后来发现是中断优先级问题。正确的TIM3配置如下void TIM3_Init(u16 arr, u16 psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); TIM_TimeBaseStructure.TIM_Period arr; TIM_TimeBaseStructure.TIM_Prescaler psc; TIM_TimeBaseStructure.TIM_ClockDivision TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, TIM_TimeBaseStructure); TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); NVIC_InitStructure.NVIC_IRQChannel TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority 1; NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure); TIM_Cmd(TIM3, ENABLE); }中断服务函数里记得调用gizTimerMs()这是协议栈的心跳机制void TIM3_IRQHandler(void) { if(TIM_GetITStatus(TIM3, TIM_IT_Update) ! RESET) { gizTimerMs(); TIM_ClearITPendingBit(TIM3, TIM_IT_Update); } }4. 机智云协议栈移植4.1 文件结构规划从官网下载的MCU代码包解压后把这两个文件夹复制到工程目录Gizwits协议核心文件Utils工具类文件在Keil工程里新建Middlewares分组添加以下文件gizwits_protocol.c gizwits_product.c protocol.c头文件包含路径要添加.\Middlewares\Gizwits .\Middlewares\Utils4.2 关键函数移植在main.c中需要实现三个核心函数设备初始化userInit()事件处理userHandle()数据点处理gizwitsEventProcess()我常用的初始化模板void userInit(void) { SystemInit(); USART1_Init(115200); // 调试串口 USART3_Init(9600); // WiFi串口 TIM3_Init(7199, 0); // 1ms定时 LED_Init(); // 状态指示灯 printf(System Init OK\r\n); }5. 硬件连接与调试技巧5.1 接线图详解ESP-01s与STM32的正确连接方式ESP-01s STM32 VCC → 3.3V GND → GND EN → 3.3V必须接 TX → PB11(USART3_RX) RX → PB10(USART3_TX)实测中发现如果EN引脚不接高电平模块虽然能亮灯但永远不会进入配网模式。这个坑我踩了整整一天才找到原因。5.2 常见问题排查问题1下载程序后ESP-01s蓝灯不亮检查VCC电压万用表实测要在3.0-3.6V之间检查EN引脚是否接高电平尝试给模块单独供电开发板的3.3V可能带载能力不足问题2能搜到热点但配网失败检查手机热点频段是否为2.4GHz确保WiFi密码不含特殊字符在gizwits_product.c里修改gizwitsSetMode(WIFI_SOFTAP_MODE)重试6. 功能验证与数据通信6.1 点灯实验验证在gizwits_product.c中找到事件处理函数添加LED控制代码case EVENT_LED_ONOFF: currentDataPoint.valueLED_ONOFF dataPointPtr-valueLED_ONOFF; if(0x01 currentDataPoint.valueLED_ONOFF) { LED_ON(); // 自定义的亮灯函数 } else { LED_OFF(); // 自定义的灭灯函数 } break;6.2 数据上报实战要主动上报设备状态可以使用这个模板dataPoint_t currentDataPoint; memset(currentDataPoint, 0, sizeof(dataPoint_t)); currentDataPoint.valueTemperature 25; // 模拟温度值 currentDataPoint.valueHumidity 60; // 模拟湿度值 gizwitsHandle(currentDataPoint);在调试阶段建议在USART1上接个串口助手打印关键日志printf(WiFi RSSI: %d\r\n, gizwitsGetRSSI()); printf(Cloud Status: %s\r\n, gizwitsGetCloudStatus()?Connected:Disconnected);7. 进阶优化建议当基础功能跑通后可以尝试这些优化低功耗处理在userHandle()里添加休眠逻辑断网重连监测gizwitsGetCloudStatus()状态自动重连OTA升级参考机智云文档实现远程固件更新有个特别实用的调试技巧在USART3的RX/TX线上各串联一个100欧电阻能有效抑制通信干扰。这个方法是老工程师教我的实测能提升20%的通信稳定性。
机智云配网实战:从零到一完成STM32F103C8T6与ESP-01s的代码移植与调试
1. 硬件准备与环境搭建第一次接触STM32和ESP-01s的配网开发时我花了两天时间才把开发环境折腾明白。现在回想起来其实只要准备好这几样东西就能快速开工核心硬件STM32F103C8T6最小系统板某宝20块钱就能买到、ESP-01s WiFi模块注意要买带金属屏蔽罩的版本下载工具ST-LINK V2编程器建议买带SWD接口的版本连接线材杜邦线至少需要6根建议买现成的母对母线束电源供应ESP-01s需要3.3V供电千万别接5V软件环境方面我强烈建议使用Keil MDK 5.25以上版本这个版本对STM32F1系列的支持最稳定。安装时记得勾选Device Family Pack里的STM32F1xx_DFP否则新建工程时会找不到芯片型号。我第一次安装时就漏了这个选项结果新建工程时列表里空空如也还以为软件装坏了。2. 工程框架搭建实战2.1 创建干净的Keil工程很多教程直接给现成工程文件但我建议新手一定要自己从头建一次工程。打开Keil后点击Project → New μVision Project选择保存路径建议用英文路径芯片型号选择STM32F103C8注意不是STM32F103C8T6Keil里没有带T6的选项这时会弹出运行时环境管理窗口需要勾选CMSIS → COREDevice → StartupSTM32F1xx_DFP → STM32F103 → Device → STM32Cube FW_F1 V1.8.02.2 添加必要外设驱动在工程里新建以下分组Hardware放LED、按键等外设驱动Middlewares放机智云协议栈User放main.c等用户代码右键点击Target 1选择Options for Target在C/C选项卡的Include Paths里添加.\User .\Middlewares .\Hardware3. 关键外设配置详解3.1 串口配置的坑与技巧ESP-01s默认波特率是115200但实际测试发现9600更稳定。在usart.c里修改初始化参数void USART3_Init(u32 bound) { // 时钟使能 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // GPIO配置 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin GPIO_Pin_10; // TX GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOB, GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin GPIO_Pin_11; // RX GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB, GPIO_InitStructure); // 串口参数配置 USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate bound; USART_InitStructure.USART_WordLength USART_WordLength_8b; USART_InitStructure.USART_StopBits USART_StopBits_1; USART_InitStructure.USART_Parity USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART3, USART_InitStructure); // 使能串口 USART_Cmd(USART3, ENABLE); }特别注意STM32F103C8T6的USART3是挂在APB1总线上的时钟频率只有36MHz计算波特率时要注意。3.2 定时器配置的玄机机智云协议需要1ms定时中断我最初用TIM2总是出现通信超时后来发现是中断优先级问题。正确的TIM3配置如下void TIM3_Init(u16 arr, u16 psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); TIM_TimeBaseStructure.TIM_Period arr; TIM_TimeBaseStructure.TIM_Prescaler psc; TIM_TimeBaseStructure.TIM_ClockDivision TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, TIM_TimeBaseStructure); TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); NVIC_InitStructure.NVIC_IRQChannel TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority 1; NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure); TIM_Cmd(TIM3, ENABLE); }中断服务函数里记得调用gizTimerMs()这是协议栈的心跳机制void TIM3_IRQHandler(void) { if(TIM_GetITStatus(TIM3, TIM_IT_Update) ! RESET) { gizTimerMs(); TIM_ClearITPendingBit(TIM3, TIM_IT_Update); } }4. 机智云协议栈移植4.1 文件结构规划从官网下载的MCU代码包解压后把这两个文件夹复制到工程目录Gizwits协议核心文件Utils工具类文件在Keil工程里新建Middlewares分组添加以下文件gizwits_protocol.c gizwits_product.c protocol.c头文件包含路径要添加.\Middlewares\Gizwits .\Middlewares\Utils4.2 关键函数移植在main.c中需要实现三个核心函数设备初始化userInit()事件处理userHandle()数据点处理gizwitsEventProcess()我常用的初始化模板void userInit(void) { SystemInit(); USART1_Init(115200); // 调试串口 USART3_Init(9600); // WiFi串口 TIM3_Init(7199, 0); // 1ms定时 LED_Init(); // 状态指示灯 printf(System Init OK\r\n); }5. 硬件连接与调试技巧5.1 接线图详解ESP-01s与STM32的正确连接方式ESP-01s STM32 VCC → 3.3V GND → GND EN → 3.3V必须接 TX → PB11(USART3_RX) RX → PB10(USART3_TX)实测中发现如果EN引脚不接高电平模块虽然能亮灯但永远不会进入配网模式。这个坑我踩了整整一天才找到原因。5.2 常见问题排查问题1下载程序后ESP-01s蓝灯不亮检查VCC电压万用表实测要在3.0-3.6V之间检查EN引脚是否接高电平尝试给模块单独供电开发板的3.3V可能带载能力不足问题2能搜到热点但配网失败检查手机热点频段是否为2.4GHz确保WiFi密码不含特殊字符在gizwits_product.c里修改gizwitsSetMode(WIFI_SOFTAP_MODE)重试6. 功能验证与数据通信6.1 点灯实验验证在gizwits_product.c中找到事件处理函数添加LED控制代码case EVENT_LED_ONOFF: currentDataPoint.valueLED_ONOFF dataPointPtr-valueLED_ONOFF; if(0x01 currentDataPoint.valueLED_ONOFF) { LED_ON(); // 自定义的亮灯函数 } else { LED_OFF(); // 自定义的灭灯函数 } break;6.2 数据上报实战要主动上报设备状态可以使用这个模板dataPoint_t currentDataPoint; memset(currentDataPoint, 0, sizeof(dataPoint_t)); currentDataPoint.valueTemperature 25; // 模拟温度值 currentDataPoint.valueHumidity 60; // 模拟湿度值 gizwitsHandle(currentDataPoint);在调试阶段建议在USART1上接个串口助手打印关键日志printf(WiFi RSSI: %d\r\n, gizwitsGetRSSI()); printf(Cloud Status: %s\r\n, gizwitsGetCloudStatus()?Connected:Disconnected);7. 进阶优化建议当基础功能跑通后可以尝试这些优化低功耗处理在userHandle()里添加休眠逻辑断网重连监测gizwitsGetCloudStatus()状态自动重连OTA升级参考机智云文档实现远程固件更新有个特别实用的调试技巧在USART3的RX/TX线上各串联一个100欧电阻能有效抑制通信干扰。这个方法是老工程师教我的实测能提升20%的通信稳定性。