環境:
主機:Fedora 12
開發軟件:QT
目標板:MINI6410
實現功能:
目標板接收PC串口傳過來的信息並在終端輸出,目標板串口接收信息用SELECT機制
源代碼:
widget.h:
[cpp]
- #ifndef WIDGET_H
- #define WIDGET_H
-
- #include <QWidget>
- #include <QDebug>
- #include <QTimer>
- #include <unistd.h>
- #include <sys/types.h>
- #include <fcntl.h>
- #include <sys/stat.h>
- #include <stdio.h>
- #include <sys/param.h>
- #include <QVector>
- #include <QByteArray>
- #include <QQueue>
- #include <QSemaphore>
- #include <iostream>
- #include <QFile>
- #include "QThread"
- #include <QtGui>
- #include <QMutex>
- #include <QtNetwork>
- #include <QUdpSocket>
- #include <sys/ioctl.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <linux/soundcard.h>
- #include <alsa/asoundlib.h>
- #include <QtGui/QMainWindow>
- #include <QtGui/QDialog>
- #include <QtGui/QPushButton>
- #include <QtGui/QHBoxLayout>
- #include <QtGui/QVBoxLayout>
- #include <QtGui/QGridLayout>
- #include <QTextCodec>
- #include <QtGui/QToolButton>
- #include <qsocketnotifier.h>
- #include <QTimer>
- #include <QtNetwork/QUdpSocket>
- #include <iostream>
- #include <qmessagebox.h>
- #include <qstringlist.h>
- #include <QtNetwork>
- #include <QUdpSocket>
- #include <QSound>
- #include <QMap>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <linux/soundcard.h>
- #include "sys/select.h"
- #include "termios.h"
-
- namespace Ui {
- class Widget;
- }
-
- class Widget : public QWidget
- {
- Q_OBJECT
-
- public:
- explicit Widget(QWidget *parent = 0);
- ~Widget();
-
- private:
- Ui::Widget *ui;
- };
-
- //端口信息定義
- typedef struct _Port_Info
- {
- int baud_rate;
- int port_fd;
- char parity;
- char stop_bit;
- char flow_ctrl;
- char data_bits;
- }*Port_Info;
-
- //打開串口
- int open_port(char *port);
- //關閉串口
- void close_port(int fd);
- //根據波特率獲得波特率設置參數
- int get_baud_rate(unsigned long baud_rate);
- //設置端口參數
- int set_port(Port_Info p_info);
- //通過串口發送數據,只能寫COMPRESS_BYTE長度數據,發送時加文件頭"JDH"
- int send_data(int fd,char *data,int data_len);
-
- #endif // WIDGET_H
widget.c:
[cpp]
- #include "widget.h"
- #include "ui_widget.h"
-
- int Fd_Com;
- #define COM "/dev/ttySAC1"
-
- char buffer_com[1024 + 10];
- char buffer_read_com[1024];
- int send_index;
-
- //打開串口
- int open_port(char *port)
- {
- int fd;
- if ((fd = open(port,O_RDWR | O_NOCTTY |O_NONBLOCK)) == -1)
- {
- perror("can not open com port!");
- return -1;
- }
- }
-
- //關閉指定串口
- void close_port(int fd)
- {
- close(fd);
- }
-
- //根據波特率獲得響應的波特率設置參數
- int get_baud_rate(unsigned long baud_rate)
- {
- switch (baud_rate)
- {
- case 2400:
- return B2400;
- case 4800:
- return B4800;
- case 9600:
- return B9600;
- case 19200:
- return B19200;
- case 38400:
- return B38400;
- case 57600:
- return B57600;
- case 115200:
- return B115200;
- case 230400:
- return B230400;
- default:
- return -1;
- }
- }
-
- //設置端口
- int set_port(Port_Info p_info)
- {
- struct termios old_opt,new_opt;
- int baud_rate,parity;
-
- memset(&old_opt,0,sizeof(old_opt));
- memset(&new_opt,0,sizeof(new_opt));
-
- cfmakeraw(&new_opt);
- tcgetattr(p_info->port_fd,&old_opt);
-
- //設置串口波特率
- baud_rate = get_baud_rate(p_info->baud_rate);
- //修改new_opt結構中的串口輸入/輸出波特率槽參數
- cfsetispeed(&new_opt,baud_rate);
- cfsetospeed(&new_opt,baud_rate);
-
- //修改控制模式,保證程序不會占用串口
- new_opt.c_cflag |= CLOCAL;
- //修改控制模式,使得能夠從串口讀取輸入數據
- new_opt.c_cflag |= CREAD;
-
- //設置數據流控制
- switch (p_info->flow_ctrl)
- {
- case '0':
- {
- //不使用流控制
- new_opt.c_cflag &= ~CRTSCTS;
- break;
- }
- case '1':
- {
- //使用硬件進行流控制
- new_opt.c_cflag |= CRTSCTS;
- break;
- }
- case '2':
- {
- new_opt.c_cflag |= IXON | IXOFF | IXANY;
- break;
- }
- }
-
- //設置數據位
- new_opt.c_cflag &= ~CSIZE;
- switch (p_info->data_bits)
- {
- case '5':
- {
- new_opt.c_cflag |= CS5;
- break;
- }
- case '6':
- {
- new_opt.c_cflag |= CS6;
- break;
- }
- case '7':
- {
- new_opt.c_cflag |= CS7;
- break;
- }
- case '8':
- {
- new_opt.c_cflag |= CS8;
- break;
- }
- default:
- {
- new_opt.c_cflag |= CS8;
- break;
- }
- }
-
- //設置奇偶校驗位
- switch (p_info->parity)
- {
- case '0':
- {
- //不使用奇偶校驗
- new_opt.c_cflag &= ~PARENB;
- break;
- }
- case '1':
- {
- //使用偶校驗
- new_opt.c_cflag |= PARENB;
- new_opt.c_cflag &= ~PARODD;
- break;
- }
- case '2':
- {
- //使用奇校驗
- new_opt.c_cflag |= PARENB;
- new_opt.c_cflag |= PARODD;
- break;
- }
- }
-
- //設置停止位
- if (p_info->stop_bit == '2')
- {
- new_opt.c_cflag |= CSTOPB;
- }
- else
- {
- new_opt.c_cflag &= ~CSTOPB;
- }
-
- //修改輸出模式,原始數據輸出
- new_opt.c_oflag *= ~OPOST;
- //修改控制字符,讀取字符最小個數為1
- new_opt.c_cc[VMIN] = 1;
- //修改控制字符,讀取第一個字符等待等待1 *(1/10)s
- new_opt.c_cc[VTIME] = 1;
-
- //如果發生數據溢出,接收數據,但是不再讀取
- tcflush(p_info->port_fd,TCIFLUSH);
-
- int result;
- result = tcsetattr(p_info->port_fd,TCSANOW,&new_opt);
- if (result == -1)
- {
- perror("cannot set the serial port parameters");
- return -1;
- }
-
- tcgetattr(p_info->port_fd,&old_opt);
- return result;
- }
-
- Widget::Widget(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::Widget)
- {
- ui->setupUi(this);
-
- //串口初始化
- //打開串口
- Fd_Com = open_port(COM);
- //設置串口通信參數
- struct _Port_Info info;
- info.baud_rate = 115200;
- info.data_bits = 8;
- info.flow_ctrl = 0;
- info.port_fd = Fd_Com;
- info.stop_bit = 1;
- info.parity = 0;
-
- if (set_port(&info) == -1)
- {
- printf("set com para wrong!!!!!!!!!!!!!");
- }
-
- int err = 0;
- struct timeval wait_time;
- fd_set read_fds;
- int len_com = 0;
-
- char *data = "jdh";
- int len = write(Fd_Com,data,3);
- if (len != 3)
- {
- //如果出現溢出情況
- qDebug() << "yi chu";
- tcflush(Fd_Com,TCOFLUSH);
- }
-
- while (1)
- {
- wait_time.tv_sec = 0;
- wait_time.tv_usec = 20000;
- FD_ZERO(&read_fds);
- FD_SET(Fd_Com,&read_fds);
-
- //err = select(Fd_Com + 1,&read_fds,NULL,NULL,&wait_time);
- err = select(Fd_Com + 1,&read_fds,NULL,NULL,NULL);
- if (err < 0)
- {
- perror("select fail");
- continue;
- }
- else
- {
- if (err == 0)
- {
- //超時返回
- //qDebug() << "chao shi";
- continue;
- }
- }
-
- //讀取串口聲卡
- //判斷聲卡是否允許讀,不允許讀退出
- if (FD_ISSET(Fd_Com,&read_fds))
- {
- qDebug() << "du qu sheng ka";
- //讀取串口緩存所有數據
- len_com = read(Fd_Com,buffer_read_com,1024);
- qDebug() << "read com byte = " << len_com;
-
- QByteArray temp;
- temp.append(buffer_read_com,len_com);
- qDebug() << temp;
- }
- }
-
- qDebug() << "end";
- }
-
- Widget::~Widget()
- {
- delete ui;
- }
說明:
串口在驅動中有一個緩存區,收到的數據會存放在裡面,如果一次發送數據很多,而讀取間隔很短,則每次讀取都是整個數據包的片段.