admin管理员组文章数量:1613755
1. 串口通信流程
不管是对于windows还是linux,串口通信的流程都是以下4步:
1. 打开串口
2. 设置串口
3. 发送、接收数据
4. 关闭串口
1.1 头文件配置
- windows下:
#include <Windows.h> /*Windows API函数库*/
- linux下:
#include <fcntl.h> /*文件控制定义*/
#include <termios.h> /*POSIX 终端控制定义*/
#include <stdio.h> /*标准输入输出定义*/
#include <stdlib.h> /*标准函数库定义*/
#include <unistd.h> /*Unix 标准函数定义*/
#include <sys/types.h>
#include <sys/stat.h>
1.2 打开串口
- windows下:
用CreateFile函数来打开串口句柄,首先看到,该类中的串口句柄为HANDLE SerialHandle;该句柄在应用CreateFile()函数创建后,就得到了指定了的串口句柄,其后,几乎所有的函数要对串口进行操作时,必须通过SerialHandle进行。
HANDLE SerialHandle;
char buf[256] = {};
sprintf(buf, "\\\\.\\%s", com); //格式化字符串
//打开串口
SerialHandle = CreateFileA(buf, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); //同步模式打开串口
if (SerialHandle == INVALID_HANDLE_VALUE) //打开串口失败
return false;
- linux下:
在Linux下串口文件是位于/dev下,串口1为/dev/ttySO,串口2为/dev/ttySl,通过调用open()打开串口设备,返回一个整形文件句柄,以后所有的端口操作都针对这个句柄进行。如果open()出错,则返回.1。open()函数带有2个参数,其中参数1为要打开的设备文件名,参数2为打开方式。
int fd;
//打开串口
fd = open(com, O_RDWR|O_NOCTTY|O_NDELAY); //O_RDWR 读写方式打开;O_NOCTTY 不允许进程管理串口(不太理解,一般都选上);O_NDELAY 非阻塞(默认为阻塞,打开后也可以使用fcntl()重新设置)
if (-1 == fd)
return false;
1.3 设置串口
- windows下:
在打开通讯设备句柄后,常常需要对串口进行一些初始化配置工作。这需要通过一个DCB结构来进行。DCB结构包含了诸如波特率、数据位数、奇偶校验和停止位数等信息。在查询或配置串口的属性时,都要用DCB结构来作为缓冲区。一般用CreateFile打开串口后,可以调用GetCommState函数来获取串口的初始配置。要修改串口的配置,应该先修改DCB结构,然后再调用SetCommState函数设置串口。
//设置串口参数
//读串口原来的参数设置
DCB dcb;
GetCommState(SerialHandle, &dcb); //串口打开方式
//串口参数配置
dcb.DCBlength = sizeof(DCB);
dcb.BaudRate = 9600;
dcb.ByteSize = 8;
dcb.Parity = EVENPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.fBinary = TRUE; // 二进制数据模式
dcb.fParity = TRUE;
if (!SetCommState(SerialHandle, &dcb))
return false;
SetupComm(SerialHandle, 1024, 1024); //设置缓冲区
return true;
- linux下:
进行串口操作之前,先要对串口通讯的波特率、校验位、输入/输出方式等参数进行设置。Linux下的串口设置实际上是根据POSIX规范来设置的。POSIX规范是由IEEE提出的,用于定义一系列可移植的操作系统接口。串口设置的所有参数都包含在Termios结构中。Linux提供了两个函数对termios进行操作,它们是tcgetattr()和tcsetattr()。tcgetattr()函数获得指定串口的设置情况,tesetattr()函数用来设置串口的参数。
//串口参数配置
struct termios options; // 串口配置结构体
tcgetattr(fd,&options); // 获取串口原来的参数设置
bzero(&options,sizeof(options));
options.c_cflag |= B9600 | CLOCAL | CREAD; // 设置波特率,本地连接,接收使能
options.c_cflag &= ~CSIZE; // 屏蔽数据位
options.c_cflag |= CS8; // 数据位为 8 ,CS7 for 7
options.c_cflag &= ~CSTOPB; // 一位停止位, 两位停止为 |= CSTOPB
options.c_cflag |= PARENB; // 有校验
options.c_cflag &= ~PARODD; // 偶校验
tcflush(fd, TCIOFLUSH); // 清除所有正在发生的I/O数据。
if(tcsetattr(fd, TCSANOW, &options)!=0) // TCSANOW立刻对值进行修改
return false;
return true;
1.4 发送、接收数据
- windows下:
使用ReadFile和WriteFile读写串口,在用ReadFile和WriteFile读写串口时,既可以同步执行,也可以重叠执行。在同步执行时,函数直到操作完成后才返回。这意味着同步执行时线程会被阻塞,从而导致效率下降。在重叠执行时,即使操作还未完成,这两个函数也会立即返回,费时的I/O操作在后台进行。ReadFile函数只要在串口输入缓冲区中读人指定数量的字符,就算完成操作。而WriteFile函数不但要把指定数量的字符拷入到输出缓冲区,而且要等这些字符从串行口送出去后才算完成操作。
//发送数据
char pData[] = {};
DWORD WriteNum = 0;
if (WriteFile(SerialHandle, pData, sizeof(pData), &WriteNum, 0))
return true;
return false;
- linux下:
串口配置完成后,把串口当作文件来读写。调用write()函数读写端口,返回实际读写的字节数,如果有错误发生则返回一1。在主线程中写数据,因为写是可以控制的,write
(fd,&WriteData,sizeof(WriteData));而读的时候不知道数据什么时候会到,所以要建立一个线程专门用来读数据,在这个线程中,循环地用Read读串口。在程序结束时关闭串口close(fd)。串口配置完成后,把串口当作文件来读写。调用read()函数读写端口,返回实际读写的字节数,如果有错误发生则返回一1。
//发送数据
char pData[] = {};
int WriteNum = write(fd,pDataOpenO01,sizeof(pDataOpenO01));
if (WriteNum!=-1)
return false;
return true;
1.5 关闭串口
- windows下:
调用ClosePort()函数来关闭串口。
if (SerialHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(SerialHandle);
SerialHandle = INVALID_HANDLE_VALUE;
return true;
}
else
return false;
- linux下:
关闭串口就是关闭文件。使用close()关闭打开的串口,唯一的参数是打开串口的文件描述符。
int flag=close(fd);
if (flag!=0)
return false;
return true;
Reference
- Linux环境与Windows环境交互串口通信设计
版权声明:本文标题:C++编程笔记:串口通信在windows环境和linux环境下的异同和代码实现 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/xitong/1728657892a1168369.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论