通信协议

  串行通信接口(如RS232、RS485等)作为计算机与单片机交互数据的主要接口,广泛用于各类仪器仪表、工业监测及自动控制领域中。

  通信协议是需要通信的双方所达成的一种约定,它对包括数据格式、同步方式、传送速度、传送步骤、检纠错方式以及控制字符定义等问题作出统一规定,在双方的通信中必须共同遵守。在实际应用系统中,如果缺少一个严格、合理、规范的串口通信协议,将无法保证数据传输的正确性及通信的可靠性。

  因此,需要提出一种基于状态机串口通信协议的设计方法:通过合理地设置数据包格式来保证了数据传输的正确性:引入了状态机方法,简化了协议的实现难度,提高了通信的可靠性,同时使通信过程具有较高的容错能力。


定义数据包格式

  串口通信中最小的的信息单元是数据帧。一个数据帧通常包括起始位、数据位、结束位,另外还可以包含用于检测传输错误的“奇偶校验位”,每个数据帧中传输的数据位可以有5、6、7、8或9个。
  实际通信过程中,数据的发送是一帧一帧地进行,当被传输的数据超过一帧时(例如浮点型数据),如果没有对数据帧进行必要的打包,发送出去的数据将会很难被数据接收方解释与分析,进而造成数据传输混乱与错误。因此,在一般应用中有必要将数据帧组装成数据包再发送。

  1. 起始标志表示开始接收一个新的数据包。
  2. 数据长度命令和附加数据共占的字节数。设置此字段,可方便接收方识别数据包的长度并能够准确地接收数据包。
  3. 命令用来说明数据包的用途。
  4. 附加数据 当命令不同时,含义不同。
  5. 校验是对命令字段与附加数据字段的所有字节数据的异或校验。
  6. 结束标志表示该数据包结束。

  另外,在多机通信中,数据包中还应增加源地址与设备地址等字段。


通信状态机

状态机简介

  状态机由事物所处的状态及引发状态变化的外部事件两部分组成。

  在软件编程中,事物所处的状态可以描述为某个程序片断或函数,而引发状态变化的处部条件可以理解为条件判断语句,当条件为真时,事物的状态发生变化。事物发生变化前的状态称为现态,变化后的状态称为次态,程序中可以通过不同的数字对不同的状态进行编号。现态到次态的变化可以通过状态变量值的改变来描述。
  在协议中需要传输的基本信息单元是数据包,数据包一般包含多个数据帧。实际传输过程中,数据的传输通常是一帧一帧地进行,数据包是被拆分成若干帧数据后再进行传输,数据接受方也是分帧接受一个数据包。

  数据接受方在解释与分析数据包时可能存在两个问题:

1.识别并接收完整的数据包

  • 对于数据接收方,一个数据包是分若干批到来,在识别包头与包尾时,也就是帧同步问题;
  • 具体编程时存在难度,特别对于已接收部分与未接收部分以及数据接收的进度及状态的处理。

2.数据传输时的容错能力

  • 数据传输过程中已经出现错误时,系统应该具有摆脱错误状态,恢复到正常状态的能力。
  • 例如,当一个数据包只传输完一部分时,因为未知故障,下一个数据包就开始传输,系统应该能识别出传输错误,抛弃前一个出错的数据包,并且能正确接收下一个数据包。
  • 实际编程时处理这种问题难度较大,结果很可能会出现将第一个数据包的前一部分与第二个数据包的前一部分拼装成一个新的数据包的情况,这就损失了两个数据包,最严重的结果可能是系统无法从错误中恢复,这就严重降低了系统的安全性与可靠性。

  为解决上面的两个问题,在协议中引入了状态机。

  在状态机中,状态的变化依赖于外部触发条件,当条件满足时,状态将发生变化。

  在协议中将数据包接收的各个阶段定义为不同的状态,将接收一帧新的数据或数据处理的结果作为外部触发条件,从而达到状态改变的目的,最终完成一个数据包的接收与校验。


串口通信状态图

  串口通信协议中,发送数据包时一般不需引入状态机,这主要是为提高发送速率和简化编程模型而考虑。

  在协议中主要针对数据接收过程建立状态机。

  


串口通信数据接收过程

  1. 当未开始接收数据包或发现数据传输出错时,系统进入空闲状态;
  2. 当数接收到数据包起始标志时,变为收到起始标志状态,如果收到的数据不为起始标志,系统继续保持空闲状态;
  3. 进入收到起始标志状态后,新接收到的任何数据将被当作数据包中命令与附加数据的总字节数(记为LEN),系统进入收到数据长度状态;
  4. 继续接收新的数据,直至接到新收到的数据总字节数达到LEN +2,进入检验结束标志状态;
  5. 这时可以检验结束标志是否为协议定义的标志值,如果是,说明传输正确,否则传输出错,出错后应查找接收缓冲区中本数据包的起始标志后有无其它起始标志,如果没有发现起始标志,系统应进入空闲状态,否则应直接进入接收到起始标志状态,这样可提高系统容错能力,方便系统从错误中恢复。
  6. 检验结柬标志正确后,进入数据校验状态;
  7. 校验结果如果正确,数据包接收完成,否则说明传输出错,系统进入空闲状态。

上位机软件编程逻辑

  上位机软件中,当接收到数据时,串口控件会触发一个事件,在事件处理代码中应及时将收到的数据存入接收冲区,同时不应该把串口通信协议接收部分的代码放置在此事件中,否则后面到来的数据可能因为前面先到的数据没有及时处理完毕而被冲掉,导致数据丢失。

  1. 在上位机软件运行时,应该启动一个Windows线程,用于不断检测接收缓冲区是否为空,不为空时则对缓冲中的数据进行处理;
  2. 线程类创建好后,应具体编写线程类执行函数的处理过程,在其中通过状态指示变量sp实现状态机机制;
  3. 数据包的接收进度依据于状态指示变量sp。

  当数据接收顺利时,sp的变化将会引导完成一个数据包的接收过程。这样处理可以简化编程的模型,使协议易于实现;数据包接收过程中,一旦发现数据传输出错,立即将sp置为0(空闲状态),也就是状态复位,使系统进入准备接收下一个数据包的状态,这样可提高通信过程的可靠性及容错能力。


状态机机制实现

{------------------------------
@功能:状态机机制实现串口通讯
@author:成鹏致远
@net:lcw.cnblogs.com
-------------------------------}
procedure TBufferThread.Execute;
var
s,a :string;
sp,mylen,oddEvenCheck,i :integer;
begin
sp :=; {指示读数据状态}
a :='';
while True do
begin {quelist为接收缓冲区}
if quelist.Count <> then {缓冲区取数}
begin
s :=quelist.Strings[];
quelist.Delete();
a :=a+s;
end;
if a='' then Continue;
{是否空闲状态}
if sp = then
begin
if ord(a[]) =0xFE then
begin
sp :=; {进入到起始标志状态}
end
else {起始标志错误}
begin end;
Delete(a,,);
end
{是否进入收到起始标志状态}
else if sp = then
begin
mylen :=Ord(a[]);
sp :=; {进入长度状态}
Delete(a,,);
end
{是否进入长度状态}
else if sp = then
begin
if Length(a) <=mylen + then Continue;
{数据结束标志:正确}
if ord(a[mylen +])=0xFD then
begin
sp :=; {进入数据校验状态}
end
else {数据结束标志:错误}
begin
sp :=; {重新进入空闲状态}
end;
end
{是否进入数据校验状态}
else if sp = then
begin
for i:= to mylen do
begin
oddEvenCheck :=a[] xor a[i];
end;
if oddEvenCheck =Ord(a[mylen +]) then
begin
sp :=; {校验正确,进入完成状态}
end
else {检验错误,进入空闲状态}
begin
sp :=;
end;
end
else if sp = then
begin
{这里省略处理命令与附加数据代码}
sp :=; {进入空闲状态}
Delete(a,,mylen+);
end;
end;
end;

【Delphi】基于状态机的串口通信的更多相关文章

  1. 基于FPGA自适应串口通信(Auto Baud Rate)

    做的课设,相当于复习了一遍verilog. 实现了 1.接收端固定模式:8N1 BAUD:921600. 2.发送端8N1,任意波特率(不取极端值). 3.数码管显示波特率(16进制). 用了 1.两 ...

  2. QT5 TK1 串口通信

    对TK1中基于QT5的串口通信过程进行总结.按照软件安装及通信实现的顺序. 1.QT5安装 较简洁方式:打开软件中心(类似A形),搜索qtcreator,点击安装即可. 2.串口通信库安装 采用上述方 ...

  3. 基于FPGA的红外遥控解码与PC串口通信

    基于FPGA的红外遥控解码与PC串口通信 zouxy09@qq.com http://blog.csdn.net/zouxy09 这是我的<电子设计EDA>的课程设计作业(呵呵,这个月都拿 ...

  4. VS2008基于对话框的MFC上位机串口通信(C++实现)简单例程

    首先,在 vs2008 环境下创建 MFC 运用程序 设置项目名称为 ComTest(这个地方随意命名,根据个人习惯),点击确定后,点击下一步 出现如下界面 选择"基于对话框"模式 ...

  5. Delphi 串口通信(1)

    利用 Delphi实现串口通信的常用的方法有 3种: 一是利用控件,如 MSCOMM控件和 SPCOMM控件: 二是使用 API函数: 三是调用其他串口通信程序.其中利用 API编写串口通信程序较为复 ...

  6. [python] 3 、基于串口通信的嵌入式设备上位机自动测试程序框架(简陋框架)

    星期一, 20. 八月 2018 01:53上午 - beautifulzzzz 1.前言 做类似zigbee.ble mesh...无线网络节点性能测试的时候,手动操作然后看表象往往很难找出真正的原 ...

  7. C#中缓存的使用 ajax请求基于restFul的WebApi(post、get、delete、put) 让 .NET 更方便的导入导出 Excel .net core api +swagger(一个简单的入门demo 使用codefirst+mysql) C# 位运算详解 c# 交错数组 c# 数组协变 C# 添加Excel表单控件(Form Controls) C#串口通信程序

    C#中缓存的使用   缓存的概念及优缺点在这里就不多做介绍,主要介绍一下使用的方法. 1.在ASP.NET中页面缓存的使用方法简单,只需要在aspx页的顶部加上一句声明即可:  <%@ Outp ...

  8. (转载)用vs2010开发基于VC++的MFC 串口通信一*****两台电脑同一个串口号之间的通信

    此文章以visual C++数据採集与串口通信測控应用实战为參考教程 此文章适合VC++串口通信入门 一.页面布局及加入控件 1, 安装好vs2010如图 2, 新建一个基于VC++的MFC项目com ...

  9. [stm32][ucos] 1、基于ucos操作系统的LED闪烁、串口通信简单例程

    * 内容简述: 本例程操作系统采用ucos2.86a版本, 建立了5个任务            任务名                                             优先级 ...

随机推荐

  1. ios中封装九宫格的使用(二级导航)

    效果图 一般用于导航功能 第一步下载http://pan.baidu.com/share/link?shareid=1824940819&uk=923776187 第二步 把下图内容放在你的x ...

  2. [转]最好用的 AI 开源数据集 Top 39:NLP、语音等 6 大类

    原文链接 本文修正部分错误. 以下是精心收集的一些非常好的开放数据集,也是做 AI 研究不容错过的数据集. 标签解释 [经典]这些是在 AI 领域中非常著名.众所周知的数据集.很少有研究者或工程师没有 ...

  3. Delphi单元文件引用名称问题

    Delphi新版本的单元文件格式变化了,如windows变成了winapi.windows,如果想在单元引用中使用简称,则需要在工程选项中配置: 这样就可以使用全名或简写来引用单元了.

  4. maven中跳过单元测试

    Maven 提供了跳过单元测试的能力,只需要使用 Surefire 插件的 skip 参数. 在命令行,只要简单的给任何目标添加 maven.test.skip 属性就能跳过测试: $ mvn ins ...

  5. mysql--SQL编程(关于mysql中的日期,实例,判断生日是否为闰年) 学习笔记2.1

    关于日期处理的实例: 从mysql给出的 example 这个是官方源码下载以及导入,http://dev.mysql.com/doc/employee/en/employees-installati ...

  6. 根据自身经验总结的一个IT时间管理

      2012-11-13 内容存档在evernote,笔记名"根据自身经验总结的一个IT时间管理"

  7. CentOS 7 systemd的坑

    一.概述 在从 CentOS 6 迁移到 CentOS 7 的过程中,可能有一些地方需要调整,最显著的地方莫过于 systemd 带来的改变,不同的管理服务的方式,不同的日志方式,设置时区,时间等等. ...

  8. ASP.NET Core Linux环境安装并运行项目

    原文地址:https://blog.csdn.net/u014368040/article/details/79192622 一 安装环境 1.  从微软官网下载 Linux版本的.NetCoreSd ...

  9. Swift2.0语言教程之函数嵌套调用形式

    Swift2.0语言教程之函数嵌套调用形式 Swift2.0语言函数嵌套调用形式 在Swift中,在函数中还能够调用函数,从而形成嵌套调用.嵌套调用的形式往往有两种:一种是在一个函数中调用其它函数:还 ...

  10. 【转载并整理】mysql 1293错误 建表两个timestamp

    http://www.jb51.net/article/50878.htm 这里要使用到mysql的触发器