串口设备数据的接收和处理.ppt

上传人:xt****7 文档编号:4259012 上传时间:2020-01-04 格式:PPT 页数:37 大小:824.81KB
返回 下载 相关 举报
串口设备数据的接收和处理.ppt_第1页
第1页 / 共37页
串口设备数据的接收和处理.ppt_第2页
第2页 / 共37页
串口设备数据的接收和处理.ppt_第3页
第3页 / 共37页
点击查看更多>>
资源描述
工控程序设计 学习情景2 2串口设备数据的接收和处理 学习情景2 2串口设备数据的接收和处理 2 2 1学习要点1 知识点 SerialPort类实例的构造 接收串口数据的方法 接收超时异常处理 HSDZC电能综合测试仪的数据格式 数据帧片段的缓存方法2 技能点 应用程序项目和SerialPort对象的创建 串口数据接收 接收数据的缓存和数据帧的提取2 2 2任务描述某些串口设备能够定时 主动地向上位机发送数据 处于上位机端的工业控制程序 需要获取串口收到的数据并进行分析和处理 利用 NETFramework2 0及更高版本提供的SerialPort类可以比较方便地在C 应用程序中实现串口通信功能 从编程的角度看 串口数据的接收就是利用SerialPort对象的Read或ReadByte方法将操作系统存放在串口输入缓冲区中的数据读入到一个字节数组中 该教学情景通过串口数据接收 接收数据的缓存 数据帧的提取 浮点数解码这几个实施步骤 达到使用SerialPort对象接收单个串口设备 下位机 数据的目的 学习情景2 2串口设备数据的接收和处理 2 2 3相关知识1SerialPort类实例的构造SerialPort类是从 NETFramework2 0版本开始提供的一个串口控制类 该类包含在System IO Ports命名空间中 使用该类的实例可以打开串口 并发送数据 通过构造函数可以产生SerialPort类的实例 SerialPort类的构造函数在定义时进行了重载 表2 2 1中列出了这些重载构造函数的接口定义 表2 2 1SerialPort类的构造函数定义 表2 2 1SerialPort类的构造函数定义 学习情景2 2串口设备数据的接收和处理 学习情景2 2串口设备数据的接收和处理 除了在构造SerialPort类实例的时候可以对端口名称 波特率 奇偶校验位 数据位和停止位进行设置外 构造好SerialPort类实例后 还可以通过PortName BaudRate Parity DataBits StopBits属性对这些参数进行修改 因此构造SerialPort类实例的程序书写形式比较灵活 2串口的打开和关闭SerialPort类中与串口打开和关闭相关的成员如下 1 Open方法Open方法打开新的串口连接 该方法不带参数 接口定义如下 publicvoidOpen 2 Close方法Close方法关闭已经打开的串口连接 该方法不带参数 接口定义如下 publicvoidClose 学习情景2 2串口设备数据的接收和处理 3 IsOpen属性通过IsOpen属性可以获知串口当前是否为打开状态 返回一个bool类型的值 该属性只读 接口定义如下 publicboolIsOpen get 串口不能重复进行打开和关闭操作 在打开或关闭串口前 都要使用该属性检查串口是否已经处于打开或已经处于关闭状态 以免引发异常 3接收串口数据的方法 1 ReadByte方法SerialPort类的ReadByte方法可以从串口接收缓冲区中读取一个字节 该方法的接口定义是 publicintReadByte 该方法从串口接收缓冲区中读取一个字节 要和ReadTimeout属性配合使用 当调用ReadByte方法时 如果接收缓冲区中没有数据 则程序被阻塞 直到缓冲区中有数据或到达ReadTimeout属性指定读取数据超时的毫秒数 程序才能继续运行 学习情景2 2串口设备数据的接收和处理 ReadByte方法返回一个int类型的值 在实际应用时 要将返回值强制转换为byte类型 2 Read方法Read方法从串口接收缓冲区中读取多个字节 该方法的接口定义是 publicintRead byte buffer intoffset intcount 该方法试图从接收缓冲区中读取count个字节 并写入字节数组buffer中 写入的起始位置是offset 执行后返回实际读取的字节数 例如 现在接收缓冲区中只有6个字节 但count参数值为10 则返回值为6 在实际应用时 通常先通过SerialPort对象的BytesToRead属性获得接收缓冲区中已有的字节数 并根据该属性值来设置count参数 和ReadByte方法不同的是 调用Read方法时 不管接收缓冲区中有无数据 都不会对应用程序的当前线程造成阻塞 学习情景2 2串口设备数据的接收和处理 4接收超时异常处理当使用ReadByte方法从接收缓冲区中读取一个字节时 如果下位机发送过来的数据没有在ReadTimeout规定的时间内到达 则会引发TimeoutException 应用程序可以捕获该异常 并作相应处理 下面的测试程序说明了超时异常处理的方法 SerialPortsp privatevoidbtnStart Click objectsender EventArgse bytefirstByte sp ReadExisting 清空接收缓冲区 准备接收数据sp ReadTimeout 10000 10秒内没有收到回复数据 将捕获到异常try firstByte byte sp ReadByte 同步读取 程序在此被阻塞 t1 Text firstByte ToString X2 显示在文本框t1中 catch TimeoutExceptionex 捕获到接收超时异常 t1 Text ex Message 在t1中显示异常信息 学习情景2 2串口设备数据的接收和处理 图2 2 1接收超时异常测试如上图所示 在点击 开始 按钮后 程序被阻塞 此时窗口对鼠标和键盘的输入都不响应 为了有足够操作时间 SerialPort对象sp的ReadTimeout属性为10000毫秒 10秒 在10秒时间内 测试者可以通过串口测试程序发送一个或多个字节过来 此时程序结束阻塞状态继续运行 并在文本框中显示接收到的第1个字节 如果10秒内没有数据到达 则引发TimeoutException 若上位机程序要一直等待 可以把ReadTimeout属性的值设置为 1 但在实际应用中一般不这样做 学习情景2 2串口设备数据的接收和处理 5HSDZC电能综合测试仪的数据格式HSDZC电能综合测试仪在钻机性能测试系统中用于输入功率 输出功率以及功率因素 参见引言介绍 该设备提供两种电脑测量方式 在仪表提示 测量方式 时 可以分别按 显示1 和 显示2 进入 在测量方式1的情况下测试仪每秒通过RS 232接口发送1组数据 长度46字节 信号格式 开始4字节均为FFH 后续每三个字节构成一个浮点数值 分别表示I1 U1 I2 U2 I3 U3 以及功率因数 视在功率 效率 输入功率 无功功率 负载率 输出功率 转速 共14个数据 在测量方式2的情况下测试仪也是每秒通过RS 232接口发送1组数据 长度30字节 信号格式 开始3字节均为12H 34H 56H 后续每三个字节构成一个浮点数值 分别表示I1 U1 P1 I2 U2 P2 I3 U3 P3 共9个数据 上位机在和HSDZC电能综合测试仪进行通信时 不需要向设备写入数据 而是被动地读取设备发送过来的数据 下面的相关知识将进一步介绍对已接收到数据的存储和处理方法 学习情景2 2串口设备数据的接收和处理 构成浮点数值的3个字节含义是 第1字节 B1 为尾数低位 第2字节 B2 为尾数高位 第3字节 B3 为阶码指数 其中阶码指数各位的含义如表2 2 2所示 表2 2 2阶码指数字节中各位的含义 学习情景2 2串口设备数据的接收和处理 尾数B的值在0到1之间 计算公式是 下面的HexToFloat函数描述了将3个字节转换为浮点数的算法 privatefloatHexToFloat byteB1 byteB2 byteB3 floatf B n B 尾数n 阶码指数B B2 256 B1 65536F if B3 学习情景2 2串口设备数据的接收和处理 6数据帧片段的缓存方法 1 使用集合类存储接收数据在通信过程中 数据帧表示由多个字节构成的 具有一定格式 表示完整语意的一组数据 例如 在和HSDZC电能综合测试仪进行通信时 如果测试仪工作在测量方式1 则一帧数据的长度为46个字节 包含起始标志和14个数值 在系统实际运行中 下位机向上位机发送数据时 可能会将数据帧分为几个片段依次发送 或者在一次接收到的数据中包含了不止一帧数据 上位机必须提供一个字节的集合来对接收到的数据进行缓存 暂存 在确认接收完毕一帧数据后 再进行进一步的分析和处理 NETFramework2 0以上版本提供了List类来实现集合元素管理 List类支持泛型 在存取byte类型的集合元素时无需进行 装箱 和 拆箱 操作 比使用ArrayList效率高 学习情景2 2串口设备数据的接收和处理 List类提供了丰富的方法来对集合中的元素进行操作 表2 2 3列出了List类的常用方法 表中的示例建立在如下定义的基础上 byteb byte ba Listli newList 创建List类的实例li 元素类型为byte表2 2 3List类的常用方法 学习情景2 2串口设备数据的接收和处理 学习情景2 2串口设备数据的接收和处理 学习情景2 2串口设备数据的接收和处理 2 集合大小的设置为了保证集合中任何时候能容纳一个完整的数据帧 集合中能容纳的字节数量应为数据帧长度的两倍 集合中的数据采取队列形式进行处理 新来的数据从队尾进 如果原有数据字节数加上新接收字节数超过集合的最大容量 则将队首的部份数据删除 图2 2 2展示数据入队和出队的过程 L 队列总容量N 原有字节数M 新接收字节数 1 队列剩余空间能容纳新接收数据L 队列总容量N 原有字节数M 新接收字节数 2 队列剩余空间能容纳新接收数据图2 2 2新接收数据的缓存 学习情景2 2串口设备数据的接收和处理 2 2 4任务实施1应用程序项目的创建串口通信应用程序的开发在VisualStudio集成开发环境中进行 首先创建一个基于C 语言的 Windows应用程序 项目 名为 ReceiveData 并存放在工作目录 F SerialPort 下 如图2 2 3所示 学习情景2 2串口设备数据的接收和处理 2SerialPort对象的创建创建SerialPort对象可以通过添加控件和编写代码两种方式 添加控件的方式相对简单 适合初学者练习 编写代码的方式具有较强的灵活性 可以把SerialPort对象对串口的操作细节隐藏起来 与数据编码 解码等功能一起封装为一个功能完整的串口通信模块 1 通过添加控件创建SerialPort对象在 工具箱 中展开 组件 选项卡 选择 SerialPort 组件 如图2 2 4 用鼠标拖动到设计视图中的窗口上 由于SerialPort是不可见组件 所以不直接出现在窗体上 而是出现在窗口下方 如图2 2 5所示 该操作的实质是在窗体设计器的源代码 文件名Form1 Designer cs 中添加了如下代码 privateSystem IO Ports SerialPortserialPort1 this serialPort1 newSystem IO Ports SerialPort ponents 实质上是定义并实例化了一个名为serialPort1的SerialPort对象 学习情景2 2串口设备数据的接收和处理 2 编写代码创建SerialPort对象切换到代码视图 在Form1 cs中编写上述代码同样可以创建SerialPort对象 首先在最前面引入System IO Ports命名空间 usingSystem IO Ports 然后定义SerialPort类的对象sp 作为Form1类的私有成员 privateSerialPortsp 最后在Form1类的构造函数中创建对象 publicForm1 InitializeComponent sp newSerialPort 学习情景2 2串口设备数据的接收和处理 2 2 4选择SerialPort组件 学习情景2 2串口设备数据的接收和处理 2 2 5将SerialPort组件加入窗体中当然 工程实践中 SerialPort对象不一定在窗体类中定义 如果项目代码量大 可以专门建立一个负责串口通信和调度的类 在里面定义一个或多个SerialPort对象作为该类的成员 学习情景2 2串口设备数据的接收和处理 3串口数据的接收在下面的程序中 当点击 开始接收 按钮时 程序调用SerialPort对象的ReadByte方法 阻塞当前线程 并开始接收下位机发送的数据 如果在10秒内接收到数据 则将接收到的数据以十六进制方式显示在文本框中 否则在文本框中显示 操作超时 异常提示 在编写程序之前 先在系统中安装虚拟串口对COM1和COM2 本程序连接COM1 串口测试程序连接COM2 程序界面如下图 图2 2 6串口数据的接收 学习情景2 2串口设备数据的接收和处理 其中文本框名字为t1 按钮名字为btnStart 对应的后台代码如下 privateSerialPortsp privatevoidForm1 Load objectsender EventArgse sp newSerialPort COM1 9600 Parity None 8 StopBits One sp Open privatevoidForm1 FormClosing objectsender FormClosingEventArgse if sp null 10秒内没有收到回复数据 将捕获到异常try 学习情景2 2串口设备数据的接收和处理 first byte sp ReadByte 同步读取 程序在此被阻塞 tmp newbyte sp BytesToRead 1 tmp 0 first sp Read tmp 1 tmp Length 1 读取剩余字节到tmp数组中 接收的数据以十六进制形式显示在文本框t1中t1 Text CCheck BinaryToHexString tmp catch TimeoutExceptionex t1 Text ex Message 在文本框t1中显示异常信息 学习情景2 2串口设备数据的接收和处理 以下代码包含在CCheck类中 publicclassCCheck 字节数组转换为十六进制字符串publicstaticstringBinaryToHexString byte buff StringBuildertmp newStringBuilder for inti 0 i buff Length i tmp Append buff i ToString X2 returntmp ToString Trim 学习情景2 2串口设备数据的接收和处理 该程序在点击 开始接收 按钮后会停止对用户输入的响应 这是因为调用ReadByte方法造成当前线程被阻塞 直到下位机发送的数据到达 或接收超时才解除阻塞 实际操作时 先运行该程序 再打开串口测试工具 并连接COM2 在测试工具中输入一些数据 做好发送的准备工作 在程序点击 开始接收 按钮后 立即切换到串口测试工具 并点击 发送 按钮 就可以在程序中看到发送过来的数据 发送 操作要在10秒内完成 否则会引起 接收超时 异常 4接收数据的缓存和数据帧的提取 1 创建数据接收队列CRecvBuf是一个用于缓存接收数据的类 利用List类来实现 在创建该类的实例时 要指定参数maxLength 表示队列的总容量 即图2 2 1中的参数L 每当接收到一段数据 就调用Add方法将收到的数据添加到队列中 Add方法中判断添加数据后字节数是否超过maxLength 并将超出部份从队首删除 学习情景2 2串口设备数据的接收和处理 classCRecvBuf publicListli publicintmaxLength publicCRecvBuf intmaxLength li newList this maxLength maxLength publicvoidAdd byte b if b Length maxLength thrownewException 接收到的数据量超出缓冲区长度 li AddRange b if li Count maxLength li RemoveRange 0 li Count maxLength 学习情景2 2串口设备数据的接收和处理 2 使用数据接收队列当HSDZC电能综合测试仪工作在 测量方式2 的情况下 使用下面的程序可以接收数据 并使用前面设计的CRecvBuf类的实例缓存接收到的数据 再从中提取出一个完整数据帧 程序运行界面如图2 2 7 2 2 7利用队列缓存接收数据 学习情景2 2串口设备数据的接收和处理 当按下 开始 按钮时 上位机准备接收数据 等待时间为10秒 此时通过串口测试程序按HSDZC电能综合测试仪工作在 测量方式2 时的数据格式 向上位机发送一个数据片段 上位机采用3个步骤处理接收数据 第1步接收到下位机发送的数据 第2步将接收的数据添加到队列中 第3步从队列中根据起始标志和约定数据长度提取出一个完整的数据帧 后台代码如下 privateSerialPortsp privateCRecvBufrecvBuf privatevoidbtnStart Click objectsender EventArgse bytefirstByte byte tmp sp ReadTimeout 10000 10秒内没有收到回复数据 将捕获到异常try firstByte byte sp ReadByte 读取第1个回复字节 程序在此被阻塞 学习情景2 2串口设备数据的接收和处理 tmp newbyte sp BytesToRead 1 tmp 0 firstByte sp Read tmp 1 tmp Length 1 读取剩余字节到tmp数组中t1 Text CCheck BinaryToHexString tmp 接收数据显示在文本框t1中recvBuf Add tmp 添加接收数据到队列中 显示队列中的全部数据t2 Text CCheck BinaryToHexString recvBuf getAllData 提取一个完整的数据帧tmp getBlock recvBuf li if tmp null t3 Text CCheck BinaryToHexString tmp 显示在文本框t3中elset3 Text 学习情景2 2串口设备数据的接收和处理 catch TimeoutExceptionex t1 Text ex Message 在t1文本框中显示异常信息 privatevoidForm1 Load objectsender EventArgse recvBuf newCRecvBuf 60 队列长度为数据帧长度的两倍sp newSerialPort COM1 9600 Parity None 8 StopBits One sp Open privatevoidForm1 FormClosing objectsender FormClosingEventArgse 学习情景2 2串口设备数据的接收和处理 if sp null 已经找到 接收循环if p 1 p为数据块的起始位置 学习情景2 2串口设备数据的接收和处理 b newbyte 30 li CopyTo p b 0 30 拷贝数据块到b数组 returnb 返回找到的完整数据帧 上面的代码已经获取到了一个完整的数据帧 根据 相关知识 中介绍的HSDZC电能综合测试仪的解码算法 可以把I1 U1 P1 I2 U2 P2 I3 U3 P3这9个浮点数值计算出来 具体实现的代码作为练习 由读者自己完成 学习情景2 2串口设备数据的接收和处理 2 2 5考核要点 学习情景2 2串口设备数据的接收和处理 2 2 6能力拓展1 使用SerialPort类要引入什么命名空间 如何创建SerialPort对象 2 SerialPort类的Read和ReadByte方法有什么区别 3 如何捕获并处理串口数据接收超时异常 4 为什么要定义一个队列来缓存接收到的数据 该队列如何实现 5 如何在队列中查找一个最新的 且完整的数据帧 6 根据HSDZC电能综合测试仪的浮点数编码格式 在 任务实施 第4个步骤的例子中增加一段代码 将解码后的I1 U1 P1 I2 U2 P2 I3 U3 P3这9个浮点数值显示在文本框t3中
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!