FreeModbus学习——接收状态机xMBRTUReceiveFSM

news2024/9/28 5:30:13

FreeModbus版本:1.6

接收状态机xMBRTUReceiveFSM

在协议栈初始化时,会发现有两个接收函数

peMBFrameReceiveCur = eMBRTUReceive;

pxMBFrameCBByteReceived = xMBRTUReceiveFSM;

那么这两个接收函数哪个是状态机?它俩有什么区别呢?
在这里插入图片描述
xMBRTUReceiveFSM这个是接收状态机函数。

FSM是finite-state machine的缩写,即有限状态机。

看一下这个函数在哪里调用
pxMBFrameCBByteReceived = xMBRTUReceiveFSM;

在portserial.c文件中,会发现pxMBFrameCBByteReceived 被prvvUARTRxISR调用。
在这里插入图片描述
prvvUARTRxISR这个函数是串口接收中断时调用的。

串口接收中断由用户实现,比如这样
在这里插入图片描述
所以接收状态机的调用顺序是这样的

接收到字节 →
中断服务函数 →
prvvUARTRxISR →
pxMBFrameCBByteReceived →
xMBRTUReceiveFSM

先看一下接收状态机都有什么状态

typedef enum
{
    STATE_RX_INIT,              /*!< Receiver is in initial state. */
    STATE_RX_IDLE,              /*!< Receiver is in idle state. */
    STATE_RX_RCV,               /*!< Frame is beeing received. */
    STATE_RX_ERROR              /*!< If the frame is invalid. */
} eMBRcvState;

分别是初始化态,空闲态,接收态,错误态。

来看一下接收状态机的实现xMBRTUReceiveFSM

BOOL
xMBRTUReceiveFSM( void )
{
    BOOL            xTaskNeedSwitch = FALSE;
    UCHAR           ucByte;

    assert( eSndState == STATE_TX_IDLE );

    /* Always read the character. */
    ( void )xMBPortSerialGetByte( ( CHAR * ) & ucByte );

    switch ( eRcvState )
    {
        /* If we have received a character in the init state we have to
         * wait until the frame is finished.
         */
    case STATE_RX_INIT:
        vMBPortTimersEnable(  );
        break;

        /* In the error state we wait until all characters in the
         * damaged frame are transmitted.
         */
    case STATE_RX_ERROR:
        vMBPortTimersEnable(  );
        break;

        /* In the idle state we wait for a new character. If a character
         * is received the t1.5 and t3.5 timers are started and the
         * receiver is in the state STATE_RX_RECEIVCE.
         */
    case STATE_RX_IDLE:
        usRcvBufferPos = 0;
        ucRTUBuf[usRcvBufferPos++] = ucByte;
        eRcvState = STATE_RX_RCV;

        /* Enable t3.5 timers. */
        vMBPortTimersEnable(  );
        break;

        /* We are currently receiving a frame. Reset the timer after
         * every character received. If more than the maximum possible
         * number of bytes in a modbus frame is received the frame is
         * ignored.
         */
    case STATE_RX_RCV:
        if( usRcvBufferPos < MB_SER_PDU_SIZE_MAX )
        {
            ucRTUBuf[usRcvBufferPos++] = ucByte;
        }
        else
        {
            eRcvState = STATE_RX_ERROR;
        }
        vMBPortTimersEnable(  );
        break;
    }
    return xTaskNeedSwitch;
}

初试化态:
协议栈使能后,会将接收状态机赋值为初始化态,串口接收使能,且定时器也使能(重新计数),定时器进入溢出中断,然后会将接收状态机由初始化态变为空闲态。

如果刚使能后,串口就接收到数据了怎么办?

我们无法判断这个数据是不是帧首,所以这一帧就舍掉。

在这里插入图片描述
当接收状态机状态为初始化态,接收到一个数据,进入接收状态机,不存储这个数据,而是重启定时器。再接收,再重启,直到这一帧完成(帧与帧之间会有个时间间隔),然后进入定时器中断,将接收状态机变为空闲态,并发布ready事件,代表协议栈就绪。

也就是说接收状态机为空闲态时,才开始接收第一个数据作为帧首。
在这里插入图片描述
当接收状态机为空闲态时,开始接收第一个数据作为帧首,然后将接收状态机置为接收态,重新计数定时器。

当接收状态机为接收态时,将存到的每一个数ucByte都放入缓存ucRTUBuf中,且重置定时器。

那么它是如何与协议栈的事件机制结合的呢

在这里插入图片描述
我们知道,在每一次进入接收状态机xMBRTUReceiveFSM,不管什么状态,都会重置定时器。

当接收状态机为接收态时,每接收到一个数据,都会重置定时器。

直到 这一帧 接收完成

然后进入定时器中断

在定时器中断里,会先发出事件 EV_FRAME_RECEIVED 即帧接收完成。然后再将接收状态机置为空闲态

然后在轮询函数eMBPoll中,看到事件EV_FRAME_RECEIVED ,开始处理事件。

使用peMBFrameReceiveCur这个函数,将一帧数据读取出来
在这里插入图片描述

所以peMBFrameReceiveCur和xMBRTUReceiveFSM的区别是

xMBRTUReceiveFSM用于在串口接收中断中读取数据。

peMBFrameReceiveCur用于接收完一帧后,将这一帧取出来。

处理帧数据后要发送响应帧,这时会将关闭串口接收中断,使能串口发送中断。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1975232.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux:Xshell相关配置及前期准备

一、Linux的环境安装 1、裸机安装或者是双系统 2、虚拟机的安装 3、云服务器&#xff08;推荐&#xff09;——>安装简单&#xff0c;维护成本低&#xff0c;学习效果好&#xff0c;仿真性高&#xff08;可多人一起用一个云服务器&#xff09; 1.1 购买云服务器 使用云服…

Linux 内核源码分析---块设备

磁盘&#xff08;disk&#xff09;是指利用磁记录技术存储数据的存储器。 磁盘是计算机主要的存储介质&#xff0c;可以存储大量的二进制数据&#xff0c;并且断电后也能保持数据不丢失。早期计算机使用的磁盘是软磁盘&#xff08;Floppy Disk&#xff0c;简称软盘&#xff09;…

LeetCode Hot100实战之双指针

公众号&#xff1a;自学编程村&#xff0c;回复“书籍”&#xff0c;领取1000多本计算机书籍。涵盖语言语法、数据结构算法、AI相关书籍、开发相关等等各种书籍&#xff0c;应有尽有&#xff0c;你总会用到。 回复“C语言”&#xff0c;领取原创C语言九讲PDF教程&#xff08;数…

功能实现——通过阿里云 OSS 实现文件管理

目录 1.需求分析2.阿里云 OSS 开通与配置2.1.登录阿里云官网2.2.搜索 OSS 服务并开通2.3.OSS 配置 3.在项目使用阿里云 OSS3.1.项目环境搭建3.2.代码实现3.2.1.将本地文件上传到阿里云 OSS3.2.2.将前端传入的文件上传到阿里云 OSS3.2.3.下载文件到本地2.3.4.流式下载3.2.4.OSSC…

携程酒店、景点、评论数据采集,testab动态js加密参数处理不补js环境不纯算

携程平台的酒店、景点、评价数据还是比较有意义的&#xff0c;可用作数据分析研究&#xff0c;目前均可采集。酒店价格需要登录采集&#xff0c;其他店名、地址、经纬度、评分、评价数、特色标签等都可以直接采集。 携程酒店数据示例&#xff1a; 酒店id&#xff1a;536424 …

免费【2024】springboot 大学生在线论坛系统的设计与实现

博主介绍&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围&#xff1a;SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化…

常用配置文件 .ini、.config、 json、xml

ini Initialization INI文件格式是某些平台或软件上的配置文件的非正式标准&#xff0c;以节(section)和键值对(key-val)构成&#xff0c;常用于微软Windows操作系统中。 这种配置文件的文件扩展名多为INI 》》INI文件不支持数据类型&#xff0c;所有的键值对都是字符串类型…

[SQLSERVER][SQL]数据库备份任务异常

SQL备份异常出现如下错误&#xff1a; 执行查询“BACKUP DATABASE [ReportServerTempDB] TO DISK N...”失败&#xff0c; 执行查询“BACKUP DATABASE [ReportServerTempDB] TO DISK N...”失败&#xff0c; 错误如下:“无法打开备份设备 E:\\sqldatabackup19\\Report_ba…

nose2,一个无敌的 Python 库!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个无敌的 Python 库 - nose2。 Github地址&#xff1a;https://github.com/nose-devs/nose2 在软件开发过程中&#xff0c;自动化测试是保证代码质量的重要环节。Python 提供…

Python(模块)

模块编写完成就可以被其他模块进行调用并使用被调用模块的功能。 import导入方式的语法结构&#xff1a; import模块名称【as别名】 from……import导入方式的语法结构&#xff1a; from模块名称&#xff0c;import变量/函数/类/*&#xff08;*是通配符&#xff09; impor…

非线性磁链观测器

前面已经介绍了龙伯格观测器、滑膜观测器&#xff1a;龙伯格观测器&#xff08;又称状态观测器&#xff09;、滑膜观测器-CSDN博客 滑膜观测器和龙伯格观测器都是没法实现电机的超低速运转、0速启动、超高速的正反方向的运行。龙伯格观测器是可以实现这些功能&#xff0c;但是…

Resolving Maven dependencies

Maven是一种项目管理和构建工具&#xff0c;通常用于Java项目。这个过程包括下载项目所需的所有外部库和插件&#xff0c;并将它们添加到项目的构建路径中。具体来说&#xff0c;它正在处理名为“AAS_byBasyx”的项目或模块的依赖项。这种任务通常在你打开一个新的Maven项目或更…

基于web的购物网站的设计与实现(系统源码+lw+部署文档+讲解等)

文字目录&#xff1a; 目录 详细视频演示 系统实现界面 1.1系统开发环境以及运行环境 1.1.1系统开发环境 1.1.2系统运行环境 1.2系统功能实现 1.3管理员模块实现 2 技术介绍 2.1 thinkphp5介绍 2.2 MySQL数据库 2.3 B/S结构 4.1系统结构设计 4.2系统功能结构设计…

​JavaWeb入门——Servlet(二)

目录 HttpServletRequest 简介 常见API HttpServletResponse 简介 常见API 请求转发和响应重定向 概述 请求转发 响应重定向 cookie&session 会话 会话跟踪方案&#xff1a; 会话跟踪方案对比&#xff1a; 1、Cookie 2、Session&#xff08;底层基于Cookie…

RocketMQ5.0消费者

RocketMQ 5.0 提供了三种主要的消费者类型&#xff1a;PushConsumer、SimpleConsumer 和 PullConsumer。每种类型的消费者都有其特定的使用场景和特点。以下是对这三种消费者的概念及其区别的详细阐述&#xff1a; PushConsumer 概念&#xff1a; PushConsumer 是一种主动推送…

Python time模块5大隐藏特性

特性一&#xff1a;结构化时间——struct_time 简介&#xff1a; struct_time是time模块中的一个数据类型&#xff0c;用于存储一个时间的各个组成部分&#xff08;年、月、日、时、分、秒等&#xff09;。它常用于解析和格式化时间。 代码示例&#xff1a; import time # …

GA4(Google Analytics 4 )升级指南丨出海笔记

Google Analytics 4 是与之前的Universal Analytics/GA3完全不同的全新版本&#xff0c;2023下半年(7月后)会全面替换UA。 本篇指南将会展示如何安装和使用 Google Analytics 4 (GA4), 以便大家更好的迁移并使用新平台。相比GA3, GA4绝对是好东西&#xff0c;这次的内容比较硬核…

Linux基于centOS7【内存与OS的随谈】,进程初学【PCB】【fork】【进程排队】

冯诺依曼体系结构——存储器 存储器主要指的是内存&#xff0c;它有个特点就是掉电易失 磁盘等其它输入和输出设备 为什么要在计算机体系结构中要存在内存 我们知道&#xff0c;CPU的处理速度很快很快&#xff0c;但输入设备&#xff0c;以及输出设备&#xff0c;是相对很慢的…

C#对Sqllite操作

前言 数据库的操作也是程序设计中的家常便饭了&#xff0c;关系型数据库中Sqlite3是非常轻量级别的&#xff0c;所以这个数据在小型应用程序的设计中占用很高的比重。当然我这里描述的是1.0版本&#xff0c;也是最原始的方案&#xff0c;大型应用开发中一般选择EF进行桥接&…

信息学奥赛初赛天天练-54-CSP-J2019阅读程序3-二叉树、满二叉树、单侧二叉树、二分查找、递归、等差数列求和

PDF文档公众号回复关键字:20240803 2019 CSP-J 阅读程序3 1阅读程序(程序输入不超过数组或字符串定义的范围&#xff1b;判断题正确填 √&#xff0c;错误填 。除特殊说明外&#xff0c;判断题 1.5 分&#xff0c;选择题 3 分&#xff0c;共计 40 分) 01 #include <iostre…