You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

ESP32通过UART读取DSMR5电表数据出现乱码问题求助

ESP32通过UART读取DSMR5电表数据出现乱码问题求助

看起来你在ESP32读取DSMR5电表P1口数据时碰到了乱码的棘手问题,我结合你的代码和DSMR5的特性,整理几个关键排查方向和修复建议:


1. 移除手动配置RX引脚的GPIO代码

你在app_main里手动把GPIO16(RX2)配置成了上拉输入,但UART驱动在调用uart_set_pinuart_driver_install后,会自动将引脚切换为UART功能模式,手动的GPIO配置很可能和驱动设置冲突,导致信号接收异常。直接删掉这段代码试试:

// 删掉以下这段冗余配置
gpio_config_t io_conf = {
    .intr_type = GPIO_INTR_DISABLE,
    .mode = GPIO_MODE_INPUT,
    .pin_bit_mask = (1ULL << 16),
    .pull_down_en = GPIO_PULLDOWN_DISABLE,
    .pull_up_en = GPIO_PULLUP_ENABLE,
};
gpio_config(&io_conf);

2. 确认DSMR5的通信参数是否匹配

虽然你设置了115200波特率、8N1参数,但部分DSMR5电表的P1口默认参数是9600波特率、偶校验(不同厂商的电表可能有差异)。可以先修改UART配置测试,同时把时钟源换成参考时钟提升波特率精度:

uart_config_t uart_config = {
    .baud_rate = 9600,  // 先尝试9600波特率
    .data_bits = UART_DATA_8_BITS,
    .parity = UART_PARITY_EVEN,  // 尝试偶校验
    .stop_bits = UART_STOP_BITS_1,
    .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
    .source_clk = UART_SCLK_REF_TICK,  // 用1MHz参考时钟减少波特率误差
};

另外,你不需要给电表发送数据,UART的TX引脚可以直接设为无变化,避免占用GPIO17:

ESP_ERROR_CHECK(uart_set_pin(2, UART_PIN_NO_CHANGE, 16, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));

3. 检查电平匹配问题(最常见的根源)

很多DSMR电表的P1口输出的是RS232电平(正负12V左右),而ESP32的UART只支持TTL电平(0-3.3V),直接接线会导致信号被严重扭曲,必然产生乱码。你需要在电表TXD和ESP32 RX之间加一个RS232转TTL模块(比如MAX3232芯片),把RS232信号转换成ESP32能识别的TTL信号。

4. 优化UART接收超时设置

你当前的uart_read_bytes超时是20ms,而DSMR5每秒钟发送一整帧数据,单帧接收时间可能超过20ms,导致数据被拆分接收(虽然不会直接导致乱码,但会影响数据完整性)。可以把超时时间改长到1000ms,确保能接收到完整的一帧:

int len = uart_read_bytes(2, data, (BUF_SIZE - 1), 1000 / portTICK_PERIOD_MS);

5. 硬件接线稳定性排查

  • 确保ESP32和电表的GND完全共地,共地不良会引入大量信号噪声;
  • 电表TXD到ESP32 RX的接线尽量短,最好用屏蔽线,减少电磁干扰;
  • 确认RTS引脚的3.3V供电稳定,DSMR5的RTS是有源高电平,只有RTS保持高电平时电表才会持续发送数据。

如果以上方法都试过还是有问题,建议用示波器或逻辑分析仪抓取电表TXD的信号波形,确认电平、波特率是否和你设置的参数一致,这样能快速定位是硬件还是软件的问题。

内容来源于stack exchange

火山引擎 最新活动