浅谈分布式多节点嵌入式系统中RS485总线指令冲突解决及性能优化

一、问题

RS485总线多节点竞争总线时,是否遇到过,由于缺乏冲突检测机制,发生指令冲突?系统实时性如何保障?如何解决了?采用主从轮询方式?同样也会因高延迟加剧冲突!笔者在项目开发过程中就遇到过这样的问题,既要保证实时性,又要解决总线指令冲突,同时还不能修改硬件,只能通过软件去改善这个问题。

二、背景

简单先介绍下项目背景,系统节点共15个,都是独立的功能模块,模块间通过RS485通讯,系统是封闭的,因此通讯协议采用的是自定义。主控模块可以控制子模块启停,同时子模块还会将运行状态上传到总线,子模块相互间写作也是通过指令控制,系统复杂度可想而知。

三、解决方案

下面聊聊是如何解决这个"既要、又要、同时还"的问题的。
先来谈谈总线指令冲突的改善的解决思路。想要解决指令冲突问题,先对系统通讯协议做了下了解,协议的一帧是定长的;在从模块的中断回调函中分析,可以通过指令字判断当前是否有指令在接收。因此,在接收指令时设置一个标志位g_tx_block_flag,模块要发送指令时先检测这个标志位是否有效,有效暂停发送,无效则发送指令。所有子系统都参照这个修改,从而有效改善指令冲突的问题。

复制代码
 void user_rs485_bus_callback(uart_callback_args_t *p_args)
{
    /* TODO: add your own code here */
    uint8_t data;
    g_rs485_uart_event = (uint8_t)p_args->event;

    if(UART_EVENT_RX_CHAR == p_args->event)
    {
        data = (uint8_t)p_args->data;
        if((data == FRAME_KEY)&&(g_rx485_index==0)){
            g_rx485_tmp_buff[g_rx485_index++] = data;
            g_tx_block_flag = true;
        }
    }
}

其次,对系统性能优化。通过对协议的分析,总线上传输的大量消息中,并不是所有的指令都与子系统相关,通过总线消息过滤,可以减少节点子系统的处理负担,提高系统效率,并能确保关键指令能够在子系统中得到及时的处理。

复制代码
//接收指令过滤,仅处理与子系统相关的指令
bool rx_cmd_filtering(uint8_t cmd_data)
{
    bool retValue=false;
    switch(cmd_data)
    {
        case RX_CMD_FILTER_A0:
        case RX_CMD_FILTER_A1:
        case RX_CMD_FILTER_A2:
        case RX_CMD_FILTER_A3:
            retValue=true;
            break;
    }
    return retValue;
}

/* Callback function */
void user_rs485_bus_callback(uart_callback_args_t *p_args)
{
    /* TODO: add your own code here */
    uint8_t data;
    g_rs485_uart_event = (uint8_t)p_args->event;

    if(UART_EVENT_RX_CHAR == p_args->event)
    {
        data = (uint8_t)p_args->data;
        if((data == FRAME_KEY)&&(g_rx485_index==0)){
            g_rx485_tmp_buff[g_rx485_index++] = data;
            g_tx_block_flag = true;
        }
        else if(g_rx485_index==1)
        {
            if(rx_cmd_filtering(data))
                g_rx485_filter_sate = 1;    //当前子系统有指令需要处理
            else
                g_rx485_filter_sate = 0;
            g_rx485_tmp_buff[g_rx485_index++] = data;
        }
        else
        {
            g_rx485_tmp_buff[g_rx485_index++] = data;

            if((g_rx485_index+1)>FRAME_LEN)
            {
                g_rx485_index=0;
                if(g_rx485_filter_sate)
                {
                    xQueueGenericSendFromISR(g_485buf_queue, g_rx485_tmp_buff, NULL, queueSEND_TO_BACK); 
                    g_tx_block_flag = false;
                }
            }
        }
    }
}

有兴趣的小伙伴,可以下载工程了解下

项目工程下载链接:
https://download.csdn.net/download/xtudj/90474572

相关推荐
明达智控技术12 小时前
告别停机内卷!热插拔远程IO,解锁工控运维新范式
分布式·物联网·自动化
漂着的圆木12 小时前
MCP 2026-07-28 长任务改造:别再用 HTTP 超时判断任务失败
分布式·架构·状态模式·ai agent
嵌入式阿蔡14 小时前
CoAP / LwM2M 轻量协议:受限设备为什么不用 MQTT
单片机·物联网·嵌入式
数智启示录18 小时前
Apache Kafka Consumer 扩到 40 个仍不提速:Partition 上限锁死有效并行度 【Kafka合集】
数据库·经验分享·分布式·缓存·面试·kafka·apache
数智启示录18 小时前
Apache Kafka 幂等 Producer 的边界:Exactly-Once 到了 MySQL 为什么失效 【Kafka合集】
数据库·经验分享·分布式·mysql·面试·kafka·apache
数智启示录19 小时前
Apache Kafka 不只是消息队列:日志与 Offset 分离如何让事件可重放 【Kafka合集】
经验分享·分布式·面试·kafka·apache
数智启示录19 小时前
Apache Kafka 同 Key 仍会乱序:从分区 Offset 到业务可见的四道边界 【Kafka 合集】
大数据·数据库·经验分享·分布式·面试·kafka·apache
BYSJMG19 小时前
大数据毕业设计选题推荐:基于大数据的全球气温历史演变分析与可视化,用Hadoop+Spark处理
大数据·hadoop·分布式·信息可视化·spark·kmeans·课程设计
爱吃苹果的梨叔19 小时前
AI 算力监控中心怎么建?分布式坐席 + 大屏联动 + 过程回放
人工智能·分布式·python
無a伟19 小时前
RabbitMQ :与AMQP的关系、核心组件、交换机类型
分布式·rabbitmq