Linux 下 QT 實(shí)現(xiàn)串口通訊小實(shí)例,代碼如下
- view plaincopy to clipboardprint?
- //ui_mainwindow.h
- #ifndef UI_MAINWINDOW_H
- #define UI_MAINWINDOW_H
- #include <QtCore/QVariant>
- #include <QtGui/QAction>
- #include <QtGui/QApplication>
- #include <QtGui/QButtonGroup>
- #include <QtGui/QHeaderView>
- #include <QtGui/QLabel>
- #include <QtGui/QMainWindow>
- #include <QtGui/QMenuBar>
- #include <QtGui/QPushButton>
- #include <QtGui/QStatusBar>
- #include <QtGui/QToolBar>
- #include <QtGui/QWidget>
- QT_BEGIN_NAMESPACE
- class Ui_MainWindow
- {
- public:
- QWidget *centralWidget;
- QPushButton *writeButton;
- QPushButton *readButton;
- QPushButton *closeButton;
- QLabel *dis_label;
- QMenuBar *menuBar;
- QToolBar *mainToolBar;
- QStatusBar *statusBar;
- void setupUi(QMainWindow *MainWindow)
- {
- if (MainWindow->objectName().isEmpty())
- MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
- MainWindow->resize(600, 400);
- centralWidget = new QWidget(MainWindow);
- centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
- writeButton = new QPushButton(centralWidget);
- writeButton->setObjectName(QString::fromUtf8("writeButton"));
- writeButton->setGeometry(QRect(100, 210, 75, 23));
- readButton = new QPushButton(centralWidget);
- readButton->setObjectName(QString::fromUtf8("readButton"));
- readButton->setGeometry(QRect(240, 210, 75, 23));
- closeButton = new QPushButton(centralWidget);
- closeButton->setObjectName(QString::fromUtf8("closeButton"));
- closeButton->setGeometry(QRect(390, 210, 75, 23));
- dis_label = new QLabel(centralWidget);
- dis_label->setObjectName(QString::fromUtf8("dis_label"));
- dis_label->setGeometry(QRect(200, 90, 191, 16));
- MainWindow->setCentralWidget(centralWidget);
- menuBar = new QMenuBar(MainWindow);
- menuBar->setObjectName(QString::fromUtf8("menuBar"));
- menuBar->setGeometry(QRect(0, 0, 600, 19));
- MainWindow->setMenuBar(menuBar);
- mainToolBar = new QToolBar(MainWindow);
- mainToolBar->setObjectName(QString::fromUtf8("mainToolBar"));
- MainWindow->addToolBar(Qt::TopToolBarArea, mainToolBar);
- statusBar = new QStatusBar(MainWindow);
- statusBar->setObjectName(QString::fromUtf8("statusBar"));
- MainWindow->setStatusBar(statusBar);
- retranslateUi(MainWindow);
- QMetaObject::connectSlotsByName(MainWindow);
- } // setupUi
- void retranslateUi(QMainWindow *MainWindow)
- {
- MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0, QApplication::UnicodeUTF8));
- writeButton->setText(QApplication::translate("MainWindow", "PushButton", 0, QApplication::UnicodeUTF8));
- readButton->setText(QApplication::translate("MainWindow", "PushButton", 0, QApplication::UnicodeUTF8));
- closeButton->setText(QApplication::translate("MainWindow", "PushButton", 0, QApplication::UnicodeUTF8));
- dis_label->setText(QApplication::translate("MainWindow", "TextLabel", 0, QApplication::UnicodeUTF8));
- } // retranslateUi
- };
- namespace Ui {
- class MainWindow: public Ui_MainWindow {};
- } // namespace Ui
- QT_END_NAMESPACE
- #endif // UI_MAINWINDOW_H
- //thread.h
- #ifndef THREAD_H
- #define THREAD_H
- #include<QThread>
- class Thread:public QThread
- {
- Q_OBJECT
- public:
- Thread();
- char buf[128];
- volatile bool stopped;
- volatile bool write_rs;
- volatile bool read_rs;
- protected:
- virtual void run();
- };
- #endif
- //thread.cpp
- #include"thread.h"
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <termios.h> //串口用到的
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <strings.h>
- #define BAUDRATE B9600
- #define RS_DEVICE "/dev/ttyS0" //串口0
- //#define RS_DEVICE "/dev/ttySAC1" //串口1
- Thread::Thread()
- {} //析構(gòu)
- void Thread::run() //這就是線程的具體工作了
- {
- int fd,c=0,res;
- struct termios oldtio,newtio; //termios結(jié)構(gòu)是用來保存波特率、字符大小等
- printf("start...\n");
- fd=open(RS_DEVICE,O_RDWR|O_NOCTTY); //以讀寫方式打開串口。不控制TTY
- if(fd<0)
- {
- perror("error");
- exit(1); //失敗退出
- }
- printf("Open...\n");
- tcgetattr(fd,&oldtio); //保存當(dāng)前設(shè)置到oldtio
- bzero(&newtio,sizeof(newtio)); //清除newtio結(jié)構(gòu),并重新對它的成員設(shè)置如下
- newtio.c_cflag=BAUDRATE|CS8|CLOCAL|CREAD; //9600、8位、忽略DCD信號、啟用接收裝置
- newtio.c_iflag|=IGNPAR; //忽略奇偶
- newtio.c_oflag=0;
- newtio.c_lflag=0;
- newtio.c_cc[VMIN]=0;
- newtio.c_cc[VTIME]=100; //在規(guī)定時間(VTIME)內(nèi)讀取(VMIN)個字符;
- tcflush(fd,TCIFLUSH); //清除所有隊列在串口的輸入與輸出;
- tcsetattr(fd,TCSANOW,&newtio); //把我們的設(shè)置寫入termios
- while(stopped) //stopped為0時將退出線程
- {
- if(write_rs) //write_rs為1時把字符串從串口中輸出
- {
- write_rs=0;
- write(fd,"QtEmbedded-4.5.1",16); //向串口中寫入字符,通過串口調(diào)試助手可看到QtEmbedded-4.5.1這個字符
- }
- if(read_rs) //read_rs為1時讀取,并存在buf
- {
- read_rs=0;
- res=read(fd,buf,10); //讀取串口的數(shù)據(jù)到buf
- buf[res]=0;
- emit finished(); //讀完后發(fā)一個信號
- }
- }
- printf("Close...\n");
- tcsetattr(fd,TCSANOW,&oldtio); //重新設(shè)置回原來的
- close(fd);
- quit();
- }
- //mainwindow.h
- #ifndef MAINWINDOW_H
- #define MAINWINDOW_H
- #include<QtGui>
- #include"ui_mainwindow.h" //奇怪?這個頭文件從哪里來的?呵呵,剛才用designer做的mainwindow.ui文件,經(jīng)過make后會生成這個頭文件,
- #include"thread.h" //把我們前面定義的線程包含進(jìn)來
- class MainWindow:public QMainWindow,public Ui::MainWindow //多繼承
- {
- Q_OBJECT
- public:
- MainWindow(QWidget *parent=0);
- public slots:
- void writeThread();
- void readThread();
- void closeThread();
- void display();
- private:
- Thread *yy;
- };
- #endif
- //mainwindow.cpp
- #include"mainwindow.h"
- MainWindow::MainWindow(QWidget *parent)
- :QMainWindow(parent)
- {
- setupUi(this);
- yy = new Thread;
- yy->start(); //啟動線程
- yy->stopped=1; //初始化變量
- yy->write_rs=0;
- yy->read_rs=0;
- connect(writeButton,SIGNAL(clicked()),this,SLOT(writeThread())); //信號與槽
- connect(readButton,SIGNAL(clicked()),this,SLOT(readThread()));
- connect(closeButton,SIGNAL(clicked()),this,SLOT(closeThread()));
- connect(yy,SIGNAL(finished()),this,SLOT(display())); //前面線程讀完了不是發(fā)一個信號么,這個信號就是發(fā)到這個槽
- }
- void MainWindow::display()
- {
- dis_label->setText(yy->buf); //讀到的在dis_label顯示,dis_label就是我們前面designer放的標(biāo)簽,顯示buf中的內(nèi)容
- }
- void MainWindow::writeThread() //前面線程都是根據(jù)stopped、write_rs、read_rs的狀態(tài)來工作的^_^
- {
- yy->write_rs=1;
- }
- void MainWindow::readThread()
- {
- yy->read_rs=1;
- }
- void MainWindow::closeThread()
- {
- yy->stopped=0;
- }
- //main.cpp
- #include<QApplication>
- #include"mainwindow.h"
- int main(int argc,char *argv[])
- {
- QApplication app(argc,argv);
- MainWindow mw;
- mw.show();
- return app.exec();
- }
- //ui_mainwindow.h
- #ifndef UI_MAINWINDOW_H
- #define UI_MAINWINDOW_H
- #include <QtCore/QVariant>
- #include <QtGui/QAction>
- #include <QtGui/QApplication>
- #include <QtGui/QButtonGroup>
- #include <QtGui/QHeaderView>
- #include <QtGui/QLabel>
- #include <QtGui/QMainWindow>
- #include <QtGui/QMenuBar>
- #include <QtGui/QPushButton>
- #include <QtGui/QStatusBar>
- #include <QtGui/QToolBar>
- #include <QtGui/QWidget>
- QT_BEGIN_NAMESPACE
- class Ui_MainWindow
- {
- public:
- QWidget *centralWidget;
- QPushButton *writeButton;
- QPushButton *readButton;
- QPushButton *closeButton;
- QLabel *dis_label;
- QMenuBar *menuBar;
- QToolBar *mainToolBar;
- QStatusBar *statusBar;
- void setupUi(QMainWindow *MainWindow)
- {
- if (MainWindow->objectName().isEmpty())
- MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
- MainWindow->resize(600, 400);
- centralWidget = new QWidget(MainWindow);
- centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
- writeButton = new QPushButton(centralWidget);
- writeButton->setObjectName(QString::fromUtf8("writeButton"));
- writeButton->setGeometry(QRect(100, 210, 75, 23));
- readButton = new QPushButton(centralWidget);
- readButton->setObjectName(QString::fromUtf8("readButton"));
- readButton->setGeometry(QRect(240, 210, 75, 23));
- closeButton = new QPushButton(centralWidget);
- closeButton->setObjectName(QString::fromUtf8("closeButton"));
- closeButton->setGeometry(QRect(390, 210, 75, 23));
- dis_label = new QLabel(centralWidget);
- dis_label->setObjectName(QString::fromUtf8("dis_label"));
- dis_label->setGeometry(QRect(200, 90, 191, 16));
- MainWindow->setCentralWidget(centralWidget);
- menuBar = new QMenuBar(MainWindow);
- menuBar->setObjectName(QString::fromUtf8("menuBar"));
- menuBar->setGeometry(QRect(0, 0, 600, 19));
- MainWindow->setMenuBar(menuBar);
- mainToolBar = new QToolBar(MainWindow);
- mainToolBar->setObjectName(QString::fromUtf8("mainToolBar"));
- MainWindow->addToolBar(Qt::TopToolBarArea, mainToolBar);
- statusBar = new QStatusBar(MainWindow);
- statusBar->setObjectName(QString::fromUtf8("statusBar"));
- MainWindow->setStatusBar(statusBar);
- retranslateUi(MainWindow);
- QMetaObject::connectSlotsByName(MainWindow);
- } // setupUi
- void retranslateUi(QMainWindow *MainWindow)
- {
- MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0, QApplication::UnicodeUTF8));
- writeButton->setText(QApplication::translate("MainWindow", "PushButton", 0, QApplication::UnicodeUTF8));
- readButton->setText(QApplication::translate("MainWindow", "PushButton", 0, QApplication::UnicodeUTF8));
- closeButton->setText(QApplication::translate("MainWindow", "PushButton", 0, QApplication::UnicodeUTF8));
- dis_label->setText(QApplication::translate("MainWindow", "TextLabel", 0, QApplication::UnicodeUTF8));
- } // retranslateUi
- };
- namespace Ui {
- class MainWindow: public Ui_MainWindow {};
- } // namespace Ui
- QT_END_NAMESPACE
- #endif // UI_MAINWINDOW_H
- //thread.h
- #ifndef THREAD_H
- #define THREAD_H
- #include<QThread>
- class Thread:public QThread
- {
- Q_OBJECT
- public:
- Thread();
- char buf[128];
- volatile bool stopped;
- volatile bool write_rs;
- volatile bool read_rs;
- protected:
- virtual void run();
- };
- #endif
- //thread.cpp
- #include"thread.h"
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <termios.h> //串口用到的
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <strings.h>
- #define BAUDRATE B9600
- #define RS_DEVICE "/dev/ttyS0" //串口0
- //#define RS_DEVICE "/dev/ttySAC1" //串口1
- Thread::Thread()
- {} //析構(gòu)
- void Thread::run() //這就是線程的具體工作了
- {
- int fd,c=0,res;
- struct termios oldtio,newtio; //termios結(jié)構(gòu)是用來保存波特率、字符大小等
- printf("start...\n");
- fd=open(RS_DEVICE,O_RDWR|O_NOCTTY); //以讀寫方式打開串口。不控制TTY
- if(fd<0)
- {
- perror("error");
- exit(1); //失敗退出
- }
- printf("Open...\n");
- tcgetattr(fd,&oldtio); //保存當(dāng)前設(shè)置到oldtio
- bzero(&newtio,sizeof(newtio)); //清除newtio結(jié)構(gòu),并重新對它的成員設(shè)置如下
- newtio.c_cflag=BAUDRATE|CS8|CLOCAL|CREAD; //9600、8位、忽略DCD信號、啟用接收裝置
- newtio.c_iflag|=IGNPAR; //忽略奇偶
- newtio.c_oflag=0;
- newtio.c_lflag=0;
- newtio.c_cc[VMIN]=0;
- newtio.c_cc[VTIME]=100; //在規(guī)定時間(VTIME)內(nèi)讀取(VMIN)個字符;
- tcflush(fd,TCIFLUSH); //清除所有隊列在串口的輸入與輸出;
- tcsetattr(fd,TCSANOW,&newtio); //把我們的設(shè)置寫入termios
- while(stopped) //stopped為0時將退出線程
- {
- if(write_rs) //write_rs為1時把字符串從串口中輸出
- {
- write_rs=0;
- write(fd,"QtEmbedded-4.5.1",16); //向串口中寫入字符,通過串口調(diào)試助手可看到QtEmbedded-4.5.1這個字符
- }
- if(read_rs) //read_rs為1時讀取,并存在buf
- {
- read_rs=0;
- res=read(fd,buf,10); //讀取串口的數(shù)據(jù)到buf
- buf[res]=0;
- emit finished(); //讀完后發(fā)一個信號
- }
- }
- printf("Close...\n");
- tcsetattr(fd,TCSANOW,&oldtio); //重新設(shè)置回原來的
- close(fd);
- quit();
- }
- //mainwindow.h
- #ifndef MAINWINDOW_H
- #define MAINWINDOW_H
- #include<QtGui>
- #include"ui_mainwindow.h" //奇怪?這個頭文件從哪里來的?呵呵,剛才用designer做的mainwindow.ui文件,經(jīng)過make后會生成這個頭文件,
- #include"thread.h" //把我們前面定義的線程包含進(jìn)來
- class MainWindow:public QMainWindow,public Ui::MainWindow //多繼承
- {
- Q_OBJECT
- public:
- MainWindow(QWidget *parent=0);
- public slots:
- void writeThread();
- void readThread();
- void closeThread();
- void display();
- private:
- Thread *yy;
- };
- #endif
- //mainwindow.cpp
- #include"mainwindow.h"
- MainWindow::MainWindow(QWidget *parent)
- :QMainWindow(parent)
- {
- setupUi(this);
- yy = new Thread;
- yy->start(); //啟動線程
- yy->stopped=1; //初始化變量
- yy->write_rs=0;
- yy->read_rs=0;
- connect(writeButton,SIGNAL(clicked()),this,SLOT(writeThread())); //信號與槽
- connect(readButton,SIGNAL(clicked()),this,SLOT(readThread()));
- connect(closeButton,SIGNAL(clicked()),this,SLOT(closeThread()));
- connect(yy,SIGNAL(finished()),this,SLOT(display())); //前面線程讀完了不是發(fā)一個信號么,這個信號就是發(fā)到這個槽
- }
- void MainWindow::display()
- {
- dis_label->setText(yy->buf); //讀到的在dis_label顯示,dis_label就是我們前面designer放的標(biāo)簽,顯示buf中的內(nèi)容
- }
- void MainWindow::writeThread() //前面線程都是根據(jù)stopped、write_rs、read_rs的狀態(tài)來工作的^_^
- {
- yy->write_rs=1;
- }
- void MainWindow::readThread()
- {
- yy->read_rs=1;
- }
- void MainWindow::closeThread()
- {
- yy->stopped=0;
- }
- //main.cpp
- #include<QApplication>
- #include"mainwindow.h"
- int main(int argc,char *argv[])
- {
- QApplication app(argc,argv);
- MainWindow mw;
- mw.show();
- return app.exec();
- }
本例中用到了線程,線程有一個好處就是可以單獨(dú)的去掃描串行端口,當(dāng)有數(shù)據(jù)發(fā)送到端口時,顯示相應(yīng)的字符到顯示框中。使用時注意波特率和串口的設(shè)置,這里用的波特率是9600,串口時ttyS0。