Qt线程控制串口的接收发送问题

ymxl0826zz 2012-09-18 01:20:24
刚接触Qt,用线程来控制串口收发出现了问题,望高手解答下,谢谢~~~
采用了第三方的串口控制类http://sourceforge.net/projects/qextserialport/files/
在Windows下用的是:qextserialbase.cpp和qextserialbase.h 以及win_qextserialport.cpp和win_qextserialport.h
我用刚写的Qt程序打开COM1,将电脑的COM1与COM2连接,用其它的串口调试软件打开COM2。打开COM1后,通过COM2给COM1发送数据,COM1口无法返回刚发的数据;发现当COM2仅发送一个字节时,COM1可以返回刚发的一个字节;如果超过一个字节就无法发送回来。而点那个按钮可以发送sendBuffer的数据,但receiveBuffer中的数据只能在接收一个字节时有用。


下面是源代码。
main.cpp文件

#include <QtGui/QApplication>
#include <QTextCodec>//头文件
#include "mainwindow.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTextCodec::setCodecForTr(QTextCodec::codecForLocale());
MainWindow w;
w.show();

return a.exec();
}


mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"



MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);


ui->closeMyComBtn->setEnabled(false);//开始时,“关闭串口”按钮不可用
ui->openMyComBtn->setEnabled(true);//开始时,“打开串口”按钮可用

}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::on_openMyComBtn_clicked()
{
QString portName = ui->portNameComboBox->currentText();//获取串口几
BaudRateType baud;
if(ui->baudRateComboBox->currentText()==tr("9600"))
baud =BAUD9600;
else if(ui->baudRateComboBox->currentText()==tr("115200"))
baud =BAUD115200;
mySerialSendThread = new serialSendThread(portName,baud);
mySerialSendThread->start();

connect(this,SIGNAL(setSendCommand(QByteArray)),mySerialSendThread,SLOT(getSendCommand(QByteArray)));


ui->openMyComBtn->setEnabled(false);//串口开启后,“打开串口”按钮不可用
ui->closeMyComBtn->setEnabled(true);//串口开启后,“关闭串口”按钮可用
ui->portNameComboBox->setEnabled(false);
ui->baudRateComboBox->setEnabled(false);
}

void MainWindow::on_closeMyComBtn_clicked()
{

mySerialSendThread->stop();
mySerialSendThread->myCom->close();//关闭函数,该函数在win_qextserialport.cpp中定义

ui->openMyComBtn->setEnabled(true);
ui->closeMyComBtn->setEnabled(false);
ui->portNameComboBox->setEnabled(true);
ui->baudRateComboBox->setEnabled(true);
}

void MainWindow::on_setBoardAddress_clicked()
{
//55 AA 05 FF 0B 01 00 06 //55 AA 05 FF 0B 01 01 01 //55 AA 05 FF 0B 01 02 08
QByteArray data;
data[0]=0x55;
data[1]=0xAA;
data[2]=0x05;
data[3]=0xFF;
data[4]=0x0b;
data[5]=0x01;
if(ui->boardAddressComboBox->currentText()==tr("00")){
data[6]=0x00;
data[7]=0x06;
}
else if(ui->boardAddressComboBox->currentText()==tr("01")){
data[6]=0x01;
data[7]=0x01;
}
else if(ui->boardAddressComboBox->currentText()==tr("02")){
data[6]=0x02;
data[7]=0x08;
}
emit this->setSendCommand(data);
}

mainwindow.h文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <win_qextserialport.h> //加入串口头文件
#include <QTimer> //定时器头文件
#include <QtGui>
#include <QDataStream>
#include <serialSendThread.h>


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

private:
Ui::MainWindow *ui;

serialSendThread *mySerialSendThread;


signals:
void setSendCommand(QByteArray);

private slots:
void on_openMyComBtn_clicked();
void on_closeMyComBtn_clicked();
void on_setBoardAddress_clicked();
};

#endif // MAINWINDOW_H

mainwindow.ui文件
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>182</width>
<height>177</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QGridLayout" name="gridLayout">
<item row="11" column="0">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QComboBox" name="portNameComboBox">
<item>
<property name="text">
<string>COM1</string>
</property>
</item>
<item>
<property name="text">
<string>COM2</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QComboBox" name="baudRateComboBox">
<item>
<property name="text">
<string>9600</string>
</property>
</item>
<item>
<property name="text">
<string>115200</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QPushButton" name="openMyComBtn">
<property name="text">
<string>打开串口</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="closeMyComBtn">
<property name="text">
<string>关闭串口</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QComboBox" name="boardAddressComboBox">
<item>
<property name="text">
<string>00</string>
</property>
</item>
<item>
<property name="text">
<string>01</string>
</property>
</item>
<item>
<property name="text">
<string>02</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QPushButton" name="setBoardAddress">
<property name="text">
<string>设置板地址</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>182</width>
<height>19</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>


serialSendThread.cpp文件
#include "serialSendThread.h"


serialSendThread::serialSendThread(QString portName,BaudRateType baud)
{
myCom = new Win_QextSerialPort(portName,QextSerialBase::EventDriven);//定义串口对象,异步方式
myCom->open(QIODevice::ReadWrite);
myCom->setBaudRate(baud);//设置波特率
myCom->setDataBits(DATA_8);//8数据位
myCom->setParity(PAR_NONE);//校验无
myCom->setStopBits(STOP_1);//1位停止位
myCom->setFlowControl(FLOW_OFF);//设置数据流控制,我们使用无数据流控制的默认设置
myCom->setTimeout(10);//延时
//信号与槽关联,当串口有数据时改变数据接收标志
connect(myCom,SIGNAL(readyRead()),this,SLOT(receiveData()));
}

void serialSendThread::stop()
{
stopComThread = true;
}


void serialSendThread::run()
{
while(!stopComThread){
msleep(1);//延时1ms,防止CPU使用到100%

myCom->write("thread is running\n");
msleep(200);

if(receiveFlag){
myCom->write(receiveBuffer);//不清楚为什么发送不成功
myCom->write("\n");
msleep(200);
}
if(sendFlag){
myCom->write(sendBuffer);
myCom->write("\n");
msleep(200);
}
}
stopComThread = false;
}

void serialSendThread::receiveData()
{
receiveBuffer=myCom->readAll();
// myCom->write(receiveBuffer);//在这里可以发送成功
receiveFlag = true;
}


void serialSendThread::getSendCommand(const QByteArray data)
{
sendBuffer = data;
sendFlag = true;
}


serialSendThread.h 文件
#ifndef COMTHREAD_H
#define COMTHREAD_H

#include <QThread>
#include <QString>
#include "qextserialbase.h"
#include "win_qextserialport.h"

class serialSendThread : public QThread
{
Q_OBJECT
public:
serialSendThread(QString portName,BaudRateType baud);
Win_QextSerialPort *myCom;
void stop();

protected:
void run();

private slots:
void receiveData();
void getSendCommand(QByteArray);

private:
QByteArray sendBuffer;
QByteArray receiveBuffer;
volatile bool stopComThread;
volatile bool sendFlag;
volatile bool receiveFlag;
};


#endif // COMTHREAD_H




...全文
370 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
tcry 2012-09-19
  • 打赏
  • 举报
回复
把发送后的 msleep(200)去掉看看。
ymxl0826zz 2012-09-19
  • 打赏
  • 举报
回复
而且主进程发送的信号得到的sendBuffer的字节都可以发送成功
ymxl0826zz 2012-09-19
  • 打赏
  • 举报
回复
去掉msleep(200)后也没用呢,当我只发一个字节时就行,只要多于一个就不行;
后来我想用共享内存来做,发现在这个槽中竟无法创建共享内存;
是不是因为myCom也是一个线程,而且它可能是serialSendThread线程的一个子线程?
myCom这个线程的readyRead()信号是不是有特定限制?求高手解惑下啊……
receiveBuffer=myCom->readAll();
// myCom->write(receiveBuffer);//在这里可以发送成功

if (sharedMemory.isAttached())
sharedMemory.detach();
// load into shared memory
QBuffer buffer;
buffer.open(QBuffer::ReadWrite);
QDataStream out(&buffer);
out << receiveBuffer;
int size = buffer.size();

if (!sharedMemory.create(size)) {
qDebug("Unable to create shared memory segment.");
return;
}
sharedMemory.lock();
char *to = (char*)sharedMemory.data();
const char *from = buffer.data().data();
memcpy(to, from, qMin(sharedMemory.size(), size));
sharedMemory.unlock();

receiveFlag = true;

16,200

社区成员

发帖
与我相关
我的任务
社区描述
Qt 是一个跨平台应用程序框架。通过使用 Qt,您可以一次性开发应用程序和用户界面,然后将其部署到多个桌面和嵌入式操作系统,而无需重复编写源代码。
社区管理员
  • Qt
  • 亭台六七座
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧