STM32 通过 USART2 驱动 ESP8266 AT 指令,代码发送 AT 指令模块返回ERROR;但是电脑串口助手直接发完全正常。硬件层面排查:供电加 AMS1117,电流充足,接线引脚无误。

根因

printf重定向函数fputc写了自动补\r的逻辑:

int fputc(int ch, FILE *f)
{
  if (ch == '\n')
  {
    HAL_UART_Transmit(&huart2, (uint8_t *)&"\r", 1, 1000); 
  }
  HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 1000); 
}

代码里调用printf("%s\r\n", cmd)发送 AT 指令,输出字符序列:cmd内容 + \r + \n。 当\n触发 if 判断,额外插入一个\r,最终发给 ESP8266 的结束符变成 \r\r\n。 ESP8266 AT 固件只识别\r\n作为指令结束标志,多余回车导致指令解析失败,返回 ERROR。

重点区分两种写法:

  1. fputc 自动补\r:printf 只需要写%s\n,不要手动加\r
  2. fputc 不做任何字符替换:printf 才用%s\r\n

修复方案

修改 fputc,原样转发字符,去掉自动添加\r的逻辑,并且补齐标准返回值:

int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 1000);
  return ch;
}

代码架构说明

  • 使用 USART2 与 ESP8266 通信,串口中断接收,全局缓冲区存储模块应答,strstr匹配应答字符串
  • ESP8266_SendAT自带 3 次重试,每次发送前清空接收缓存,函数内部通过 printf 追加\r\n作为 AT 指令结尾
  • OneNET 物模型上传使用AT+MQTTPUBRAW,下发 AT 命令收到 OK 之后,直接发送 JSON 载荷,载荷不能带任何换行符
  • MQTTUSERCFG 参数保持原有配置不变,MQTT 连接应答要匹配+MQTTCONNECTED,不是CONNECT

其他潜在隐患(后续优化)

  1. 全局 buffer 在中断写、主循环同时读取,存在并发竞争,会造成应答识别不稳定、超时
  2. 初始化函数不要重复调用,MQTT 会话建立后重复执行 AT 初始化指令会报错
  3. sprintf 拼接字符串注意数组长度,防止缓冲区溢出产生乱码

调试顺序建议

  1. 修改 fputc 代码下载
  2. 单独测试最简单AT指令,确认返回 OK
  3. 依次测试 AT+CWMODE、AT+CWJAP、MQTTUSERCFG、MQTTCONN
  4. 最后调用 OneNET_PubRaw_Multi 上传物模型数据

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐