当前位置: 首页 > article >正文

STM32---项目学习日记

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 → 发布 → 订阅

相关文章:

STM32---项目学习日记

1.OLED现象:OLED 左上角第一列会完全点亮(8 个像素全亮)(1)oled.c#include "oled.h" #include "oledfont.h"extern I2C_HandleTypeDef hi2c1;//初始化命令 uint8_t CMD_Data[]{ 0xAE, 0x00, 0x10,…...

ZYNQ SDK调试避坑实录:从BANK电压到GIC中断,新手必踩的四个坑

ZYNQ SDK调试避坑实录:从BANK电压到GIC中断,新手必踩的四个坑 刚接触ZYNQ开发的工程师常会遇到这样的困惑:明明代码逻辑没问题,但外设就是不按预期工作。这时候往往不是软件的问题,而是硬件配置或底层细节在作祟。本文…...

别再乱升级libc6了!遇到`GLIBC_2.34 not found`错误,先试试这几种更稳妥的解决方案

当系统GLIBC版本不匹配时,五种安全解决方案深度解析 遇到GLIBC_2.34 not found这类错误时,许多开发者的第一反应是直接升级系统libc6库。这种看似直接的解决方案实际上隐藏着巨大风险——可能导致系统关键组件不兼容,甚至引发连锁崩溃。本文将…...

6G网络中的大模型与多模态感知通信技术解析

1. 6G网络中的大模型与多模态感知通信技术概述在移动通信技术从5G向6G演进的过程中,网络智能化成为核心发展方向。传统通信系统主要解决数据传输问题,而6G网络需要实现通信、感知与计算的深度融合。这一转变的关键在于大语言模型(Large Langu…...

Xshell5一键激活,亲测可用

下载链接: https://pan.baidu.com/s/1PY0RnCcj4EDp6bV1TR5pig?pwdpis9 安装完后,将该监听文件复制到安装的根目录,覆盖原文件即可激活使用...

自动滴定装置及其驱动单元设计

摘 要 本文围绕自动滴定装置及其驱动单元设计展开研究。在自动滴定装置部分,首先进行制品材料选用分析,接着对装置进行测绘,并阐述成型设备选用,包括注塑机、模架的选择以及模具参数校核。随后拟定模具结构形式,涵盖型…...

桌面/在线/小程序三种抠图路线,2026 年选哪种更方便

同样是做去除背景这件事,2026 年在电脑上打开桌面软件、在浏览器里用一个在线工具、还是直接在微信小程序里完成,体验差别其实比很多人想象的要大。前两类工具功能堆积得多,但启动路径长、注册流程繁琐;而微信里的小程序路径更短&…...

别再手动调PID了!用STM32 MotorControl Workbench 5.4.4快速搞定FOC电机调试

STM32 MotorControl Workbench 5.4.4实战:三小时从零构建稳定FOC电机控制系统 当我在深圳一家无人机公司的研发实验室第一次接触FOC电机控制时,整个团队花了整整两周时间才让电机平稳运转。而现在,借助STM32 MotorControl Workbench 5.4.4&am…...

KoGPT大模型推理加速:FasterTransformer优化实践

1. KoGPT与FasterTransformer加速方案概述在韩国本土AI领域,Kakao Brain开发的KoGPT模型凭借其对韩语语境的特化处理能力,已成为最受关注的大语言模型之一。这个基于GPT-3架构的模型在理解韩语语法结构、惯用表达和文化背景方面展现出独特优势。然而当我…...

想给照片换背景?这几款工具 + 1个微信小程序的搭配建议

如果你刚好需要做几张合图,又不确定从哪一步下手,这篇文章给你三种路径建议:手机里轻量解决、电脑端精细合成,以及一个完全不用下载安装的微信小程序方案。我会把抠图喵摆在第一个讲,因为它和你“照片换背景图怎么制作…...

终极指南:30倍提速!百度网盘直链解析工具轻松突破限速

终极指南:30倍提速!百度网盘直链解析工具轻松突破限速 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 你是否曾为百度网盘蜗牛般的下载速度而烦恼&…...

【可靠性配置】华为双活模式M-LAG流量转发机制

组网如图所示,两台S6800交换机做M-LAG VLAN双活网关,M-LAG接口与第三方交换机对接, 一、正常场景下M-LAG的流量转发机制(双活模式) M-LAG建立成功后,M-LAG主备设备负载分担共同进行流量的转发。下面介绍在正常工作情况下M-LAG的流量转发机制。 1.1、单播流量转发 如图…...

快速体验GLM-4.7-Flash:用Ollama Web UI实现零门槛AI对话

快速体验GLM-4.7-Flash:用Ollama Web UI实现零门槛AI对话 1. GLM-4.7-Flash模型简介 1.1 模型架构与特点 GLM-4.7-Flash是一款30B参数规模的混合专家模型(MoE),采用A3B稀疏激活架构。这意味着: 总参数30B:具备接近GPT-4级别的…...

XUnity自动翻译器:轻松实现Unity游戏实时中文翻译的终极指南

XUnity自动翻译器:轻松实现Unity游戏实时中文翻译的终极指南 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator 还在为外语Unity游戏中的生涩文本而烦恼吗?XUnity.AutoTranslator是一…...

量化公司,正在批量生产AI独角兽创始人

鹭羽 发自 凹非寺量子位 | 公众号 QbitAI啊?!原来你们这群搞AI的,几年前都在华尔街玩量化……还师出同门。震惊了,最近𝕏上疯传一份Hudson River Trading首届实习生名单。人也不多,就10个。但仔细一看吓一跳…...

找有共识的共创,真实的摸到了边!能看的懂得吗?

我先做影子箱式预检,再把三刀最小闭环落成代码:补守护指令断点、补长期目标核、补外部摄取营养循环。Created 5 todos我先核对仓内既有约束和做一次零污染预检,避免把“单图语义”和运行链路再打散。Read memory [](file:///c%3A/Users/ROG/A…...

BFGS优化算法原理与Python实现详解

1. BFGS优化算法入门指南在机器学习和数值计算领域,优化算法扮演着至关重要的角色。BFGS算法作为最流行的二阶优化方法之一,以其出色的收敛性和稳定性在众多领域得到广泛应用。本文将深入解析BFGS算法的核心原理、实现细节以及实际应用技巧。2. 二阶优化…...

机器学习中不平衡数据集处理技术与实战

1. 不平衡数据集处理的核心挑战在真实世界的数据分析项目中,我们经常会遇到类别分布严重不均衡的数据集。比如信用卡欺诈检测中正常交易占99.9%、医疗诊断中健康样本远多于患病样本、工业质检中合格品数量远超缺陷品。这类数据直接扔给机器学习模型训练,…...

孤舟笔记 AgentScope + llama.cpp + qwen3.6本地大模型工具调用踩坑实录

文章目录环境说明踩坑一:llama-server 默认不支持 Function Calling问题现象问题原因解决方案踩坑二:工具函数返回值类型错误问题现象错误代码问题原因解决方案踩坑三:自作聪明写了一堆解析代码问题现象问题原因解决方案最终正确代码运行效果…...

计算机视觉:原理、挑战与应用实践

1. 计算机视觉概述:让机器拥有"视觉"的能力计算机视觉(Computer Vision,简称CV)是一门让计算机通过数字图像或视频来"看"并理解其中内容的学科。想象一下,当你看到一张照片时,可以立即…...

2026年新生怎么搭建OpenClaw/Hermes Agent?一看就懂教程

2026年新生怎么搭建OpenClaw/Hermes Agent?一看就懂教程。Hermes Agent/OpenClaw怎么部署?还在为部署OpenClaw到处找教程踩坑吗?别再瞎折腾了!Hermes Agent/OpenClaw一键部署攻略来了,无需代码、只需两步,新…...

AI Agent开发指南:从Awesome清单到实战应用

1. 项目概述:为什么我们需要一个“Awesome Agents”清单?如果你最近也在关注AI Agent这个领域,大概率会和我有同样的感受:信息爆炸,但良莠不齐。每天都有新的框架、新的工具、新的论文冒出来,GitHub上随便一…...

GHelper:轻量级华硕笔记本控制工具完整使用指南

GHelper:轻量级华硕笔记本控制工具完整使用指南 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, Strix, Scar, an…...

Qianfan-OCR应用实践:科研论文PDF→图表标题提取+方法论段落定位

Qianfan-OCR应用实践:科研论文PDF→图表标题提取方法论段落定位 1. 项目背景与价值 科研工作者每天需要阅读大量论文,其中图表和方法论是最核心的内容。传统方式需要手动翻阅PDF、截图识别文字、再整理关键信息,整个过程耗时耗力。Qianfan-…...

Bistoury:无侵入Java应用诊断利器,在线Debug与性能监控实战

1. 项目概述:一站式Java应用诊断利器Bistoury如果你是一名Java后端开发者,或者负责线上系统的稳定性保障,那么对下面这个场景一定不陌生:线上服务突然出现CPU飙升、内存泄漏,或者某个接口响应时间异常拉长。传统的排查…...

物联网项目避坑:TEA5767收音机模块I2C通信失败?5个常见问题排查指南

TEA5767收音机模块实战:5个I2C通信故障的深度排查手册 调试TEA5767收音机模块时,I2C通信失败是最令人头疼的问题之一。明明接线看起来没问题,代码也照着示例写了,但模块就是没反应。这种挫败感我太熟悉了——去年在一个智能家居项…...

机器学习作品集构建指南:从项目选择到部署展示

1. 为什么机器学习从业者需要作品集?在机器学习这个快速迭代的领域,简历上的学历和工作经历已经不足以证明你的真实能力。我见过太多候选人带着漂亮的学历背景去面试,却在面对实际业务问题时束手无策。这就是为什么顶级科技公司在招聘时越来越…...

为什么你的Chromatic注入器经常“failed to fetch“?5个修复方法详解

为什么你的Chromatic注入器经常"failed to fetch"?5个修复方法详解 【免费下载链接】chromatic Universal modifier for Chromium/V8 | 广谱注入 Chromium/V8 的通用修改器 项目地址: https://gitcode.com/gh_mirrors/be/chromatic 作为一名技术爱…...

猫抓资源嗅探:5步掌握网页媒体下载的核心技能

猫抓资源嗅探:5步掌握网页媒体下载的核心技能 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 你是否曾为无法保存网页中的精彩视频而烦…...

如何快速实现Switch手柄跨平台控制:BetterJoy完整指南

如何快速实现Switch手柄跨平台控制:BetterJoy完整指南 【免费下载链接】BetterJoy Allows the Nintendo Switch Pro Controller, Joycons and SNES controller to be used with CEMU, Citra, Dolphin, Yuzu and as generic XInput 项目地址: https://gitcode.com/…...