文章目录
引言
- 在完成老师的项目过程中,用到了Pcomm串口通信的库,这个库我是第一次接触,并不知道如何使用,甚至串口通信的需要设置那些参数都不知道。所以,专门写这篇文章,一方面学习一下串口通信,另外一方面记录一下Pcomm串口通信库的使用记录。
- 本文主要分为一下几个内容
- 串口通信的基本知识
- 使用Pcomm进行串口通信
正文
串口通信介绍
- 在串口通信中,数据是按照字节进行发送的,所以也叫做字节流通信。如果你要发送一段很长的报文,比如说“qwert”,会拆解成“q”,“w”,“e”,“r”,“t”,每一个字母都会作为一个单独的字节进行发送。
- 每一个发送单元都有以下几个要素
- 起始位:每一个字节开始的数据都有一个起始位,用于标识字节的开始,一般是1个或者是1.5个。
- 数据位:通常为8位,表示实际要传输的数据。8位就是ACSII码
- 校验位:可选,用于错误的检测
- 停止位:每一个字节的停止位置,用于标识字节的停止
- 最终按照上述配置,需要发送“qwert”,具体翻译如下
- ‘q’: 113 的二进制表示为 01110001
- ‘w’: 119 的二进制表示为 01110111
- ‘e’: 101 的二进制表示为 01100101
- ‘r’: 114 的二进制表示为 01110010
- ‘t’: 116 的二进制表示为 01110100
关于串口通信的缓冲区
- 串口通信的传输速率通常比较慢,所以需要设置数据缓冲区来提高通信的速率,其工作方式如下
- 自动发送
- 将数据通过write函数调用后,并不是直接发送,会将数据写入缓冲区。串口驱动程序会自动将缓冲区的数据发送到目标串口,并且随着发送,串口的数据会逐渐减少。
- 缓冲区大小
- 缓冲区的大小是固定的
- 一次性写入的数据超过了缓冲区大小,写入程序会陷入阻塞或者返回错误
- 不需要手动清空
- 串口驱动程序会自动将缓冲区的数据发送,然后清空已经发送的数据
- 刷新缓冲区
- 刷新缓冲区会将缓冲区的数据立即发送。
串口通信的基本流程
-
串口通信的具体流程如下
- 端口选择和配置
- 选择合适的串口端口
- 配置串口参数,包括波特率、数据位、停止位等
- 打开串口链接
- 使用相关库函数打开串口,并检验是否打开成功
- 初始化和握手(可选)
- 发送数据
- 将需要发送的数据写入串口中
- 设定发送的数据的帧结构、起始位置
- 接受数据
- 从串口读取数据,并解析特定的帧结构
- 错误检测和处理(可选)
- 使用奇偶校验、CRC等进行错误检测
- 流控制(可选)
- 使用硬件或者软件流控制来协调发送和接受速率
- 关闭串口链接
- 关闭串口链接,清理任何分配的资源
- 日志和监控(可选)
- 记录通信日志
- 端口选择和配置
-
按照这个流程,基本上,我需要设定的就是选择和配置串口,打开串口链接,发送和接受数据,以及关闭串口。
串口编程(使用Pcomm库)
- 这一节主要是描述使用Pcomm库,使用C++实现端口通信的指令
- 打开串口
- 输入:1,2,3,4分别表示COM1,COM2等常数
- 输出:0表示打开成功,否则打开失败
sio.open(port);
- 关闭串口
- 输入:1,2,3,4分别表示COM1,COM2等常数
- 输出:0表示打开成功,否则关闭失败
sio.close(port);
- 配置串口通信参数
- 输入:
- port端口号
- baud是波特率
- mode是校验位、数据位和停止位等数据的或
- 输出:
- 输入:
// 注意,这个mode是多个位置数位的或
sio.ioctl(port,baud,mode);
- 读取数据
- 输入
- port是端口号
- buf是缓冲区
- len是要读取的字符串长度
- 输出
- 0未收到字符
- 大于0表示收到的字符个数
- 输入
sio.read(port,buf,len);
- 设置等待间隔时间
- 输入
- port是端口号
- TotalTimeouts设定的等待时间
- IntervalTimesout每次读出的间隔时间
- 输出
- 0设置成功
- 输入
sio_SetReadTimeouts(int port, DWORD TotalTimeouts, DWORD IntervalTimeouts);
- 向串口缓冲区发送数据
- 输入
- port是端口号
- buf是缓冲区
- len是要读取的字符串长度
- 输出
- 0发送成功
- 输入
sio_write(int port, char *buf, int len);
- 清空缓冲区
- 输入
- port端口号
- func:0清空输入缓冲区,1清空输出缓冲区,2清空输入和输出缓冲区
- 输出
- 0发送成功
- 输入
sio_flush(int port, int func);
Pcomm Lite串口通信的封装
- 这里是将Pcomm这个库进行二次封装,方便进行调用。
- 私有成员函数中
- 主要是函数内部调用,实现将特定变量转成宏定义变量
- 在Pcomm.h文件中,将所有的变量尽心了宏定义
- 公有成员函数中
- 将所有的Pcomm用于串口通信的函数进行封装,包括打开串口、关闭串口、发送接受等,符合自己的编程习惯。
- 创建串口初始化函数,InitSerialPort,该函数实现打开并设置串口通信的参数,直接调用。
#ifndef _CWiINDOWSSERIALPORT_
#define _CWiINDOWSSERIALPORT_
#include <windows.h>
#include "Pcomm.h"
// 将Pcomm进行封装,进行方便直接调用
class CWindowsSerialPort
{
public:
CWindowsSerialPort();
~CWindowsSerialPort();
//打开并初始化串口,同时返回串口获取的结果
int InitSerialPort(int portid, int baudrate = 19200, int databits =8, int stopbits=1,int parity = 0);
int port_open();
int port_close();
// 将数据送入输出缓冲区,放入的长度根据缓冲区的空余空间决定
int port_send(char *buf, int len);
// 从输入缓冲区中读取特定长度的数据
int post_recv(char *buf, int datale);
// 获取输入缓冲区中的数据长度
int port_iqueue();
// 刷新缓冲区,数据立即发送。
int port_flush(int type);
private:
//波特率转换
int TranslateBaudRate(int baudrate);
//停止位转换
int TranslateStopBits(int n);
//校验设置
//0:不进行奇偶校验,1:奇校验,2:偶校验
int TranslateParity(int n);
//数据位转换
int TranslateDatabits(int n);
private:
int m_nPortId;
};
#endif
- 二次封装
- 这次封装,是建立在我们一次封装的基础上进行的,调用串口通信的一些指令,然后完成控制指令的交互,具体实现如下的功能
- CTransStatus:完成配置文件的读取,初始化传串口,初始化捕获状态指令的内容
- SendCaptureStatus:发送图片捕捉的具体状态信息
- RecvCaptureCmd:获取PLC发送过来的控制命令
这段就不公开了,这段是别人给的代码,就不公布了
串口通信编程
- 对于串口通信需要能够实现如下要求
- 能够通过串口发送信息和接收信息
- 能够调用多线程,实现对于接收信息的回调处理。
安装和设置PCOMM Lite串口编程动态库
-
和opencv一样,需要安装对应的串口编程开发包,这里参考这个链接,直接下载安装
-
在VS 2023中进行设置,具体参考这篇博客
-
真恶心,用vs2023配置了半天,就是不行,头文件里面定义的函数都是报错,找不到对应的库文件,但是我已经来回检查过了,而且试了两种方式,还是找不到,索性就用原来已经调整好的项目吧。之前一打开没有任何问题,头文件和库文件都在当前项目的目录下方,不应该会出现问题的。
本地串口模拟
-
手里没有相关的设备,这里使用了一些串口模拟软件,在本地模拟一个串口进行通信。
-
这里使用了Virtual Serial Port Driver Pro软件,具体链接,这里并没有花时间去使用破解版,可以试用两周 。两周之后的我的硬件肯定到了。
-
Virtual Serial Port Driver Pro使用链接,串口模拟软件,在本机模拟串口通信
-
除此之外,这里还使用了SCCOM这个串口检测软件,用于数据通信,具体链接. 这个软件是图型操作界面,添加串口之后,可以直接使用图形界面进行串口通信。
-
添加串口
- 这里添加了com 7和com 8,并且二者实现互联。可以在设备管理器中看到。
- 这里添加了com 7和com 8,并且二者实现互联。可以在设备管理器中看到。
-
图形界面串口通信模拟
- 增加了两个串口之后,进行传后通信模拟。直接选择com 7和com 8,然后设置相同的波特率,发送信息如下。
- 增加了两个串口之后,进行传后通信模拟。直接选择com 7和com 8,然后设置相同的波特率,发送信息如下。
-
编程通过串口发送信息
- 这里打开一个界面com7,然后将COM2和COM7链接,通过COM2向COM7发送数据,可以看到数据随着线程的运作正常发送。
- 这里仅仅是往队列中添加了很多很多重复的信息,可以看到成功通信。
- 但是这里仅仅实现了单向通信,还需要对程序进一步完善,向别的串口发送了信息
-
编程通过串口接收信息
- 这里配置和上一节相同,都是使用相同的串口配置和端口号。
- 如下图,能够成功接收到不同串口发送来的信息,接收到了控制指令。
- 正常的流程是什么样?单独一个线程,不断循环等待,是否接收到修改线程的命令,然后在修改某一个参数,进而判定是否需要打开捕捉图片的功能。还是说直接在捕捉图片的线程中,增加一个循环,知道遇到控制命令触发。
总结
- 通过网上搜集资料大概知道了串口通信的基本方式,打开并配置端口,然后发送信息,接受信息,无非就是多了一些状态码。
- 通过这个函数,来看别人封装的代码,就清晰多了。
- 这里直接给出了PComm的说明文档,可以自己下载,
链接: https://pan.baidu.com/s/1CWgvRrg2ZeiCsodRe7o0tw 提取码: 949e
–来自百度网盘超级会员v3的分享