[单片机芯片] 基于 CH32V307 的串口服务器(支持 MQTT)系统设计

[复制链接]
152|0
abner_ma 发表于 2025-10-31 22:02 | 显示全部楼层 |阅读模式
本帖最后由 abner_ma 于 2025-10-31 22:04 编辑


一、概述

CH32V307 作为沁恒微电子针对物联网和工业通信场景设计的高性能 MCU,其网络功能是核心亮点之一,尤其在集成度、易用性和性能上表现突出,非常适合构建低成本网络终端设备(如串口服务器、物联网网关、工业数据采集节点等)CH32V307 集成了10/100M 以太网 MAC(媒体访问控制层)和 PHY(物理层),支持 RMII(简化媒体独立接口),无需外接独立以太网芯片(如 LAN8720)。相比需要外挂 PHY 的 MCU(如 STM32F103),可减少 PCB 面积约 30%,降低硬件成本(省去 PHY 芯片及外围电路),同时减少信号传输延迟。串口服务器的核心功能是实现串口数据与 MQTT 协议的双向转发,基于 CH32V307(RISC-V 内核,支持高速外设)硬件平台,结合 FreeRTOS/RT-Thread 实时操作系统实现多任务调度,主要模块包括:





模块

功能描述

硬件驱动层

串口(UART)、以太网(ETH)、定时器驱动

网络协议层

LwIP 协议栈(TCP/IP)、MQTT 客户端(paho-mqtt)

数据转发层

串口与 MQTT 消息的双向解析 / 转发逻辑

配置管理层

串口参数(波特率 / 校验位)、MQTT 参数配置


二、硬件设计要点  
CH32V307 核心外设配置:
串口:使用 UART1(PA9/PA10),支持最高 4Mbps 波特率,配置 DMA 提升吞吐
以太网:内置 MAC+PHY(RMII 接口),外接网络变压器
存储:SPI Flash(W25Q 系列)存储配置参数(掉电保存)
电源:3.3V 供电,支持 5V 串口电平转换


三、软件架构(RT-Thread 系统)  采用分层设计,基于 RT-Thread 的组件化框架:

    应用层
mqtt_client:MQTT连接/订阅/发布
serial_forward:串口-MQTT数据转发
config:参数配置(CLI命令/Flash存储)
    协议层
LwIP:TCP/IP协议栈
MQTT:paho-mqtt-lite客户端
      驱动层
uart:串口驱动(DMA+中断)
eth:以太网驱动
spi_flash:配置存储
四、核心代码实现    1. 串口驱动初始化(uart.c)

  1. #include "rtthread.h"
  2. #include "drivers/uart.h"

  3. #define UART_DEV_NAME "uart1"
  4. static rt_device_t uart_dev;
  5. static struct rt_semaphore uart_rx_sem; // 接收信号量

  6. // 串口接收回调
  7. static rt_err_t uart_input(rt_device_t dev, rt_size_t size) {
  8.     rt_sem_release(&uart_rx_sem);
  9.     return RT_EOK;
  10. }

  11. // 初始化串口(115200, 8N1)
  12. void uart_init(void) {
  13.     rt_sem_init(&uart_rx_sem, "uart_rx", 0, RT_IPC_FLAG_FIFO);
  14.     uart_dev = rt_device_find(UART_DEV_NAME);
  15.     rt_device_open(uart_dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
  16.     rt_device_set_rx_indicate(uart_dev, uart_input); // 设置接收回调
  17. }

  18. // 读取串口数据
  19. rt_size_t uart_read(uint8_t *buf, rt_size_t len) {
  20.     return rt_device_read(uart_dev, 0, buf, len);
  21. }

  22. // 发送数据到串口
  23. rt_size_t uart_write(uint8_t *buf, rt_size_t len) {
  24.     return rt_device_write(uart_dev, 0, buf, len);
  25. }


2. MQTT 客户端实现(mqtt_client.c)
  基于 paho-mqtt-lite 库,实现连接、订阅、发布功能:

  1. #include "rtthread.h"
  2. #include "mqtt.h"

  3. #define MQTT_BROKER "mqtt://192.168.1.100:1883"
  4. #define MQTT_CLIENT_ID "ch32v307-uart-server"
  5. #define SUB_TOPIC "uart/recv"   // 订阅:接收MQTT消息转发到串口
  6. #define PUB_TOPIC "uart/send"   // 发布:串口数据发送到MQTT

  7. static MQTTClient client;
  8. static rt_thread_t mqtt_thread;

  9. // MQTT消息接收回调(转发到串口)
  10. static void mqtt_message_arrived(void *context, char *topicName, int topicLen, MQTTMessage *message) {
  11.     rt_kprintf("MQTT recv: %.*s\n", message->payloadlen, (char*)message->payload);
  12.     uart_write(message->payload, message->payloadlen); // 转发到串口
  13. }

  14. // MQTT连接函数
  15. static int mqtt_connect(void) {
  16.     MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
  17.     conn_opts.keepAliveInterval = 60;
  18.     conn_opts.cleansession = 1;

  19.     int rc = MQTTClient_connect(client, &conn_opts);
  20.     if (rc == MQTTCLIENT_SUCCESS) {
  21.         rt_kprintf("MQTT connected\n");
  22.         MQTTClient_subscribe(client, SUB_TOPIC, 0); // 订阅主题
  23.         return RT_EOK;
  24.     }
  25.     return -RT_ERROR;
  26. }

  27. // MQTT任务:循环处理消息
  28. static void mqtt_task(void *param) {
  29.     MQTTClient_create(&client, MQTT_BROKER, MQTT_CLIENT_ID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
  30.     MQTTClient_setCallbacks(client, NULL, NULL, mqtt_message_arrived, NULL);

  31.     while (1) {
  32.         if (mqtt_connect() != RT_EOK) {
  33.             rt_thread_mdelay(2000); // 连接失败重试
  34.             continue;
  35.         }
  36.         while (1) {
  37.             rt_thread_mdelay(100); // 保持线程运行
  38.         }
  39.     }
  40. }

  41. // 初始化MQTT客户端
  42. void mqtt_client_init(void) {
  43.     mqtt_thread = rt_thread_create("mqtt", mqtt_task, NULL, 2048, 8, 10);
  44.     if (mqtt_thread) rt_thread_startup(mqtt_thread);
  45. }

  46. // 发布消息到MQTT
  47. void mqtt_publish(uint8_t *data, uint16_t len) {
  48.     MQTTMessage msg = {0};
  49.     msg.payload = data;
  50.     msg.payloadlen = len;
  51.     msg.qos = 0;
  52.     MQTTClient_publishMessage(client, PUB_TOPIC, &msg, NULL);
  53. }
main
  1. #include "rtthread.h"
  2. #include "board.h"

  3. int main(void) {
  4.     rt_kprintf("CH32V307 UART Server with MQTT\n");
  5.    
  6.     uart_init();         // 初始化串口
  7.     mqtt_client_init();  // 初始化MQTT客户端
  8.     forward_init();      // 初始化转发任务

  9.     while (1) {
  10.         rt_thread_mdelay(1000);
  11.     }
  12. }






您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:项目经理
简介:资深嵌入式开发工程师

111

主题

199

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部