Linux下实现串口读写操作 #include “mainwindow.h” #include “ui_mainwindow.h” #include <QMessageBox> #include <QTime> #include <QDebug> #include <fcntl.h> #include “stdio.h” #include “termios.h” #include “unistd.h” #include “limits.h” #include <stdint.h> #include “time.h” //=================== #include <sys/select.h> #include <sys/time.h> //=================== #define UART_DEV “/dev/ttyS0” MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_2_clicked() { int fd =0; int RxLen=0; int flag =0; uint8_t RxBuff[100]; uint8_t SenBuff[2]={0xaa,0xbb}; //==========串口打开============// fd = open(UART_DEV ,O_RDWR|O_NOCTTY); if(fd<0) QMessageBox::information(NULL, “COM”,”COM Open Fail !”); //==========配置串口============// struct termios opt; //配置串口的属性定义在结构体struct termios中 tcgetattr(fd, & opt); //终端控制属性 cfsetispeed(& opt, B); //指定输入波特率 cfsetospeed(& opt, B); //指定输出波特率 /* c_lflag 本地模式 */ opt.c_cflag &= ~ INPCK; //不启用输入奇偶检测 opt.c_cflag |= (CLOCAL | CREAD); //CLOCAL忽略 modem 控制线,CREAD打开接受者 /* c_lflag 本地模式 */ opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); //ICANON启用标准模式;ECHO回显输入字符;ECHOE如果同时设置了 ICANON,字符 ERASE 擦除前一个输入字符,WERASE 擦除前一个词;ISIG当接受到字符 INTR, QUIT, SUSP, 或 DSUSP 时,产生相应的信号 /* c_oflag 输出模式 */ opt.c_oflag &= ~ OPOST; //OPOST启用具体实现自行定义的输出处理 opt.c_oflag &= ~(ONLCR | OCRNL); //ONLCR将输出中的新行符映射为回车-换行,OCRNL将输出中的回车映射为新行符 /* c_iflag 输入模式 */ opt.c_iflag &= ~(ICRNL | INLCR); //ICRNL将输入中的回车翻译为新行 (除非设置了 IGNCR),INLCR将输入中的 NL 翻译为 CR opt.c_iflag &= ~(IXON | IXOFF | IXANY); //IXON启用输出的 XON/XOFF流控制,IXOFF启用输入的 XON/XOFF流控制,IXANY(不属于 POSIX.1;XSI) 允许任何字符来重新开始输出 /* c_cflag 控制模式 */ opt.c_cflag &= ~ CSIZE; //字符长度掩码,取值为 CS5, CS6, CS7, 或 CS8,加~就是无 opt.c_cflag |= CS8; //数据宽度是8bit opt.c_cflag &= ~ CSTOPB; //CSTOPB设置两个停止位,而不是一个,加~就是设置一个停止位 opt.c_cflag &= ~ PARENB; //PARENB允许输出产生奇偶信息以及输入的奇偶校验,加~就是无校验 /* c_cc[NCCS] 控制字符 */ opt.c_cc[VTIME] = 0 ; //等待数据时间(10秒的倍数),每个单位是0.1秒 20就是2秒 opt.c_cc[VMIN] = 255 ; //最少可读数据,非规范模式读取时的最小字符数,设为0则为非阻塞,如果设为其它值则阻塞,直到读到到对应的数据,就像一个阀值一样,比如设为8,如果只接收到3个数据,那么它是不会返回的,只有凑齐8个数据后一齐才READ返回,阻塞在那儿 /* new_cfg.c_cc[VMIN] = 8;//DATA_LEN; new_cfg.c_cc[VTIME] = 20;//每个单位是0.1秒 20就是2秒 如果这样设置,就完全阻塞了,只有串口收到至少8个数据才会对READ立即返回,或才少于8个数据时,超时2秒也会有返回 另外特别注意的是当设置VTIME后,如果read第三个参数小于VMIN ,将会将VMIN 修改为read的第三个参数*/ /*TCIFLUSH 刷清输入队列 TCOFLUSH 刷清输出队列 TCIOFLUSH 刷清输入、输出队列*/ tcflush(fd, TCIOFLUSH); //刷串口清缓存 tcsetattr(fd, TCSANOW, &opt); //设置终端控制属性,TCSANOW:不等数据传输完毕就立即改变属性 //==========串口发送============// int TxLen = write(fd,SenBuff,2); //如果你要连续发几包数据到下位机,需要对不同包之间的数据发生加延时,不然会出现粘包的情况;或者你还可以在下位机进行拆包处理 while(1) { /* 添加sleep延时,让下位机串口数据全到缓存区,否则会出现只读到一部分数据情况,具体原因未知,可能虚拟机导致,不过该方法会导致接收变慢; 或者可以直接修改opt.c_cc[VMIN]的值,改为阻塞接收,这里就是用来这个方法; 或者直接修改为一次接收一个数据,根据累计接收到的数据判断你是否接收完成*/ //sleep(1); //==========串口接收============// while( ((RxLen = read(fd, RxBuff, 24)) > 0) ) { for(int i=0;i<RxLen;i++) qDebug(“Rbuff[%d] = %x”,i,RxBuff[i]); flag=1; break; } if(flag==1) break; } while(1) { //==========串口接收============// while( ((RxLen = read(fd, RxBuff, 4)) > 0) ) { for(int i=0;i<RxLen;i++) qDebug(“4 Rbuff[%d] = %x”,i,RxBuff[i]); flag=1; break; } if(flag==1) break; } flag=0; ui->textA->setText(QString::number(fd)); ui->textB->setText(QString::number(RxLen)); ui->textC->setText(QString::number(TxLen)); ::close(fd); }
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/28402.html