STM32---项目学习日记

news2026/5/12 5:22:07
1.OLED现象OLED左上角第一列会完全点亮8 个像素全亮1oled.c#include oled.h#include oledfont.hextern I2C_HandleTypeDef hi2c1;//初始化命令uint8_t CMD_Data[]{0xAE, 0x00, 0x10, 0x40, 0xB0, 0x81, 0xFF, 0xA1, 0xA6, 0xA8, 0x3F,0xC8, 0xD3, 0x00, 0xD5, 0x80, 0xD8, 0x05, 0xD9, 0xF1, 0xDA, 0x12,0xD8, 0x30, 0x8D, 0x14, 0xAF};void WriteCmd(){uint8_t i 0;for(i 0; i 27; i){HAL_I2C_Mem_Write(hi2c1, 0x78, 0x00, I2C_MEMADD_SIZE_8BIT, CMD_Datai, 1, 0x100);}}//向设备写控制命令void OLED_WR_CMD(uint8_t cmd){HAL_I2C_Mem_Write(hi2c1, 0x78, 0x00, I2C_MEMADD_SIZE_8BIT, cmd, 1, 0x100);}//向设备写数据void OLED_WR_DATA(uint8_t data){HAL_I2C_Mem_Write(hi2c1, 0x78, 0x40, I2C_MEMADD_SIZE_8BIT, data, 1, 0x100);}//初始化oled屏幕void OLED_Init(void){HAL_Delay(200);WriteCmd();}//清屏size12 size16要清两行其他函数有类似情况void OLED_Clear(){uint8_t i, n;for(i 0; i 8; i){OLED_WR_CMD(0xb0 i);OLED_WR_CMD (0x00);OLED_WR_CMD (0x10);for(n 0; n 128; n)OLED_WR_DATA(0);}}//清行void OLED_Clearrow(uint8_t i){uint8_t n;OLED_WR_CMD(0xb0 i);OLED_WR_CMD (0x00);OLED_WR_CMD (0x10);for(n 0; n 128; n)OLED_WR_DATA(0);}//开启OLED显示void OLED_Display_On(void){OLED_WR_CMD(0X8D); //SET DCDC命令OLED_WR_CMD(0X14); //DCDC ONOLED_WR_CMD(0XAF); //DISPLAY ON}//关闭OLED显示void OLED_Display_Off(void){OLED_WR_CMD(0X8D); //SET DCDC命令OLED_WR_CMD(0X10); //DCDC OFFOLED_WR_CMD(0XAE); //DISPLAY OFF}void OLED_Set_Pos(uint8_t x, uint8_t y){OLED_WR_CMD(0xb0 y);OLED_WR_CMD(((x 0xf0) 4) | 0x10);OLED_WR_CMD(x 0x0f);}void OLED_On(void){uint8_t i, n;for(i 0; i 8; i){OLED_WR_CMD(0xb0 i); //设置页地址0~7OLED_WR_CMD(0x00); //设置显示位置—列低地址OLED_WR_CMD(0x10); //设置显示位置—列高地址for(n 0; n 128; n)OLED_WR_DATA(1);} //更新显示}unsigned int oled_pow(uint8_t m, uint8_t n){unsigned int result 1;while(n--)result * m;return result;}//在指定位置显示一个字符,包括部分字符//x:0~127//y:0~63//mode:0,反白显示;1,正常显示//size:选择字体 16/12void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t Char_Size){unsigned char c 0, i 0;c chr - ;//得到偏移后的值if(x 128 - 1){x 0;y y 2;}if (Char_Size 40){OLED_Set_Pos(x, y);for (i 0; i 20; i)OLED_WR_DATA(F20X40[c * 100 i]);OLED_Set_Pos(x, y 1);for (i 0; i 20; i)OLED_WR_DATA(F20X40[c * 100 i 20]);OLED_Set_Pos(x, y 2);for (i 0; i 20; i)OLED_WR_DATA(F20X40[c * 100 i 40]);OLED_Set_Pos(x, y 3);for (i 0; i 20; i)OLED_WR_DATA(F20X40[c * 100 i 60]);OLED_Set_Pos(x, y 4);for (i 0; i 20; i)OLED_WR_DATA(F20X40[c * 100 i 80]);}else if (Char_Size 32){OLED_Set_Pos(x, y);for (i 0; i 16; i)OLED_WR_DATA(F16X32[c * 64 i]);OLED_Set_Pos(x, y 1);for (i 0; i 16; i)OLED_WR_DATA(F16X32[c * 64 i 16]);OLED_Set_Pos(x, y 2);for (i 0; i 16; i)OLED_WR_DATA(F16X32[c * 64 i 32]);OLED_Set_Pos(x, y 3);for (i 0; i 16; i)OLED_WR_DATA(F16X32[c * 64 i 48]);}else if(Char_Size 16){OLED_Set_Pos(x,y);for(i0;i8;i)OLED_WR_DATA(F8x16[c * 16 i]);OLED_Set_Pos(x, y 1);for(i 0; i 8;i)OLED_WR_DATA(F8x16[c*16i8]);}else{OLED_Set_Pos(x, y);for(i 0; i 6; i)OLED_WR_DATA(F6x8[c][i]);}}//显示2个数字//x,y :起点坐标//len :数字的位数//size:字体大小//mode:模式 0,填充模式;1,叠加模式//num:数值(0~4294967295);void OLED_ShowNum(uint8_t x,uint8_t y,unsigned int num,uint8_t len,uint8_t size2){uint8_t t, temp;uint8_t enshow 0;for(t 0; t len; t){temp (num / oled_pow(10, len - t - 1)) % 10;if(enshow 0 t (len - 1)){if(temp 0){OLED_ShowChar(x (size2 / 2) * t, y, , size2);continue;}elseenshow1;}OLED_ShowChar(x (size2 / 2) * t, y, temp 0, size2);}}//显示一个字符号串void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr, uint8_t Char_Size){unsigned char j 0;while (chr[j] ! \0){OLED_ShowChar(x, y, chr[j], Char_Size);x 8;if(x 120){x 0;y 2;}j;}}//显示汉字//hzk 用取模软件得出的数组void OLED_ShowChinese(uint8_t x, uint8_t y, uint8_t no){uint8_t t, adder 0;OLED_Set_Pos(x, y);for(t 0; t 16; t){OLED_WR_DATA(Hzk[2 * no][t]);adder 1;}OLED_Set_Pos(x,y1);for(t 0; t 16; t){OLED_WR_DATA(Hzk[2 * no 1][t]);adder 1;}}void oled_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, const uint8_t *pic){uint8_t temp_page 0;uint8_t start_page y0 / 8;uint8_t end_page y1 / 8;for (temp_page start_page; temp_page end_page; temp_page){OLED_Set_Pos(x0, temp_page);for(int t 0; t 128; t){OLED_WR_DATA(*(pic));}x0 0;}}(2)main.cOLED_Init();OLED_Clear();//点亮第一列uint8_t Data;Data 0xb0;HAL_I2C_Mem_Write(hi2c1, 0x78,0x00,I2C_MEMADD_SIZE_8BIT,Data,1,HAL_MAX_DELAY);//page0Data 0x00;//低四位HAL_I2C_Mem_Write(hi2c1, 0x78,0x00,I2C_MEMADD_SIZE_8BIT,Data,1,HAL_MAX_DELAY);//page0Data 0x10;//高四位HAL_I2C_Mem_Write(hi2c1, 0x78,0x00,I2C_MEMADD_SIZE_8BIT,Data,1,HAL_MAX_DELAY);//page0Data 0xff;HAL_I2C_Mem_Write(hi2c1, 0x78,0x40,I2C_MEMADD_SIZE_8BIT,Data,1,HAL_MAX_DELAY);//page0(3)现象2.OLED显示字符或汉字1oled.cif(Char_Size 64){c chr - 0;OLED_Set_Pos(x,y);for(i0;i32;i)OLED_WR_DATA(F32X64[c * 256 i]);OLED_Set_Pos(x,y1);for(i0;i32;i)OLED_WR_DATA(F32X64[c * 256 i 32]);OLED_Set_Pos(x,y2);for(i0;i32;i)OLED_WR_DATA(F32X64[c * 256 i 64]);OLED_Set_Pos(x,y3);for(i0;i32;i)OLED_WR_DATA(F32X64[c * 256 i 96]);OLED_Set_Pos(x,y4);for(i0;i32;i)OLED_WR_DATA(F32X64[c * 256 i 128]);OLED_Set_Pos(x,y5);for(i0;i32;i)OLED_WR_DATA(F32X64[c * 256 i 160]);OLED_Set_Pos(x,y6);for(i0;i32;i)OLED_WR_DATA(F32X64[c * 256 i 192]);OLED_Set_Pos(x,y7);for(i0;i32;i)OLED_WR_DATA(F32X64[c * 256 i 224]);}2.BH1750STM32 I2C 驱动 BH1750 数字光照传感器向 BH1750 发送测量指令读取传感器返回的 2 字节原始数据将数据转换成光照强度单位 lx1bh1750.c#includebh1750.hextern I2C_HandleTypeDef hi2c1;功能向 BH1750 发送一个指令如启动测量HAL_I2C_Master_TransmitSTM32 作为主机发送数据hi2c1使用 I2C1BH1750_READ_ADDR(0x47)传感器的 I2C 地址cmd要发送的指令1发送 1 个字节HAL_MAX_DELAY无限等待直到完成//写命令void BH1750_Send_CMD(uint8_t cmd){HAL_I2C_Master_Transmit(hi2c1,BH1750_READ_ADDR,cmd,1,HAL_MAX_DELAY);}//读结果void BH1750_Read_Data(uint8_t *pData){HAL_I2C_Master_Receive(hi2c1,BH1750_READ_ADDR,pData,2,HAL_MAX_DELAY);}功能读取 BH1750 返回的 2 字节光照原始数据HAL_I2C_Master_Receive主机接收数据pData传入数组指针用来存放读到的 2 个字节2读取 2 个字节BH1750 输出固定 16 位数据//转换结果uint16_t BH1750_Data_To_Lx(uint8_t *pData){uint16_t light pData[0];light 8;light pData[1];light (uint16_t)(light / 1.2);return light;}功能把传感器的 2 字节原始数据 → 转换成光照强度 lxBH1750 输出高字节在前低字节在后必须移位合并高8位 8 | 低8位官方公式光照值 合并值 / 1.2(2)bh1750.h#ifndef __BH1750_H_#define __BH1750_H_#includestm32f4xx_hal.h#define BH1750_WRITE_ADDR 0X46#define BH1750_READ_ADDR 0X47void BH1750_Read_Data(uint8_t *pData);void BH1750_Send_CMD(uint8_t cmd);uint16_t BH1750_Data_To_Lx(uint8_t *pData);#endif(3)main.c部分uint8_t Data[2] {0};while (1){BH1750_Send_CMD(0X20);// 发送指令连续高分辨率模式HAL_Delay(150);BH1750_Read_Data(Data);printf(--- %d ---\r\n,BH1750_Data_To_Lx(Data));HAL_Delay(1000);指令 0x20 含义连续测量模式 / 高分辨率模式分辨率 1lx转换时间典型值120ms整套代码的执行流程循环发送0x20 测量指令等待150ms让传感器完成采集读取2 字节原始数据将高 8 位 低 8 位合并成 16 位数据除以1.2得到最终光照强度串口打印结果延时 1 秒重复执行3.DHT11这是一段基于 STM32 HAL 库编写的DHT11 温湿度传感器驱动代码采用单总线协议通信包含微秒级延时、传感器初始化、起始信号、应答检测、数据读取等完整功能。#includedht11.hvoid Delay_US(uint32_t us){uint32_t old_time SysTick-VAL;uint32_t new_time;uint32_t ticks us * 100;uint32_t cnt 0;uint32_t load SysTick-LOAD;while(1){new_time SysTick-VAL;if(new_time ! old_time){if(new_time old_time)cnt (old_time - new_time);elsecnt (load - new_time old_time);if(cnt ticks)break;old_time new_time;}}}功能实现精准微秒级延时DHT11 单总线协议严格依赖时序必须用微秒延时。原理读取系统滴答定时器SysTick的当前计数值、重装载值计算需要延时的总时钟周期数ticks us*100循环读取定时器值统计经过的时钟周期达到设定值后退出循环完成延时。作用为 DHT11 通信时序提供us 级延时如 30us、1usvoid DHT11_Init(void){__HAL_RCC_GPIOB_CLK_ENABLE();GPIO_InitTypeDef GPIO_Init_Struct;GPIO_Init_Struct.Mode GPIO_MODE_OUTPUT_OD;GPIO_Init_Struct.Pin GPIO_PIN_3;GPIO_Init_Struct.Pull GPIO_PULLUP;GPIO_Init_Struct.Speed GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOB, GPIO_Init_Struct);}功能初始化PB3 引脚为 DHT11 通信引脚。关键配置解析__HAL_RCC_GPIOB_CLK_ENABLE()开启 GPIOB 时钟GPIO 必须先开时钟才能使用GPIO_MODE_OUTPUT_OD开漏输出模式单总线协议标准配置支持双向通信GPIO_PULLUP内部上拉保证总线空闲时为高电平GPIO_SPEED_FREQ_HIGH高速 GPIO适配传感器通信时序。作用让 PB3 引脚具备与 DHT11 通信的硬件条件。void DHT11_Start(void){HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,GPIO_PIN_RESET);HAL_Delay(20);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,GPIO_PIN_SET);Delay_US(30);}功能向 DHT11 发送单总线起始信号唤醒传感器。时序逻辑DHT11 标准协议主机STM32拉低总线至少 18ms代码用 20ms主机释放总线拉高电平延时 30us等待传感器响应。作用唤醒 DHT11告诉传感器准备发送数据uint8_t DHT11_Response(void){uint16_t time 0;while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_3)time100){Delay_US(1);time;}if(time100)return 1;time 0;while(!HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_3)time100){Delay_US(1);time;}if(time 100)return 1;return 0;}功能检测 DHT11 是否正常响应起始信号判断传感器是否在线。应答逻辑DHT11 标准协议等待总线拉低传感器拉低总线表示开始响应超时 100us 则判定失败等待总线拉高传感器完成应答超时 100us 则判定失败无超时返回0传感器正常超时返回1传感器异常 / 未连接。作用确认 DHT11 已被成功唤醒可以开始传输数据。uint8_t DHT11_Read_Bit(void){uint16_t time 0;while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_3)time100){Delay_US(1);time;}if(time100)return 2;while(!HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_3)time100){Delay_US(1);time;}if(time 100)return 2;Delay_US(30);if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_3) 0)return 0;elsereturn 1;}功能从 DHT11 读取1bit一位数据是读取字节的基础。位数据读取原理等待传感器拉低总线数据传输开始等待传感器拉高总线延时 30us 后读取电平低电平 → 数据0高电平 → 数据1超时返回2表示读取失败。作用单次读取 1 位二进制数据。uint8_t DHT11_Read_Byte(void){uint8_t data 0;uint8_t i 0;for (i0;i8;i){data 1;data data | DHT11_Read_Bit();}return data;}功能连续读取8 次 1bit 数据拼接成1 字节8bit数据。逻辑解析data 1数据左移一位腾出最低位data | DHT11_Read_Bit()将新读取的 1bit 写入最低位循环 8 次得到完整的 1 字节数据。作用读取 DHT11 传输的单字节数据。void DHT11_Read_Data(uint8_t *pData){DHT11_Start();if(DHT11_Response())return;uint8_t i;for(i0;i5;i){pData[i] DHT11_Read_Byte();}if(pData[4] ! pData[0] pData[1] pData[2] pData[3]){for(i0;i5;i){pData[i] 0;}}}功能读取 DHT11 完整的5 字节数据并进行校验。5 字节数据定义DHT11 标准pData[0]湿度整数部分pData[1]湿度小数部分DHT11 固定为 0pData[2]温度整数部分pData[3]温度小数部分DHT11 固定为 0pData[4]校验和 前 4 字节之和/* USER CODE BEGIN 1 */int fputc(int c,FILE *p){HAL_UART_Transmit(huart1,(uint8_t *)c,1,HAL_MAX_DELAY);return c;}/* USER CODE END 1 *//* USER CODE BEGIN 2 */DHT11_Init();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */uint8_t res[5] {0};while (1){memset(res,0,5);DHT11_Read_Data(res);printf(humi: %d.%d temp: %d.%d\r\n,res[0],res[1],res[2],res[3]);HAL_Delay(1000);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}#ifndef DHT11_H#define DHT11_H#include stm32f4xx_hal.hvoid DHT11_Init(void);void DHT11_Start(void);void DHT11_Read_Data(uint8_t *pData);#endif整体总结通信方式单总线协议仅用PB3一个引脚完成通信数据格式5 字节数据湿度整、湿度小、温度整、温度小、校验和流程初始化 → 起始信号 → 应答检测 → 逐位读数据 → 拼接字节 → 数据校验核心依赖Delay_US微秒延时保证严格的 DHT11 通信时序使用方式调用DHT11_Read_Data传入数组即可获取温湿度原始值。4.ESP8266这份代码是STM32 通过串口UART2驱动 ESP8266 WiFi 模块的底层驱动包含模块复位、串口响应检测、串口波特率修改三个核心功能#includeesp8266.h#includestdio.h#includestring.hextern UART_HandleTypeDef huart2;extern uint8_t g_UART_Buf[256];extern uint16_t g_Index;void ESP8266_Init(void){HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET);HAL_Delay(20);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);HAL_Delay(20);}功能硬件复位 ESP8266 模块原理ESP8266 的复位脚接在 STM32 的 PB12低电平复位高电平工作流程拉低复位脚 → 延时保持复位 → 拉高复位脚 → 延时等待模块启动作用每次初始化时让 WiFi 模块恢复初始状态避免异常void ESP8266_Response(const char *msg,uint32_t timeout){uint32_t Cur_Tick HAL_GetTick();uint8_t data,i 0;while(1){if(HAL_GetTick() - Cur_Tick timeout)//超时break;if(HAL_UART_Receive(huart2,data,1,10) HAL_TIMEOUT)continue;//printf(%c,data);g_UART_Buf[g_Index] data;//把数据保存到缓冲区if(data msg[i]){i;if(i strlen(msg))break;}else{i 0;}}}核心功能参数const char *msg要检测的目标字符串如OKuint32_t timeout最大等待超时时间单位ms工作流程计时开始 → 循环读取串口 1 字节数据 → 存入全局缓冲区逐字符对比目标字符串匹配成功则继续失败则重置匹配两种退出条件完整匹配到目标字符串或等待超时用途发送 AT 指令后调用这个函数检测 ESP8266 是否返回预期结果void ESP8266_SetBaud(uint32_t baud)//重新改的比特率{huart2.Instance USART2;huart2.Init.BaudRate baud;huart2.Init.WordLength UART_WORDLENGTH_8B;huart2.Init.StopBits UART_STOPBITS_1;huart2.Init.Parity UART_PARITY_NONE;huart2.Init.Mode UART_MODE_TX_RX;huart2.Init.HwFlowCtl UART_HWCONTROL_NONE;huart2.Init.OverSampling UART_OVERSAMPLING_16;HAL_UART_Init(huart2);}功能动态修改 STM32 串口 2 的波特率背景ESP8266 默认波特率通常是 115200可通过 AT 指令修改模块波特率作用修改 ESP8266 波特率后必须同步修改 STM32 串口波特率才能正常通信特点完整重配置串口所有参数最后调用HAL_UART_Init生效#ifndef ESP8266_H#define ESP8266_H#includestm32f4xx_hal.hvoid ESP8266_Response(const char *msg,uint32_t timeout);void ESP8266_SetBaud(uint32_t baud);void ESP8266_Init(void);#endifint fputc(int c,FILE *p){HAL_UART_Transmit(huart1,(uint8_t *)c,1,HAL_MAX_DELAY);return c;}/* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();MX_USART2_UART_Init();/* USER CODE BEGIN 2 */ESP8266_Init();ESP8266_Response(csum 0xde\r\n,2000);ESP8266_SetBaud( 115200);ESP8266_Response(ready\r\n,1000);ESP8266_Response(xxxx,1000);printf(%s,g_UART_Buf);g_Index 0;/* USER CODE END 2 *//* Infinite loop */整体代码总结核心功能ESP8266_Init硬件复位 WiFi 模块初始化模块状态ESP8266_Response串口接收 字符串匹配检测模块返回的指令响应ESP8266_SetBaud动态修改串口波特率适配 ESP8266 的通信速率代码用途这是 STM32 驱动 ESP8266 的底层基础函数上层可以基于这三个函数实现发送 AT 指令、连接 WiFi、联网通信等功能6.ESP8266进阶整体功能概述这是一份STM32 驱动 ESP8266 连接 WIFI MQTT 服务器的固件代码基于 HAL 库通过串口USART2与 ESP8266 通信实现ESP8266 初始化连接路由器 WIFI连接 MQTT 服务器MQTT 消息发布PublishMQTT 主题订阅Subscribe串口接收、指令等待响应、缓冲区管理includeesp8266.h#includestdio.h#includestring.hextern UART_HandleTypeDef huart2;extern uint8_t g_UART_Buf[256];extern uint16_t g_Index;void ESP8266_Init(void){HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET);HAL_Delay(20);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);HAL_Delay(20);ESP8266_Response(csum 0xde\r\n,2000);ESP8266_SetBaud( 115200);ESP8266_Response(ready\r\n,1000);printf(%s,g_UART_Buf);g_Index 0;memset(g_UART_Buf,0,512);}uint8_t ESP8266_Response(const char *msg,uint32_t timeout){uint32_t Cur_Tick HAL_GetTick();uint8_t data,i 0;while(1){if(HAL_GetTick() - Cur_Tick timeout)//超时return 0;if(HAL_UART_Receive(huart2,data,1,10) HAL_TIMEOUT)continue;//printf(%c,data);g_UART_Buf[g_Index] data;//把数据保存到缓冲区if(data msg[i]){i;if(i strlen(msg))return 1;}else{i 0;}}}void ESP8266_SetBaud(uint32_t baud)//重新改的比特率{huart2.Instance USART2;huart2.Init.BaudRate baud;huart2.Init.WordLength UART_WORDLENGTH_8B;huart2.Init.StopBits UART_STOPBITS_1;huart2.Init.Parity UART_PARITY_NONE;huart2.Init.Mode UART_MODE_TX_RX;huart2.Init.HwFlowCtl UART_HWCONTROL_NONE;huart2.Init.OverSampling UART_OVERSAMPLING_16;HAL_UART_Init(huart2);}void ESP8266_Send_Cmd(const char *cmd)//封装函数发送命令{HAL_UART_Transmit(huart2,(uint8_t *)cmd,strlen(cmd),HAL_MAX_DELAY);HAL_UART_Transmit(huart2,(uint8_t *)\r\n,2,HAL_MAX_DELAY);}void ESP8266_Refresh_Buffer(){printf(%s\r\n,g_UART_Buf);g_Index 0;memset(g_UART_Buf,0,512);}void ESP8266_Connect_AP(const char *ssid,const char *passwd)// WIFI名字和密码{char cmd[128] {0};sprintf(cmd,ATCWJAP\%s\,\%s\,ssid,passwd);//转义字符ESP8266_Send_Cmd(cmd);if(ESP8266_Response(OK,50000))//20s内连上{ESP8266_Refresh_Buffer();}else{ESP8266_Refresh_Buffer();printf(CONNECT WIFI FAILURE\r\n );}}void ESP8266_Connect_MQTT(const char *ip,int port,const char *user,const char *passwd){char cmd[128] {0};sprintf(cmd,ATMQTTUSERCFG0,1,\0001\,\%s\,\%s\,0,0,\ \,user,passwd);//Set MQTT User ConfigESP8266_Send_Cmd(cmd);if(ESP8266_Response(OK,5000)){ESP8266_Refresh_Buffer();}else{ESP8266_Refresh_Buffer();printf(CONFIG MQTT FAILURE\r\n);}memset(cmd,0,sizeof(cmd));sprintf(cmd,ATMQTTCONN0,\%s\,%d,1,ip,port); //Connect to a MQTT broker主机ESP8266_Send_Cmd(cmd);if(ESP8266_Response(OK,10000)){ESP8266_Refresh_Buffer();}else{ESP8266_Refresh_Buffer();printf(CONNECT MQTT FAILURE\r\n);}}ATMQTTUSERCFG→ 配置 MQTT 账号ATMQTTCONN→ 连接服务器IP 端口void ESP8266_Publish(const char *topic,const char *msg)//发布 no 订阅{char cmd[256] {0};sprintf(cmd,ATMQTTPUB0,\%s\,\%s\,0,0,topic,msg);ESP8266_Send_Cmd(cmd);if(ESP8266_Response(OK,10000)){ESP8266_Refresh_Buffer();}else{ESP8266_Refresh_Buffer();printf(PUBLISH FAILURE\r\n);}}指令ATMQTTPUB功能向指定主题发送消息void ESP8266_Subscribe(const char *topic){char cmd[128] {0};sprintf(cmd,ATMQTTSUB0,\%s\,0,topic);ESP8266_Send_Cmd(cmd);if(ESP8266_Response(OK,10000)){ESP8266_Refresh_Buffer();}else{ESP8266_Refresh_Buffer();printf(SUBSCRIBE FAILURE\r\n);}}指令ATMQTTSUB功能订阅主题等待服务器下发消息#ifndef ESP8266_H#define ESP8266_H#includestm32f4xx_hal.huint8_t ESP8266_Response(const char *msg,uint32_t timeout);void ESP8266_SetBaud(uint32_t baud);void ESP8266_Init(void);void ESP8266_Connect_AP(const char *ssid,const char *passwd);// WIFI名字和密码void ESP8266_Connect_MQTT(const char *ip,int port,const char *user,const char *passwd);//void ESP8266_Publish(const char *topic,const char *msg);//发布void ESP8266_Subscribe(const char *topic);//订阅void ESP8266_Refresh_Buffer(void);#endifuint8_t data,Flag 0;uint32_t old_tick 0;while (1){if(HAL_GetTick() - old_tick 50 Flag ){ESP8266_Refresh_Buffer();Flag 0;}if(HAL_UART_Receive(huart2,data,1,10) HAL_TIMEOUT)//超时{continue;}else{g_UART_Buf[g_Index] data;old_tick HAL_GetTick();Flag 1;}代码整体逻辑流程图复位 ESP8266初始化串口波特率 115200连接 WIFI配置 MQTT 用户信息连接 MQTT 服务器可发布 / 订阅 MQTT 消息所有指令都靠ESP8266_Response等待OK判断成功关键特点总结基于ESP8266 AT 指令集 MQTT用状态匹配方式判断指令是否成功缓冲区全局共享超时机制保证不卡死封装清晰初始化 → WIFI → MQTT → 发布 → 订阅

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2559006.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…