Linux下基于QT串口编程测试一

Linux下基于QT串口编程测试一


本文博客链接: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;
}

说明:

串口在驱动中有一个缓存区,收到的数据会存放在里面,如果一次发送数据很多,而读取间隔很短,则每次读取都是整个数据包的片段.


你可能感兴趣的:(linux)