数据量 每毫秒6个字节
主要采用单生产者单消费者模型:
1.生产者moveToThread,线程扫描串口数据,入消息队列,释放信号量,同时emit信号;
2.消费者接收到消息,获取信号量,从消息队列中获取数据。
生产者:
#include "serialcom.h"
SerialCom::SerialCom()
{
m_port = “COM1”;
m_rate = "115200";
m_sem = new QSemaphore(0);
m_updatesem = new QSemaphore(0);
m_thread_running = false;
m_thread = new QThread();
m_serial = new QSerialPort(m_thread);
moveToThread(m_thread);
// 绑定线程循环体
connect(m_thread, SIGNAL(started()), this, SLOT(Serial_ReadyRead()));
}
bool SerialCom::IsConnected()
{
if (m_serial)
{
//if (m_serial->isOpen())
if (m_thread_running)
{
return true;
}
}
return false;
}
QString SerialCom::GetPort()
{
return m_port;
}
void SerialCom::ScanPort()
{
if(m_serial != nullptr)
{
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
QSerialPort serial;
serial.setPort(info);
if(serial.open(QIODevice::ReadWrite))
{
//qDebug() << "port:" << serial.portName();
m_port = serial.portName();
serial.close();
return; // use the first avilable one
}
}
}
}
QString SerialCom::GetStatus()
{
return m_status;
}
bool SerialCom::Connect(char *pPort, char *pRate)
{
if (m_serial == nullptr)
{
return false;
}
if (!IsConnected())
{
QString port = m_port;
qint32 rate = m_rate.toInt();
// port
if (pPort != nullptr)
{
port = QString(pPort);
m_port = port;
}
// rate
if (pRate != nullptr)
{
rate = QString(pRate).toInt();
m_rate = QString(pRate);
}
m_serial->setPortName(port);
m_serial->setBaudRate(rate);
m_serial->setDataBits(QSerialPort::Data8);
m_serial->setParity(QSerialPort::NoParity);
m_serial->setStopBits(QSerialPort::OneStop);
m_serial->setFlowControl(QSerialPort::NoFlowControl);
m_serial->setReadBufferSize(150);
if (m_serial->open(QIODevice::ReadWrite))
{
m_thread_running = true;
m_thread->start();
qDebug() << "port:" << m_port << "rate:" << m_rate;
m_status = ("port:" + port + ",rate:" + QString::number(rate));
return true;
}
else
{
qDebug() << "Open COM ERROR!!!" << "port:" << port << "rate:" << rate;
m_status = ("port:" + port + ",rate:" + QString::number(rate));
return false;
}
}
return true;
}
bool SerialCom::Disconnect()
{
if (m_thread != nullptr)
{
m_thread_running = false;
m_thread->quit();
m_thread->wait();
}
if (m_serial != nullptr)
{
m_serial->close();
}
return true;
}
int SerialCom::GetPacket(QByteArray &message, int timeout)
{
if (timeout == -1) {
timeout = this->timeout;
}
if (m_sem->tryAcquire(1, timeout))
{
message = m_message.first();
m_message.pop_front();
return 0;
}
else
{
//qDebug() << "SerialCom::GetPacket() recv timeout!" << m_message.size();
return -1;
}
}
void SerialCom::PutPacket(QByteArray &message)
{
m_serial->write(message.data(), message.size());
msecSleep(15);
}
void SerialCom::Serial_ReadyRead()
{
while (true) {
if (m_serial != nullptr && m_thread_running)
{
if (m_serial->bytesAvailable())
{
QByteArray rdata;
rmessage.resize(m_serial->bytesAvailable());
{
//qDebug() << "bytesAvailable:" << m_serial->bytesAvailable();
rdata = m_serial->readLine();
}
{
// qDebug() << "recv:" << rdata.toHex() << rdata.size() << m_sem->available();
m_message.push_back(rdata);
m_sem->release();
emit recvMsg();
}
}
}
else
{
return;
}
QThread::msleep(1);
}
}
消费者:
#include "home.h"
#include "ui_home.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
start();
}
Widget::~Widget()
{
stop();
delete ui;
}
void Widget::start()
{
m_scom = new SerialCom();
m_scom->ScanPort();
m_scom->Connect();
if(m_scom->IsConnected())
{
connect(m_scom,SIGNAL(recvMsg()),this,SLOT(msgSwitch()));//msgSwitch()为自定义槽
//QMessageBox::information(NULL, "成功", "连接成功!\n"+m_icom->GetStatus());
}
else
{
QMessageBox::critical(NULL, "失败", "连接失败,端口被占用!\n"+m_icom->GetStatus());
QTimer::singleShot(200, this, SLOT(jumpQuit()));
}
}
int Widget::stop() const
{
if (m_scom != nullptr)
{
m_scom->Disconnect();
delete m_scom;
}
}
return 0;
}
void Widget::msgSwitch()
{
QByteArray msg;
if (!(m_icom->GetPacket(msg, 1)))
{
// 获取到包
qDebug() << msg.toHex() << "Recv data lenth:" << msg.size();
}
}