串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。串行接口(Serial Interface) 是指数据一位一位地顺序传送,其特点是通信线路简单,只要一对传输线就可以实现双向通信,大大降低了成本,特别适用于远距离通信,但传送速度较慢。根据信息的传送方向,串行通讯可以进一步分为单工、半双工和全双工三种。串行接口按电气标准及协议来分包括RS-232-C、RS-422、RS485等。

异步串行是指UART(Universal Asynchronous Receiver/Transmitter),通用异步接收/发送。UART包含TTL电平的串口和RS232电平的串口。 TTL电平是3.3V的,而RS232是负逻辑电平,它定义+5~+12V为低电平,而-12~-5V为高电平。UART作为异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输,其中各位的意义如下:

起始位:先发出一个逻辑”0”的信号,表示传输字符的开始。
数据位:紧接在起始位之后,数据位的个数可以是4、5、6、7、8等,构成一个字符,从最低位开始传送,靠时钟定位。
奇偶校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性。
停止位:它是一个字符数据的结束标志,可以是1位、1.5位、2位的高电平。 由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。
空闲位:处于逻辑“1”状态,表示当前线路上没有数据传送。

此外,在异步通信中还有一个重要的参数,即波特率,它是衡量数据传送速率的指标,表示每秒钟传送的符号数(symbol)。收发双方的波特率必须保持一致,才能保证数据的正常通信。

在通信程序中,一般来说如何获取收到的信息是一个问题。因为接收是被动的,即不知道对方什么时候会发送信息来,所以需要一直对接收端进行侦听,看是否有信息到来,这样就需要CPU反复地进行查询,会消耗过多的资源。所以,在硬件层面一般会使用中断方式来进行接收侦听,而不会采用查询方式。同样,在基于操作系统的编程中,对于接收也有查询和事件两种方式。查询方式同样需要反复地对接收进行读取,看是否收到了信息,同样会消耗过多的系统资源,一般会把它放在一个线程中来进行,以保证系统资源不会被过度地消耗掉。另一种是事件方式,即当接收端收到信息时,会采用事件的方式来通知主程序,以对收到的信息进行相应地处理。事件方式有点类似硬件上的中断方式,效率较高。

在基于Qt的串口编程中,有多种实现的方式。比如可以使用Qt自己带的串口模块(如QSerialPort),也可以使用其他第三方的控件(如qextserialport等),还可以使用操作系统中直接编写的串口程序。各种方式都有自己的特点,但对于Qt自带的QSerialPort模块,虽然兼容性较好,但目前只有Qt5.0以上的版本才支持该模块。对于第三方控件qextserialport,虽然在Qt4.0的版本就可以使用,但目前对于Linux系统而言,仅支持查询方式,而不支持事件方式,所以在Linux中一般只能把它放到一个新建的线程中去运行。对于在操作系统中直接编程处理串口通信的方式,需要一定的程序开发能力,但适用性更广泛一些,执行的效率也要高一些。

在Qt4.0及以上的版本中,新增加了一个名为QSocketNotifier的模块,它用来监听系统文件的操作,把操作转换为Qt事件进入系统的消息循环队列,并调用预先设置的事件接受函数来处理事件。QSocketNotifier一共设置了三类事件:read、write、exception,具体如下表所示。

在使用QSocketNotifier来处理串口时,只需要设置为Read属性即可。每个QSocketNotifie对象监听一个事件,在使用open方法打开串口并设置好属性后,就可以使用Qt的类 QSocketNotifier来监听串口是否有数据可读,它是事件驱动的,配合Qt的信号/槽机制,当有数据可读时,QSocketNotifier就会发射ativated信号,只需要创建一个槽连接到该信号即可,然后在槽函数中处理串口读到的数据。这样一来,读取串口的任务就不用新开辟线程来处理了,这也是Qt官方给出的建议。

在Linux系统中,一切设备都可以按文件来处理,这一机制也正好符合QSocketNotifie监听系统文件变化的机制。因此,在Linux系统中使用QSocketNotifie来处理串口接收数据,可谓相得益彰。因此,下面讨论的就是在Linux系统中,基于Qt4.8.7的版本,结合Linux的串口模块编程,然后在Qt中使用QSocketNotifie来实现串口信息的读取。下面给出具体步骤。

首先,在Linux系统中,所有的设备文件都位于/dev目录下,以tty为前缀的文件,是终端设备。以tty加大写S开头的即为串口设备文件,如ttyS0即为串口0(即COM0)。但在嵌入式Linux中,串口是以ttySAC为前缀的,如ttySAC0即代表串口0。

其次,在Linux系统中,要对文件进行相应地操作,必须先打开它,对串口设备文件也不例外,所以需要调用open函数来打开对应的串口端口。另外在打开的同时,还需要设置打开文件的合适属性(如可读可写、不将设备分配为控制终端、无延时模式等)。 比如,可执行语句“open("/dev/ttySAC0", O_RDWR | O_NOCTTY |  O_NDELAY);”。

接下来,需要对打开的串口进行配置,其中的重要参数有:波特率、数据位数、停止位位数、奇偶校验、硬件流量控制等。在Linux中,这些配置项目由一个名为termios 结构体实现,结合前面的打开串口,可以一起写在一个串口初始化函数中,如下 。

int MainWindow::UART_Init(void)
{
struct termios opt;
fdUart = open("/dev/ttySAC1", O_RDWR | O_NOCTTY | O_NDELAY);
tcgetattr(fdUart, &opt); //获取当前打开的串口参数到termios型结构体mycom中
opt.c_cflag &= ~(PARENB | CSTOPB | CSIZE | OPOST);//无奇偶校验、1位停止位、原始模式
opt.c_cflag |= (CS8 | CLOCAL | CREAD); //8位数据位
cfsetispeed(&opt, B9600);
cfsetospeed(&opt, B9600); //波特率为9600
opt.c_cc[VMIN] = 0;
opt.c_cc[VTIME] = 0;
tcflush(fdUart,TCIOFLUSH); //清除输出输入缓冲
if (tcsetattr(fdUart, TCSANOW, &opt) < 0) //使用mycom中的参数设置当前已打开的串口,不等数据传输完毕就立即改变
{
return -1;
}
return fdUart;
}

接下来需要在Qt的主程序中,加入串口初始化,创建一个QSocketNotifier类的对象并将其实例化,建立信号与槽的连接函数,如下。

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
UART_Init();
QSocketNotifier *com0_notifier;
com0_notifier = new QSocketNotifier(fdUart, QSocketNotifier::Read, this);
connect(com0_notifier, SIGNAL(activated(int)), this, SLOT(SerialIncoming(void)));
}

最后,还要写一个槽函数来读取串口数据,如下。

void MainWindow::SerialIncoming(void)
{
char buff[8];
read(fdUart,buff,8);
}

在上述程序中,文件描述符fdUart应定义为全局变量。程序运行后,只要串口接收到数据,就会触发SerialIncoming函数,然后把收到的数据存入buff数组中,以供后续处理之用。当然,若要向串口发送数据,直接写fdUart即可,比如执行“write(fdUart,buff,8);”即可把buff中的8个字节数据及时发送出去。

为了让上述程序能够正常运行,还需要包含下面的三个头文件。

#include <QSocketNotifier>
#include <fcntl.h>
#include <termios.h>

本例给出的只是一个最小框架,在具体应用时,还要根据实际的项目进行适当的修改。

Qt中的串口编程的更多相关文章

  1. Qt中的串口编程之三

    QtSerialPort 今天我们来介绍一下QtSerialPort模块的源代码,学习一下该可移植的串口编程库是怎么实现的. 首先,我们下载好了源代码之后,使用QtCreator打开整个工程,可以看到 ...

  2. Qt中的串口编程之一

    QtSerialPort 简介 功能介绍 SerialPort SerialPortInfo 源代码 编译和安装 配置编译环境 Perl只是在Qt5的时候才需要Qt4的情况下可以不配置 使用如下推荐步 ...

  3. QT中的SOCKET编程(QT-2.3.2)

    转自:http://mylovejsj.blog.163.com/blog/static/38673975200892010842865/ QT中的SOCKET编程 2008-10-07 23:13 ...

  4. QT中的SOCKET编程

    转自:http://mylovejsj.blog.163.com/blog/static/38673975200892010842865/ QT中的SOCKET编程 2008-10-07 23:13 ...

  5. Qt中的多线程编程

    http://www.ibm.com/developerworks/cn/linux/l-qt-mthrd/ Qt 作为一种基于 C++ 的跨平台 GUI 系统,能够提供给用户构造图形用户界面的强大功 ...

  6. <QT障碍之路>qt中使用串口类接收数据不完整

    问题:当用QT中的serial->readAll()的时候,不会把全部的数据一次性都读取出来,而是阶段性的.原因是因为当串口有信号时候,readyRead()信号就会被抛出,那么一帧完整的数据帧 ...

  7. 5.关于QT中的网络编程,QTcpSocket,QUdpSocket

     1 新建一个项目:TCPServer.pro A  修改TCPServer.pro,注意:如果是想使用网络库,需要加上network SOURCES += \ TcpServer.cpp \ T ...

  8. qt中的udp编程

    UDP QUdpSocket ---> upd socket 1.创建 QUdpSocket *p = new QUdpSocket(); 2.最先接收数据一方 调用bind-> ip/p ...

  9. qt中的tcp编程

    server .server.h #define DIALOG_H #include <QDialog> #include <QTcpServer> #include < ...

  10. Qt 多线程和网络编程学习

    一,Qt多线程类学习 QThread类,开始一个新的线程就是开始执行重新实现QThread::run(),run()是默认现实调用exec(),QThread::start()开始线程的执行,run( ...

随机推荐

  1. 正则过滤http|https地址

    let reg = /(\w+):\/\/([^/:]+)(:\d*)?/; let s = http.match(reg); let s1 = http1.match(reg); console.l ...

  2. ubuntu 安装SVN

    s1: [sudo apt-get install subversion] s2:本地新建一个文件夹如SVN,在该文件夹下打开终端输入命令[svn co https://xxx/svn/xxx --u ...

  3. JustAuth-第三方登录组件

    1.新增依赖 <dependency> <groupId>me.zhyd.oauth</groupId> <artifactId>JustAuth< ...

  4. SQL server自动创建日历表。

    做日报功能需要统计每个月的上班天数,节假日因为每年的日期都不一样,所以需要自己手动更新这些节假日 1:首先先自动创建一个日历表,选择开始年月日和结束的年月日 不要同时执行,先执行创建表之后CREATE ...

  5. Kubernetes--标签选择器(标签)

    标签选择器用于表达标签的查询条件或选择标准,Kubernetes API目前支持两个选择器:基于等值关系(equality-based)以及基于集合关系 (set-based).例如,env=prod ...

  6. HTML&CSS学习总结

    目录 一. HTML学习总结 1.HTML是什么 2.HTML结构 1. 创建一个HTML实例 2. HTML结构解析 3. HTML标题 4. HTML段落 5. HTML链接 6. HTML图像 ...

  7. svn ssh方式避免每次输入密码

    ubuntu下没有tortoiseSVN,用svn+ssh方式每次都提示要输入密码 通过配置~/.ssh/config文件让系统记住ssh密匙(private key)文件就不用输入密码了. 在con ...

  8. redis-creating server tcp listening socket 127.0.0.1:6379: bind No error

    安装redis,出现如下错误: 解决方法: 步骤1:命令行下输入:redis-cli.exe(注意不是redis-server.exe) 然后输入:shutdown exit 退出后输入.\redis ...

  9. Windows10免安装版的Mysql

    文章转载出处https://www.cnblogs.com/winton-nfs/p/11524007.html 免安装版的Mysql MySQL关是一种关系数据库管理系统,所使用的 SQL 语言是用 ...

  10. typora破解使用

    1.将example文件夹以及run.exe同时拷贝到typora安装目录下的\Typora\resources\ 里面. 2.然后运行run.exe,会出现一个cmd弹窗,然后会消失,此时,激活码k ...