本帖最后由 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)
- #include "rtthread.h"
- #include "drivers/uart.h"
- #define UART_DEV_NAME "uart1"
- static rt_device_t uart_dev;
- static struct rt_semaphore uart_rx_sem; // 接收信号量
- // 串口接收回调
- static rt_err_t uart_input(rt_device_t dev, rt_size_t size) {
- rt_sem_release(&uart_rx_sem);
- return RT_EOK;
- }
- // 初始化串口(115200, 8N1)
- void uart_init(void) {
- rt_sem_init(&uart_rx_sem, "uart_rx", 0, RT_IPC_FLAG_FIFO);
- uart_dev = rt_device_find(UART_DEV_NAME);
- rt_device_open(uart_dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
- rt_device_set_rx_indicate(uart_dev, uart_input); // 设置接收回调
- }
- // 读取串口数据
- rt_size_t uart_read(uint8_t *buf, rt_size_t len) {
- return rt_device_read(uart_dev, 0, buf, len);
- }
- // 发送数据到串口
- rt_size_t uart_write(uint8_t *buf, rt_size_t len) {
- return rt_device_write(uart_dev, 0, buf, len);
- }
2. MQTT 客户端实现(mqtt_client.c)
基于 paho-mqtt-lite 库,实现连接、订阅、发布功能:
- #include "rtthread.h"
- #include "mqtt.h"
- #define MQTT_BROKER "mqtt://192.168.1.100:1883"
- #define MQTT_CLIENT_ID "ch32v307-uart-server"
- #define SUB_TOPIC "uart/recv" // 订阅:接收MQTT消息转发到串口
- #define PUB_TOPIC "uart/send" // 发布:串口数据发送到MQTT
- static MQTTClient client;
- static rt_thread_t mqtt_thread;
- // MQTT消息接收回调(转发到串口)
- static void mqtt_message_arrived(void *context, char *topicName, int topicLen, MQTTMessage *message) {
- rt_kprintf("MQTT recv: %.*s\n", message->payloadlen, (char*)message->payload);
- uart_write(message->payload, message->payloadlen); // 转发到串口
- }
- // MQTT连接函数
- static int mqtt_connect(void) {
- MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
- conn_opts.keepAliveInterval = 60;
- conn_opts.cleansession = 1;
- int rc = MQTTClient_connect(client, &conn_opts);
- if (rc == MQTTCLIENT_SUCCESS) {
- rt_kprintf("MQTT connected\n");
- MQTTClient_subscribe(client, SUB_TOPIC, 0); // 订阅主题
- return RT_EOK;
- }
- return -RT_ERROR;
- }
- // MQTT任务:循环处理消息
- static void mqtt_task(void *param) {
- MQTTClient_create(&client, MQTT_BROKER, MQTT_CLIENT_ID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
- MQTTClient_setCallbacks(client, NULL, NULL, mqtt_message_arrived, NULL);
- while (1) {
- if (mqtt_connect() != RT_EOK) {
- rt_thread_mdelay(2000); // 连接失败重试
- continue;
- }
- while (1) {
- rt_thread_mdelay(100); // 保持线程运行
- }
- }
- }
- // 初始化MQTT客户端
- void mqtt_client_init(void) {
- mqtt_thread = rt_thread_create("mqtt", mqtt_task, NULL, 2048, 8, 10);
- if (mqtt_thread) rt_thread_startup(mqtt_thread);
- }
- // 发布消息到MQTT
- void mqtt_publish(uint8_t *data, uint16_t len) {
- MQTTMessage msg = {0};
- msg.payload = data;
- msg.payloadlen = len;
- msg.qos = 0;
- MQTTClient_publishMessage(client, PUB_TOPIC, &msg, NULL);
- }
main
- #include "rtthread.h"
- #include "board.h"
- int main(void) {
- rt_kprintf("CH32V307 UART Server with MQTT\n");
-
- uart_init(); // 初始化串口
- mqtt_client_init(); // 初始化MQTT客户端
- forward_init(); // 初始化转发任务
- while (1) {
- rt_thread_mdelay(1000);
- }
- }
|