本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.
环境:
主机:Fedora12
开发软件:QT
目标板:MINI6410
实现功能:
目标板接收PC串口传过来的信息并在终端输出,目标板串口接收信息用SELECT机制
源代码:
widget.h:
- #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:
- #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;
- }
说明:
串口在驱动中有一个缓存区,收到的数据会存放在里面,如果一次发送数据很多,而读取间隔很短,则每次读取都是整个数据包的片段.