一、软件概述
串口通信广泛应用于嵌入式linux系统及单片机等工业控制场景。本文阐述的多路串口通信软件开发设计基于黑金ZYNQ-AC7021B平台,Petalinux 2017 系统,FPGA-PL端实现8路RS485串口转换芯片电路,并发接受SCP1168震动传感器数据,ARM-PS端通过linux多线程异步IO实时调度处理把8路数据解析且保存十进制文本数据。
二、上位机程序
上位机SCP1168 MCU转发放大电平数据和发送震动传感器数据,其中震动传感器发送3组坐标数据ADC fifo数组,发送至UART buff,电压信号差分放大。UART BUFF Write接口到串口。主要实现流程与接口函数:
三、接收机程序
3.1 接收机程序设计概述
3.1.1设计概述
下位机接受多路传感器数据程序主要包括内容,设置多个串口参数,打开串口,读取串口;linux多线程读取串口数据,运用linux IO Select或poll完成异步检测串口,定时获取串口数据及字节长度;linux多线程crc16校验串口数据,运用串口状态机解析单帧数据,帧头,payload,crc字段及与本机crc校验是否一致;linux多线程保存文件,运用多线程互斥或同步机制把crc校验数据写到文件;互斥保存数据并按照特定格式转换十进制文件;以及参数配置文件和日志文件等。
3.1.2 技术指标
主要技术指标,8路RS485串口,2Mbps传输速率,116500 串口驱动采样传输;MCU 20k采样率对接放大电路和8路震动传感器,实时传输8路震动数据和温度数据;每帧1208个字节长度,有帧头AA 55位2个字节,4字节温度数据,有效数据300组连续X,Y,Z坐标值共600字节,以及包含CRC校验位2个字节构成。
3.1.3开发工具
开发环境
VMware1604:
VMware16.1.0 build-17198959
UBUNTU1604LTS:
Linux ubuntu 4.15.0-142-generic #146~16.04.1-Ubuntu SMP Tue Apr 13 09:27:15 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
交叉编译环境设置
Xilinx Software Development Kit
Xilinux开发工具
FPGA设置串口
Vivado 2017.4,uart11650,MicroBraze IP核
Xilinx-ZYNQ:
ALINX AC7021B
MCU:
SCP1168 sensor
NFS网络存储配置
3.2 主要模块设计
3.2.1 RS485串口设置模块
打开8个串口,运用linux fopen,fread,fclose 接口函数操作串口 ,以termios属性设置串口传输协议参数。其中,串口参数设置以串口属性结构体对象termios optons配置串口波特率,校验位,停止位等主要参数。
3.2.2 数据帧解析模块
3.2.2.1 解帧原理
考虑数据帧同步,解决方法就是引入帧同步字节,也就是增加帧头、帧尾等,对于固定长度数据帧通信可以只使用帧头帧尾,对于可变长度数据帧通信还需引入描述帧长的字节。利用帧头、帧尾、帧长即可解决。数据帧差错控制,解决方法即用CRC校验。
3.2.2.2单帧格式
解析每帧1208个字节长度,有帧头AA 55位2个字节,4字节温度数据,有效数据300组连续X,Y,Z坐标值共600字节,以及包含CRC校验位2个字节构成,其中CRC校验数据包含帧头和有效数据共计1208个字节,并在 Linux 多线程中完成。
3.2.2.3解帧状态机
串口状态机解帧流程:
状态机是指一个状态集合和一组状态转移规则,用于解析串口数据并提取出完整的帧数据。状态机要包含一个状态变量,表示当前状态是哪个。初始状态通常是“等待帧头”,当接收到帧头时,则进入下一状态“读取有效数据”;当接收到校验位时,则进入下一状态“检查校验和”;当校验和不正确时,则返回初始状态重新等待帧头。多线程循环解析多路串口的每一帧数据。
实现解析读取有效数据流程:
一旦进入“读取有效数据”状态,就需要读取连续的300组X,Y,Z坐标数据。使用一个计数器,记录已经读取了多少个数据,当读取完成后再进入下一状态“检查校验和”。最后一个状态是“检查校验和”,需要计算数据包含帧头和有效数据的校验和,与接收到的两个字节的校验值比较。如果校验和不对,则返回初始状态等待下一帧数据。
状态机切换流程:
串口状态机确定5种状态,分别是:状态0等待接收帧头第1字节0xAA;状态1等待接收帧头第2字节0x5A;状态2等待接收数据字节,共计300组坐标数据600个字节;状态3等待接收校验字节高8位1个字节;状态4等待接收校验字节低8位。
状态之间如何有效切换能保证流程最简化和数据处理最可靠,接收到0xAA->接收到0x5A->接收到0xAA;接收到非0xAA非0x5A;接收到1202字节数据;接收到命令字节且长度字节为0;接收到校验字节高8位;接收到校验字节低8位;校验正确,保存校验数据传递数据解析接口函数;校验不正确丢弃处理或帧补偿处理接口流程。
3.2.3 数据帧CRC校验模块
单帧数据解析流程,即在串口解析状态第五步时,把含有帧头内的1206字节数据由指针传递给CRC-16接口函数,实现基于CRC-16/XMODEM x^16+x^12+x^5+1算法校验,取得2字节CRC校验值与原接收帧CRC字段比较,如一致则数据帧正确,否则丢弃该帧数据。
计算CRC-16/XMODEM校验值的函数。它通过对输入的数据使用CRC-16/XMODEM算法来计算校验和。函数中的循环通过将输入数据逐字节处理,使用查找表将每个字节与当前校验和进行计算。循环结束后,最终的校验和存储在变量cksum中。接下来,通过将校验和的高字节与低字节进行交换,得到反转后的校验和cksum_reversal。最后,函数返回反转后的校验和作为结果。
3.2.4 保存CRC数据模块
单帧数据解析完成,创建写文件保存CRC校验数据,此时保存一帧数据1208字节包含CRC校验值。如是多路写保存文件,需要添加互斥锁保证单路文件完整保存。此文件数据可作为后面进制转换备用。
3.2.5 数据帧转换十进制模块
把CRC校验后数据有十六进制转换为十进制,单帧数据前需要添加当前时间标记,CRC校验标记,串口通道ID标记,300组坐标数据以一组XYZ为一行换行且以逗号分隔;六个字节坐标数据分别做进制移位算法操作。
单个坐标数值转换方法,使用循环迭代 datas 数组,从索引为 2 开始,每次递增 6(每个数据包含 6 个字节)。在每次循环中,将两个字节的数据 datas[j] 和 datas[j+1] 合并为一个数据 num_x,然后提取高字节和低字节分别保存在 byte1 和 byte2 中,并将它们组合为最终的分析结果 result_x,类似的推导出坐标,对 num_y 和 num_z 进行相同的操作。把转换后十进制坐标值保存文件方法,使用 fprintf 函数将分析结果 result_x、result_y 和 result_z 以逗号分隔的形式写入文件。
3.2.6 多线程读写串口模块
3.2.6.1 Linux select IO模型读写
多线程间数据通信及互斥读写文件设计实现,共享内存和线程传参实现方式。Linux 多线程Select IO 轮询接受串口数据互斥保存文件,线程间内存共享数据实现方案。
3.2.6.2 Linux poll IO模型读写
Linux 多线程Poll IO 轮询接受串口数据互斥保存文件,线程间内存共享数据实现方案。
3.2.6.3 Linux IRQ 软中断模型读写
Linux 多线程软件IRQ中断轮询接受串口数据互斥保存文件,线程间内存共享数据实现方案。
3.2.6.2 FPGA-MicroBraze核地址映射模型读写
Linux 多线程FPGA-PL端串口寄存器指针映射ARM-PS轮询接受串口数据互斥保存文件,线程间内存共享数据实现方案。
线程间内存共享数据实现方案
多内存块拷贝
共享消息队列
FIFObuff数据块
3.2.7 多文件大小检测模块
基于linux 文件系统会有单个文件读写超过2G大小时会不能保存限制,需要把保存数据文件保存一定大小,定时创建目录新建文件机制解决此问题。为此,新开发文件大小检测方法,每一分钟7M文件大小,以mac地址后三位加当前时间组合命名新文件,以时间命名文件夹,同时8个文件保存,结合NFS网络存储8路传感器数据。
3.2.8 配置文件模块
实现程序首次运行则创建ini配置文件,写入默认配置参数及数值,再次打开修改配置参数,程序读取配置参数传入程序生效运行。
Ini配置文件设置多级字段,多级字段匹配关键字段解析实现。
3.2.9 日志文件模块
日志打印函数及创建日志保存文件,日志打印函数添加到需要打印程序段中,独立创建和保存打印程序流程等消息。
3.2.10 web服务模块
配合petalinux系统httpd服务器与本应用程序融合参数传递到web应用实现重要参数读取或写入配置。主要包括网络配置,串口ID配置管理及任意使能,串口数据监测统计等功能。
单路串口读写测试。