串口开线程读写的数据,你可以根据自己的配置修改,接收数据和发送数据加强。内核缓存串口数据,你一次传输100个字符,一次就能接收完,否则你就要循环一百次接收数据,如果循环过快内核来不及缓存,那你接收到的数据就不确定了
注意内核接收到数据123abc调用read一次直接从内核拿123abc,如果没有那你就要调用6次read才能拿到完整的123abc,如果你超出内核接收大小数据会被截断,别的情况同样数据是拿到数据有时123a可能会是12等其他情况
一定要谨慎
头文件SerialPortServer.h
#ifndef SERIALPORTSERVER_H
#define SERIALPORTSERVER_H
#include <QString>
#include <QObject>
#include <QThread>
#include <QTimer>
#include <stdio.h> //标准输入输出定义
#include <string.h>
#include <unistd.h> //Unix 标准函数定义
#include <stdlib.h> //标准函数库定义
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h> //文件控制定义
#include <termios.h> //PPSIX 终端控制定义
#include <errno.h> //错误号定义
typedef struct _SERIAL_PORT_PAR {
QString baudRate;
QString dataBits;
QString parity;
QString stopBits;
QString splitChar;
} SERIAL_PORT_PAR;
class SerialPortServer : public QThread
{
Q_OBJECT
public:
SerialPortServer();
~SerialPortServer();
int startServer();
int uardfd();
private slots:
void onTimeout();
private:
void readSerialPortData();
int replyData();
protected:
void run();
private:
int m_fd_uart;
SERIAL_PORT_PAR _par;
QByteArray m_recv_data;
QTimer m_timer;
};
#endif
源文件SerialPortServer.cpp
#include "SerialPortServer.h"
#include <QDebug>
SerialPortServer::SerialPortServer()
{
m_recv_data.clear();
m_fd_uart=0;
//配置串口通信
_par.baudRate = "19200";
_par.dataBits = "8";
_par.parity = "无";
_par.stopBits = "1";
_par.splitChar = ";";
connect(&m_timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
}
void SerialPortServer::onTimeout()
{
}
SerialPortServer::~SerialPortServer()
{
}
/*
这里一直等待串口数据
*/
void SerialPortServer::run()
{
if(m_fd_uart <= 0){
qDebug() << "串口未打开,服务线程启动失败";
return ;
}
m_timer.start(1000);
fd_set rdfd;
//struct timeval timeout = {1, 500 * 1000};
struct timeval timeout = {3, 0};
int maxfd = m_fd_uart + 1;
int retval = 0;
qDebug() << "SerialPortServer::run()";
while(1){
FD_ZERO(&rdfd);
FD_SET(m_fd_uart, &rdfd);
retval = select(maxfd, &rdfd, NULL, NULL, &timeout);
if(retval < 0){
if(errno == EINTR)
continue;
//Error
QString str = QString("接受数据出错:%1").arg(strerror(errno));
qDebug() << str;
break;
}else if(retval == 0){
usleep(1000);
continue;
}
if (FD_ISSET(m_fd_uart, &rdfd)){
readSerialPortData();
}
}
m_timer.stop();
close(m_fd_uart);
m_fd_uart = 0;
qDebug() << "服务线程退出";
}
/*
接收串口发送过来的数据
读到对方发送的Do you love me? 中文就是你爱我吗
*/
void SerialPortServer::readSerialPortData()
{
if (m_fd_uart)
{
char buf[255] = {0};
int ret = read(m_fd_uart, buf, 255);
//printf("len: %d, data: %s\n", ret, buf);
if (ret > 0)
m_recv_data.append(buf, ret);
//收到数据校验 如果是Do you love me? 你就可以调用函数replyData回复love you你爱他
int index1 = m_recv_data.indexOf("Do you love me?");
if(index1 == 0) {
m_recv_data.clear();
replyData();
}
if(m_recv_data.length()>5){
m_recv_data.clear();
}
}
}
int SerialPortServer::uardfd()
{
return m_fd_uart;
}
//你可以回复对方数据
int SerialPortServer::replyData()
{
//qDebug() << "replyPrintData: " << m_markspeed << ", " << text_data;
char packet[13] = {"love you"};
if (m_fd_uart){
write(m_fd_uart, packet, sizeof(packet));
}
return 0;
}
int SerialPortServer::startServer() //开始服务
{
if (m_fd_uart)
{
close(m_fd_uart);
m_fd_uart = 0;
}
m_fd_uart = open("/dev/ttymxc2", O_RDWR | O_NOCTTY | O_NONBLOCK); //非阻塞方式
if (m_fd_uart < 0)
{
m_fd_uart = 0;
printf("打开串口设备错误\n");
return -1;
}
struct termios opt;
if (tcgetattr(m_fd_uart, &opt) != 0)
{
//printf("error: tcgetattr fd\n");
close(m_fd_uart);
m_fd_uart = 0;
printf("串口错误: tcgetattr fd\n");
return -2;
}
tcflush(m_fd_uart, TCIOFLUSH);
speed_t baudRate;
if (_par.baudRate == "2400")
baudRate = B2400;
else if (_par.baudRate == "4800")
baudRate = B4800;
else if (_par.baudRate == "9600")
baudRate = B9600;
else if (_par.baudRate == "19200")
baudRate = B19200;
else if (_par.baudRate == "38400")
baudRate = B38400;
else if (_par.baudRate == "57600")
baudRate = B57600;
else if (_par.baudRate == "115200")
baudRate = B115200;
else
baudRate = B38400;
cfsetispeed(&opt, baudRate);
cfsetospeed(&opt, baudRate);
opt.c_cflag &= ~CSIZE;
if (_par.dataBits == "8")
opt.c_cflag |= CS8; //数据位8
else
opt.c_cflag |= CS7; //数据位7
if (_par.stopBits == "2")
opt.c_cflag |= CSTOPB; //停止位2
else
opt.c_cflag &= ~CSTOPB; //停止位1
if (_par.parity == "无")
opt.c_cflag &= ~PARENB; //无校验
else if (_par.parity == "奇")
{
opt.c_cflag |= PARODD; //奇校验
opt.c_cflag |= PARENB; //使能校验
}
else if (_par.parity == "偶")
{
opt.c_cflag &= ~PARODD; //偶校验
opt.c_cflag |= PARENB; //使能校验
}
else
{
opt.c_cflag &= ~PARENB; //无校验
}
opt.c_cflag |= (CLOCAL | CREAD);
opt.c_lflag &= ~(ICANON | ECHO |ECHOE | ISIG);
opt.c_oflag &= ~OPOST;
opt.c_oflag &= ~(ONLCR | OCRNL);
opt.c_iflag |= INPCK;
opt.c_iflag &= ~(ICRNL | INLCR | IGNCR);
opt.c_iflag &= ~(IXON | IXOFF | IXANY);
tcflush(m_fd_uart, TCIOFLUSH);
opt.c_cc[VTIME] = 0;
opt.c_cc[CMIN] = 0;
if (tcsetattr(m_fd_uart, TCSANOW, &opt) != 0)
{
close(m_fd_uart);
m_fd_uart = 0;
printf("串口错误: 2 tcsetattr fd");
return -3;
}
tcflush(m_fd_uart, TCIOFLUSH);
start();//启动线程run函数
return 0;
}