SCI串行异步通信与MODBUS-RTU协议

文章介绍了280025C芯片的SCI串口通信原理,SCI通讯格式,MODBUS通信规约,并分享了作者在实际应用中基于SCI的MODBUS协议的处理方法,确保消息通信的准确性。
摘要由CSDN通过智能技术生成


前言

CCS的各种第一代,第二代,第三代芯片的问世,从封装及外设功能上不断优化,缩小了成本但是提高了芯片性能。虽然国产的芯片目前无法与它媲美,但是作为嵌入式的出入门径的小新,先用好漂亮国的片子,再有机会给国产片做贡献吧(好像在痴人说梦),总之希望国产片能越来越好,实现弯道超车,从而彻底摆脱外国芯片卡脖子。

本文主要讲解本人对280025C芯片的SCI的理解,MODBUS-RTU的理解,如有错误之处敬请各位博友私信指正。

一、SCI串口通信介绍

串口通信即SCI就是平时所说的UART,是一个双线异步串行端口。SCI模块支持CPU和其他适应标准不归零格式的异步外围设备间的数字通信。SCI的接收器和发送器各自拥有一个16级深度的FIFO,可独立运行在半双工或者联合运行在全双工通信。

二、SCI通讯格式

SCI异步通信格式既可以使用单线通信,也可以使用双线通信。在此模式中,帧由1位起始位、1~8位数据位,1位可选择的奇偶校验位和1~2位停止位构成。每个数据位占8个SCICLK时钟周期。接收器在收到有效的起始位后开始工作,一个有效的起始位由四个连续的内部SCICLK周期的低电平来确定。如果没有连续的低电平,处理器就会重新启动便于开始寻找新的起始位。(有个问题:在多个处理器通信时是否需要判断总线的状态是否忙碌,这个问题一直困扰我)

三、MODBUS通信规约

MODBUS通信是一种广泛应用于电子控制器之间的一种通用语言,通过此协议,控制器之间相互可以通信。此协议定义了一个控制器能够认识使用的消息结构,可分为两种数据传输模式,ASCII与RTU模式。大体分为地址域,功能域,数据域,CRC校验域。在此不再赘述详细MODBUS协议内容,可自行上网查询。

四、基于SCI的MODBUS协议的经典应用

经过学习与总结,利用队列探索了一套常用的,不丢帧的通信程序(自己称作三指针法),大体流程如下:

1)、消息接受

1、新建三个指针Uint16 *pbBufHead;    Uint16 *pbBufDeal;    Uint16 *pbRptr;与一个接受消息的队列(他们都叫Buffer,但是我不习惯这么中英混着叫,有点装逼的感觉)。

2、初始化指针都指向队列的头

    UartHost.pbBufHead = UartHost.ReceBuf; //指针初始化
    UartHost.pbBufTail = UartHost.ReceBuf; //指针初始化
    UartHost.pbBufDeal = UartHost.ReceBuf; //指针初始化
    UartHost.pbRptr    = UartHost.ReceBuf; //指针初始化

3、根据MODBUS协议判断接收消息的每个字节,由于一个完整的数据帧都是由地址域+功能域+数据域+校验域构成,所以需要判断出4个字节的信息是否满足MODBUS协议。当接受到一个消息时,数据被存放在队列ReceBuf中,UartHost.pbBufDeal++是关键,只有判断接受帧的地址位正确,才会判断下一个字节,否则该字节被直接抛弃。

    //以查询方式接收
    if(ScicRegs.SCIRXST.bit.RXRDY == 1)
    {
        *UartHost.pbRptr++ = ScicRegs.SCIRXBUF.all;    // Read data
        if (UartHost.pbRptr >= (UartHost.ReceBuf + MAX_RECE_BUF_LEN))
            UartHost.pbRptr = UartHost.ReceBuf;

    }

此时判断如果UartHost.pbBufDeal!=*UartHost.pbRptr则说明有数据放入消息队列,开始一个字节一个字节的判断,

void Class_HostModbusComm::fnHostFrameJudge()
{
        '''

    while(UartHost.pbBufDeal!= UartHost.pbRptr)
    {
        switch(UartHost.ReceSta)
        {
        case 0:
            if(*UartHost.pbBufDeal ==objDigitalIO.m_st_wLocalSignal2.bModuleID)//需要加地址
            {
                UartHost.pbBufHead = UartHost.pbBufDeal;
                fram_len = 0;
                UPS_ID_NUM=objDigitalIO.m_st_wLocalSignal2.bModuleID;
                tmpbuf[fram_len++] = *UartHost.pbBufDeal;
                UartHost.ReceSta++;
            }
            break;
      ...//省略

            default:
                fnHostErrCode();
                fram_len = 0;
                UartHost.ReceSta = 0;
                break;

        }

        UartHost.pbBufDeal++;
        if( UartHost.pbBufDeal >= (UartHost.ReceBuf + MAX_RECE_BUF_LEN) )
        {UartHost.pbBufDeal = UartHost.ReceBuf;}
    }

2)、接受消息处理

首先判断地址,功能码,最后判断CRC校验码,当收到一个完整的帧后,开始执行此步骤,否则将不会进入消息的发送。

3)、消息发送

一样采用指针++的方法进行消息发送,根据接收到的命令选择不同的消息发送命令,发送一个字符(完整的串口帧1位起始位+8位数据位+1位奇偶校验位+1位停止位)后指针++.


总结

以上只是对串口通信及MODBUS的简单介绍,但是经过一个星期的磨练,已经成功将上述的消息处理的方法应用于产品,消息通信校通率完全满足工业要求,不会存在漏帧、误判的情况。值得各位同仁与博友借鉴,如果想要完整代码可与我联系,我将很高兴与大家共享。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值