前言:
之前写过一篇Qt 5.x+串口通信的文章: https://blog.csdn.net/weixin_42837024/article/details/81669540
现在环境变为 qt 4.8 没有Qt 封装的跨平台的 串口类
可以使用网上开源的 posix_qextserialport,qextserialport
我在使用这个库的时候,在linux 正常使用
但是我的环境是 arm 板子 + linux 3.x + qt4.8 交叉编译
用这个库会出现 接收不到数据 (飞凌的板子)
头疼的一批
后来搞了一个库 用着还可以 就一个.h一个.cpp
serialport.h
serialport.cpp
用起来也很简单,就打开 读写数据
完整代码:
serialport.h
#ifndef SER_COM_PORT_TX_H
#define SER_COM_PORT_TX_H
#include <QSocketNotifier>
#include <linux/fs.h>
#include<fcntl.h>
#include<errno.h>
#include<termio.h>
#include<sys/ioctl.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>
#include <stdio.h>
#include<QTimer>
#include<QMutex>
#include<QWidget>
enum BaudRateType
{
BAUD50, //POSIX ONLY
BAUD75, //POSIX ONLY
BAUD110,
BAUD134, //POSIX ONLY
BAUD150, //POSIX ONLY
BAUD200, //POSIX ONLY
BAUD300,
BAUD600,
BAUD1200,
BAUD1800, //POSIX ONLY
BAUD2400,
BAUD4800,
BAUD9600,
BAUD14400, //WINDOWS ONLY
BAUD19200,
BAUD38400,
BAUD56000, //WINDOWS ONLY
BAUD57600,
BAUD76800, //POSIX ONLY
BAUD115200,
BAUD128000, //WINDOWS ONLY
BAUD256000 //WINDOWS ONLY
};
enum DataBitsType
{
DATA_5,
DATA_6,
DATA_7,
DATA_8
};
enum ParityType
{
PAR_NONE,
PAR_ODD,
PAR_EVEN,
PAR_MARK, //WINDOWS ONLY
PAR_SPACE
};
enum StopBitsType
{
STOP_1,
STOP_1_5, //WINDOWS ONLY
STOP_2
};
enum FlowType
{
FLOW_OFF,
FLOW_HARDWARE,
FLOW_XONXOFF
};
class SerialPort:public QObject
{
Q_OBJECT
public:
explicit SerialPort(QWidget *parent = 0);
private:
int m_fd;
termios new_serialArry;
QSocketNotifier *m_notifier;
QByteArray *rev_buf;
QMutex mutex_r;
public :
//open
bool openPort(QString portName,BaudRateType baundRate,DataBitsType dataBits,ParityType parity,
StopBitsType stopBits, FlowType flow ,int time_out);
//close
bool close();
//write
int write(QByteArray buf);
//read
QByteArray read();
signals:
void hasdata();
private slots:
void remoteDateInComing();
};
#endif // SER_COM_PORT_TX_H
serialport.cpp
#include "serialport.h"
#include<QDebug>
SerialPort::SerialPort(QWidget *parent):
QObject(parent)
{
m_fd=-1;
rev_buf=new QByteArray();
}
//open
bool SerialPort::openPort(QString portName, BaudRateType baundRate, DataBitsType dataBits,
ParityType parity, StopBitsType stopBits, FlowType flow, int time_out)
{
if(m_fd!=-1)
{
qDebug("is aready opened!");
return false;
}
rev_buf->clear();
memset(&new_serialArry,0,sizeof new_serialArry);
m_fd=::open(portName.toLatin1(),O_RDWR|O_NONBLOCK);
if( m_fd==-1)
{
qDebug("serial port open erro!");
return false;
}
switch(baundRate)
{
case BAUD50:
new_serialArry.c_cflag |= B50;
break;
case BAUD75:
new_serialArry.c_cflag |= B75;
break;
case BAUD110:
new_serialArry.c_cflag |= B110;
break;
case BAUD300:
new_serialArry.c_cflag |= B300;
break;
case BAUD600:
new_serialArry.c_cflag |= B600;
break;
case BAUD1200:
new_serialArry.c_cflag |= B1200;
break;
case BAUD2400:
new_serialArry.c_cflag |= B2400;
break;
case BAUD4800:
new_serialArry.c_cflag |= B4800;
break;
case BAUD9600:
new_serialArry.c_cflag |= B9600;
break;
case BAUD19200:
new_serialArry.c_cflag |= B19200;
break;
case BAUD38400:
new_serialArry.c_cflag |= B38400;
break;
case BAUD57600:
new_serialArry.c_cflag |= B57600;
break;
case BAUD115200:
new_serialArry.c_cflag |= B115200;
break;
default:
new_serialArry.c_cflag |= B9600;
break;
}
switch(dataBits)
{
case DATA_5:
new_serialArry.c_cflag|=CS5;
break;
case DATA_6:
new_serialArry.c_cflag|=CS6;
break;
case DATA_7:
new_serialArry.c_cflag|=CS7;
break;
case DATA_8:
new_serialArry.c_cflag|=CS8;
break;
default:
new_serialArry.c_cflag|=CS8;
break;
}
switch (parity)
{
case PAR_NONE:
new_serialArry.c_cflag &= (~PARENB);
break;
case PAR_EVEN:
new_serialArry.c_cflag &= (~PARODD);
new_serialArry.c_cflag |= PARENB;
break;
case PAR_ODD:
new_serialArry.c_cflag |= (PARODD|PARENB);
break;
default:
break;
}
switch(stopBits)
{
case STOP_1:
new_serialArry.c_cflag &=(~CSTOPB);
break;
case STOP_1_5:
break;
case STOP_2:
new_serialArry.c_cflag |=CSTOPB;
break;
default:
new_serialArry.c_cflag &=(~CSTOPB);
break;
}
switch(flow)
{
case FLOW_OFF:
new_serialArry.c_cflag &=(~CRTSCTS);
new_serialArry.c_iflag &=(~(IXON|IXOFF|IXANY));
break;
case FLOW_XONXOFF:
new_serialArry.c_cflag &=(~CRTSCTS);
new_serialArry.c_iflag |=(IXON|IXOFF|IXANY);
break;
case FLOW_HARDWARE:
new_serialArry.c_cflag |=~CRTSCTS;
new_serialArry.c_iflag &=(~(IXON|IXOFF|IXANY));
break;
default:
break;
}
new_serialArry.c_oflag=0;
new_serialArry.c_cc[VTIME]=time_out/100;
tcflush(m_fd,TCIFLUSH);
tcsetattr(m_fd,TCSANOW,&new_serialArry);
m_notifier= new QSocketNotifier(m_fd,QSocketNotifier::Read,0);
connect(m_notifier,SIGNAL(activated(int)),this,SLOT(remoteDateInComing()));
return true;
}
//close
bool SerialPort::close()
{
mutex_r.lock();
if(m_fd!=-1)
{
disconnect(m_notifier,SIGNAL(activated(int)),this,SLOT(remoteDateInComing()));
delete m_notifier;
m_fd=-1;
mutex_r.unlock();
return true;
}
mutex_r.unlock();
return false;
}
//recive data
void SerialPort::remoteDateInComing()
{
unsigned char c[1024];
int n= ::read(m_fd,&c,sizeof c);
mutex_r.lock();
for(int i=0;i<n;i++)
{
rev_buf->append(c[i]);
}
mutex_r.unlock();
emit hasdata();
}
//write data
int SerialPort::write(QByteArray buf)
{
mutex_r.lock();
int ret;
ret=0;
if(m_fd!=-1)
{
ret= :: write(m_fd,buf.data(),buf.length());
}
mutex_r.unlock();
return ret;
}
QByteArray SerialPort::read()
{
mutex_r.lock();
QByteArray retByteArray;
if(rev_buf->isEmpty())
{
retByteArray.append("aaa");
retByteArray.clear();
}else
{
//RECEIVE 00 ERROR 2019/2/19 retByteArray.append(rev_buf->data())
retByteArray.append(rev_buf->data(),rev_buf->size());
rev_buf->clear();
}
mutex_r.unlock();
return retByteArray;
}
这个代码解决我当时的问题,我也修改了一下,当时还是有个bug的
当串口数据中有 00 时 他会解析不正确,改完就ok了,正常使用
我放到github:
https://github.com/shenmingyi/SerialPort