qt c++ c语言Linux串口通信服务

串口开线程读写的数据,你可以根据自己的配置修改,接收数据和发送数据加强。内核缓存串口数据,你一次传输100个字符,一次就能接收完,否则你就要循环一百次接收数据,如果循环过快内核来不及缓存,那你接收到的数据就不确定了

注意内核接收到数据123abc调用read一次直接从内核拿123abc,如果没有那你就要调用6次read才能拿到完整的123abc,如果你超出内核接收大小数据会被截断,别的情况同样数据是拿到数据有时123a可能会是12等其他情况

一定要谨慎

头文件SerialPortServer.h 

#ifndef SERIALPORTSERVER_H
#define SERIALPORTSERVER_H

#include <QString>
#include <QObject>
#include <QThread>
#include <QTimer>

#include <stdio.h>          //标准输入输出定义
#include <string.h>
#include <unistd.h>         //Unix 标准函数定义
#include <stdlib.h>         //标准函数库定义
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>          //文件控制定义
#include <termios.h>        //PPSIX 终端控制定义
#include <errno.h>          //错误号定义

typedef struct _SERIAL_PORT_PAR {
    QString baudRate;
    QString dataBits;
    QString parity;
    QString stopBits;
    QString splitChar;
} SERIAL_PORT_PAR;

class SerialPortServer : public QThread
{
    Q_OBJECT
public:
    SerialPortServer();
    ~SerialPortServer();

    int startServer();
    int uardfd();

private slots:
    void onTimeout();

private:
    void readSerialPortData();
    int replyData();

protected:
    void run();

private:
    int m_fd_uart;
    SERIAL_PORT_PAR _par;
    QByteArray m_recv_data;

    QTimer m_timer;
};

#endif

 源文件SerialPortServer.cpp

#include "SerialPortServer.h"
#include <QDebug>

SerialPortServer::SerialPortServer()
{
    m_recv_data.clear();
    m_fd_uart=0;
    //配置串口通信
    _par.baudRate = "19200";
    _par.dataBits = "8";
    _par.parity = "无";
    _par.stopBits = "1";
    _par.splitChar = ";";

    connect(&m_timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
}

void SerialPortServer::onTimeout()
{
}

SerialPortServer::~SerialPortServer()
{
}

/*
这里一直等待串口数据
*/
void SerialPortServer::run()
{
    if(m_fd_uart <= 0){
        qDebug() << "串口未打开,服务线程启动失败";
        return ;
    }

    m_timer.start(1000);
    fd_set rdfd;
    //struct timeval timeout = {1, 500 * 1000};
    struct timeval timeout = {3, 0};
    int maxfd = m_fd_uart + 1;
    int retval = 0;
    qDebug() << "SerialPortServer::run()";
    while(1){
        FD_ZERO(&rdfd);
        FD_SET(m_fd_uart, &rdfd);
        retval = select(maxfd, &rdfd, NULL, NULL, &timeout);
        if(retval < 0){
            if(errno == EINTR)
                continue;
            //Error
            QString str = QString("接受数据出错:%1").arg(strerror(errno));
            qDebug() << str;
            break;
        }else if(retval == 0){
            usleep(1000);
            continue;
        }

        if (FD_ISSET(m_fd_uart, &rdfd)){
            readSerialPortData();
        }
    }

    m_timer.stop();
    close(m_fd_uart);
    m_fd_uart = 0;
    qDebug() << "服务线程退出";
}

/*
接收串口发送过来的数据
读到对方发送的Do you love me?  中文就是你爱我吗
*/
void SerialPortServer::readSerialPortData()
{
    if (m_fd_uart)
    {
        char buf[255] = {0};
        int ret = read(m_fd_uart, buf, 255);
        //printf("len: %d, data: %s\n", ret, buf);
        if (ret > 0)
            m_recv_data.append(buf, ret);

        //收到数据校验 如果是Do you love me?  你就可以调用函数replyData回复love you你爱他
        int index1 = m_recv_data.indexOf("Do you love me?");
        if(index1 == 0) {
            m_recv_data.clear();
            replyData();
        }

        if(m_recv_data.length()>5){
            m_recv_data.clear();
        }
    }
}

int SerialPortServer::uardfd()
{
    return m_fd_uart;
}

//你可以回复对方数据
int SerialPortServer::replyData() 
{
    //qDebug() << "replyPrintData: " << m_markspeed << ", " << text_data;
    char packet[13] = {"love you"};
    if (m_fd_uart){
        write(m_fd_uart, packet, sizeof(packet));
    }

    return 0;
}

int SerialPortServer::startServer() //开始服务
{
    if (m_fd_uart)
    {
        close(m_fd_uart);
        m_fd_uart = 0;
    }

    m_fd_uart = open("/dev/ttymxc2", O_RDWR | O_NOCTTY | O_NONBLOCK);		//非阻塞方式
    if (m_fd_uart < 0)
    {
        m_fd_uart = 0;
        printf("打开串口设备错误\n");
        return -1;
    }

    struct termios opt;
    if (tcgetattr(m_fd_uart, &opt) != 0)
    {
        //printf("error: tcgetattr fd\n");
        close(m_fd_uart);
        m_fd_uart = 0;
        printf("串口错误: tcgetattr fd\n");
        return -2;
    }
    tcflush(m_fd_uart, TCIOFLUSH);
    speed_t baudRate;
    if (_par.baudRate == "2400")
        baudRate = B2400;
    else if (_par.baudRate == "4800")
        baudRate = B4800;
    else if (_par.baudRate == "9600")
        baudRate = B9600;
    else if (_par.baudRate == "19200")
        baudRate = B19200;
    else if (_par.baudRate == "38400")
        baudRate = B38400;
    else if (_par.baudRate == "57600")
        baudRate = B57600;
    else if (_par.baudRate == "115200")
        baudRate = B115200;
    else
        baudRate = B38400;
    cfsetispeed(&opt, baudRate);
    cfsetospeed(&opt, baudRate);

    opt.c_cflag &= ~CSIZE;
    if (_par.dataBits == "8")
        opt.c_cflag |= CS8;		//数据位8
    else
        opt.c_cflag |= CS7;		//数据位7

    if (_par.stopBits == "2")
        opt.c_cflag |= CSTOPB;		//停止位2
    else
        opt.c_cflag &= ~CSTOPB;		//停止位1

    if (_par.parity == "无")
        opt.c_cflag &= ~PARENB;		//无校验
    else if (_par.parity == "奇")
    {
        opt.c_cflag |= PARODD;		//奇校验
        opt.c_cflag |= PARENB;		//使能校验
    }
    else if (_par.parity == "偶")
    {
        opt.c_cflag &= ~PARODD;		//偶校验
        opt.c_cflag |= PARENB;		//使能校验
    }
    else
    {
        opt.c_cflag &= ~PARENB;		//无校验
    }

    opt.c_cflag |= (CLOCAL | CREAD);

    opt.c_lflag &= ~(ICANON | ECHO |ECHOE | ISIG);

    opt.c_oflag &= ~OPOST;
    opt.c_oflag &= ~(ONLCR | OCRNL);

    opt.c_iflag |= INPCK;
    opt.c_iflag &= ~(ICRNL | INLCR | IGNCR);
    opt.c_iflag &= ~(IXON | IXOFF | IXANY);

    tcflush(m_fd_uart, TCIOFLUSH);

    opt.c_cc[VTIME] = 0;
    opt.c_cc[CMIN] = 0;

    if (tcsetattr(m_fd_uart, TCSANOW, &opt) != 0)
    {
        close(m_fd_uart);
        m_fd_uart = 0;
        printf("串口错误: 2 tcsetattr fd");
        return -3;
    }
    tcflush(m_fd_uart, TCIOFLUSH);

    start();//启动线程run函数

    return 0;
}

Qt C 串口助手是一个基于Qt库和C语言开发串口通信辅助工具。它可以实现与串口设备的连接、数据的发送和接收、调试信息的显示等功能。 首先,Qt C 串口助手通过Qt库提供的QSerialPort类,简化了串口通信的编程过程。我们可以使用QSerialPort类来打开指定的串口设备,并设置波特率、数据位、校验位等参数。同时,还可以监听串口收到的数据。 其次,在串口助手的界面中,我们可以通过按钮或菜单选项来进行串口的连接和断开。当串口成功连接后,我们可以将待发送的数据输入到发送文本框中,然后点击发送按钮将数据发送出去。同时,接收区域会实时显示串口接收到的数据。这样方便了用户对串口的操作和数据的收发。 此外,Qt C 串口助手还提供了数据的调试功能。用户可以选择以ASCII码或十六进制的形式来显示接收到的数据。这对于调试串口设备时特别有用。用户还可以选择是否在接收区域显示时间戳,以便记录每条数据的接收时间。 最后,Qt C 串口助手还具备其他辅助功能,比如清除接收区、保存接收到的数据到本地文件、设置串口超时时间等。这些功能的设计使得串口助手更加实用和便捷。 综上所述,Qt C 串口助手是一个功能完善的串口通信辅助工具。它采用Qt库和C语言开发,具备串口连接、数据发送和接收、调试信息显示等功能,帮助用户轻松实现串口通信
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值