Linux下基于QT串口编程测试一
本文博客链接:http://blog.youkuaiyun.com/jdh99,作者:jdh,转载请注明.
环境:
主机:Fedora12
开发软件:QT
目标板:MINI6410
实现功能:
目标板接收PC串口传过来的信息并在终端输出,目标板串口接收信息用SELECT机制
源代码:
widget.h:
#ifndef WIDGET_H#define WIDGET_H#include <QWidget>#include <QDebug>#include <QTimer>#include <unistd.h>#include <sys/types.h>#include <fcntl.h>#include <sys/stat.h>#include <stdio.h>#include <sys/param.h>#include <QVector>#include <QByteArray>#include <QQueue>#include <QSemaphore>#include <iostream>#include <QFile>#include "QThread"#include <QtGui>#include <QMutex>#include <QtNetwork>#include <QUdpSocket>#include <sys/ioctl.h>#include <stdlib.h>#include <stdio.h>#include <linux/soundcard.h>#include <alsa/asoundlib.h>#include <QtGui/QMainWindow>#include <QtGui/QDialog>#include <QtGui/QPushButton>#include <QtGui/QHBoxLayout>#include <QtGui/QVBoxLayout>#include <QtGui/QGridLayout>#include <QTextCodec>#include <QtGui/QToolButton>#include <qsocketnotifier.h>#include <QTimer>#include <QtNetwork/QUdpSocket>#include <iostream>#include <qmessagebox.h>#include <qstringlist.h>#include <QtNetwork>#include <QUdpSocket>#include <QSound>#include <QMap>#include <sys/socket.h>#include <arpa/inet.h>#include <linux/soundcard.h>#include "sys/select.h"#include "termios.h"namespace Ui { class Widget;}class Widget : public QWidget{ Q_OBJECTpublic: explicit Widget(QWidget *parent = 0); ~Widget();private: Ui::Widget *ui;};//端口信息定义typedef struct _Port_Info{ int baud_rate; int port_fd; char parity; char stop_bit; char flow_ctrl; char data_bits;}*Port_Info;//打开串口int open_port(char *port);//关闭串口void close_port(int fd);//根据波特率获得波特率设置参数int get_baud_rate(unsigned long baud_rate);//设置端口参数int set_port(Port_Info p_info);//通过串口发送数据,只能写COMPRESS_BYTE长度数据,发送时加文件头"JDH"int send_data(int fd,char *data,int data_len);#endif // WIDGET_H
widget.c:
#include "widget.h"#include "ui_widget.h"int Fd_Com;#define COM "/dev/ttySAC1"char buffer_com[1024 + 10];char buffer_read_com[1024];int send_index;//打开串口int open_port(char *port){ int fd; if ((fd = open(port,O_RDWR | O_NOCTTY |O_NONBLOCK)) == -1) { perror("can not open com port!"); return -1; }}//关闭指定串口void close_port(int fd){ close(fd);}//根据波特率获得响应的波特率设置参数int get_baud_rate(unsigned long baud_rate){ switch (baud_rate) { case 2400: return B2400; case 4800: return B4800; case 9600: return B9600; case 19200: return B19200; case 38400: return B38400; case 57600: return B57600; case 115200: return B115200; case 230400: return B230400; default: return -1; }}//设置端口int set_port(Port_Info p_info){ struct termios old_opt,new_opt; int baud_rate,parity; memset(&old_opt,0,sizeof(old_opt)); memset(&new_opt,0,sizeof(new_opt)); cfmakeraw(&new_opt); tcgetattr(p_info->port_fd,&old_opt); //设置串口波特率 baud_rate = get_baud_rate(p_info->baud_rate); //修改new_opt结构中的串口输入/输出波特率槽参数 cfsetispeed(&new_opt,baud_rate); cfsetospeed(&new_opt,baud_rate); //修改控制模式,保证程序不会占用串口 new_opt.c_cflag |= CLOCAL; //修改控制模式,使得能够从串口读取输入数据 new_opt.c_cflag |= CREAD; //设置数据流控制 switch (p_info->flow_ctrl) { case '0': { //不使用流控制 new_opt.c_cflag &= ~CRTSCTS; break; } case '1': { //使用硬件进行流控制 new_opt.c_cflag |= CRTSCTS; break; } case '2': { new_opt.c_cflag |= IXON | IXOFF | IXANY; break; } } //设置数据位 new_opt.c_cflag &= ~CSIZE; switch (p_info->data_bits) { case '5': { new_opt.c_cflag |= CS5; break; } case '6': { new_opt.c_cflag |= CS6; break; } case '7': { new_opt.c_cflag |= CS7; break; } case '8': { new_opt.c_cflag |= CS8; break; } default: { new_opt.c_cflag |= CS8; break; } } //设置奇偶校验位 switch (p_info->parity) { case '0': { //不使用奇偶校验 new_opt.c_cflag &= ~PARENB; break; } case '1': { //使用偶校验 new_opt.c_cflag |= PARENB; new_opt.c_cflag &= ~PARODD; break; } case '2': { //使用奇校验 new_opt.c_cflag |= PARENB; new_opt.c_cflag |= PARODD; break; } } //设置停止位 if (p_info->stop_bit == '2') { new_opt.c_cflag |= CSTOPB; } else { new_opt.c_cflag &= ~CSTOPB; } //修改输出模式,原始数据输出 new_opt.c_oflag *= ~OPOST; //修改控制字符,读取字符最小个数为1 new_opt.c_cc[VMIN] = 1; //修改控制字符,读取第一个字符等待等待1 *(1/10)s new_opt.c_cc[VTIME] = 1; //如果发生数据溢出,接收数据,但是不再读取 tcflush(p_info->port_fd,TCIFLUSH); int result; result = tcsetattr(p_info->port_fd,TCSANOW,&new_opt); if (result == -1) { perror("cannot set the serial port parameters"); return -1; } tcgetattr(p_info->port_fd,&old_opt); return result;}Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget){ ui->setupUi(this); //串口初始化 //打开串口 Fd_Com = open_port(COM); //设置串口通信参数 struct _Port_Info info; info.baud_rate = 115200; info.data_bits = 8; info.flow_ctrl = 0; info.port_fd = Fd_Com; info.stop_bit = 1; info.parity = 0; if (set_port(&info) == -1) { printf("set com para wrong!!!!!!!!!!!!!"); } int err = 0; struct timeval wait_time; fd_set read_fds; int len_com = 0; char *data = "jdh"; int len = write(Fd_Com,data,3); if (len != 3) { //如果出现溢出情况 qDebug() << "yi chu"; tcflush(Fd_Com,TCOFLUSH); } while (1) { wait_time.tv_sec = 0; wait_time.tv_usec = 20000; FD_ZERO(&read_fds); FD_SET(Fd_Com,&read_fds); //err = select(Fd_Com + 1,&read_fds,NULL,NULL,&wait_time); err = select(Fd_Com + 1,&read_fds,NULL,NULL,NULL); if (err < 0) { perror("select fail"); continue; } else { if (err == 0) { //超时返回 //qDebug() << "chao shi"; continue; } } //读取串口声卡 //判断声卡是否允许读,不允许读退出 if (FD_ISSET(Fd_Com,&read_fds)) { qDebug() << "du qu sheng ka"; //读取串口缓存所有数据 len_com = read(Fd_Com,buffer_read_com,1024); qDebug() << "read com byte = " << len_com; QByteArray temp; temp.append(buffer_read_com,len_com); qDebug() << temp; } } qDebug() << "end";}Widget::~Widget(){ delete ui;}
说明:
串口在驱动中有一个缓存区,收到的数据会存放在里面,如果一次发送数据很多,而读取间隔很短,则每次读取都是整个数据包的片段.
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.youkuaiyun.com/jiangjunshow