Linux下基于Qt串口编程测试


环境:

主机:Fedora 12

开发软件:QT

目标板:MINI6410

实现功能:

目标板接收PC串口传过来的信息并在终端输出,目标板串口接收信息用SELECT机制


源代码:

widget.h:

[cpp]
  1. #ifndef WIDGET_H   
  2. #define WIDGET_H   
  3.   
  4. #include <QWidget>   
  5. #include <QDebug>   
  6. #include <QTimer>   
  7. #include <unistd.h>   
  8. #include <sys/types.h>   
  9. #include <fcntl.h>   
  10. #include <sys/stat.h>   
  11. #include <stdio.h>   
  12. #include <sys/param.h>   
  13. #include <QVector>   
  14. #include <QByteArray>   
  15. #include <QQueue>   
  16. #include <QSemaphore>   
  17. #include <iostream>   
  18. #include <QFile>   
  19. #include "QThread"   
  20. #include <QtGui>   
  21. #include <QMutex>   
  22. #include <QtNetwork>   
  23. #include <QUdpSocket>   
  24. #include <sys/ioctl.h>   
  25. #include <stdlib.h>   
  26. #include <stdio.h>   
  27. #include <linux/soundcard.h>   
  28. #include <alsa/asoundlib.h>   
  29. #include <QtGui/QMainWindow>   
  30. #include <QtGui/QDialog>   
  31. #include <QtGui/QPushButton>   
  32. #include <QtGui/QHBoxLayout>   
  33. #include <QtGui/QVBoxLayout>   
  34. #include <QtGui/QGridLayout>   
  35. #include <QTextCodec>   
  36. #include <QtGui/QToolButton>   
  37. #include <qsocketnotifier.h>   
  38. #include <QTimer>   
  39. #include <QtNetwork/QUdpSocket>   
  40. #include <iostream>   
  41. #include <qmessagebox.h>   
  42. #include <qstringlist.h>   
  43. #include <QtNetwork>   
  44. #include <QUdpSocket>   
  45. #include <QSound>   
  46. #include <QMap>   
  47. #include <sys/socket.h>   
  48. #include <arpa/inet.h>   
  49. #include <linux/soundcard.h>   
  50. #include "sys/select.h"   
  51. #include "termios.h"   
  52.   
  53. namespace Ui {  
  54.     class Widget;  
  55. }  
  56.   
  57. class Widget : public QWidget  
  58. {  
  59.     Q_OBJECT  
  60.   
  61. public:  
  62.     explicit Widget(QWidget *parent = 0);  
  63.     ~Widget();  
  64.   
  65. private:  
  66.     Ui::Widget *ui;  
  67. };  
  68.   
  69. //端口信息定义   
  70. typedef struct _Port_Info  
  71. {  
  72.     int baud_rate;  
  73.     int port_fd;  
  74.     char parity;  
  75.     char stop_bit;  
  76.     char flow_ctrl;  
  77.     char data_bits;  
  78. }*Port_Info;  
  79.   
  80. //打开串口   
  81. int open_port(char *port);  
  82. //关闭串口   
  83. void close_port(int fd);  
  84. //根据波特率获得波特率设置参数   
  85. int get_baud_rate(unsigned long baud_rate);  
  86. //设置端口参数   
  87. int set_port(Port_Info p_info);  
  88. //通过串口发送数据,只能写COMPRESS_BYTE长度数据,发送时加文件头"JDH"   
  89. int send_data(int fd,char *data,int data_len);  
  90.   
  91. #endif // WIDGET_H  
widget.c:

[cpp]
  1. #include "widget.h"   
  2. #include "ui_widget.h"   
  3.   
  4. int Fd_Com;  
  5. #define COM "/dev/ttySAC1"   
  6.   
  7. char buffer_com[1024 + 10];  
  8. char buffer_read_com[1024];  
  9. int send_index;  
  10.   
  11. //打开串口   
  12. int open_port(char *port)  
  13. {  
  14.     int fd;  
  15.     if ((fd = open(port,O_RDWR | O_NOCTTY |O_NONBLOCK)) == -1)  
  16.     {  
  17.         perror("can not open com port!");  
  18.         return -1;  
  19.     }  
  20. }  
  21.   
  22. //关闭指定串口   
  23. void close_port(int fd)  
  24. {  
  25.     close(fd);  
  26. }  
  27.   
  28. //根据波特率获得响应的波特率设置参数   
  29. int get_baud_rate(unsigned long baud_rate)  
  30. {  
  31.     switch (baud_rate)  
  32.     {  
  33.     case 2400:  
  34.         return B2400;  
  35.     case 4800:  
  36.         return B4800;  
  37.     case 9600:  
  38.         return B9600;  
  39.     case 19200:  
  40.         return B19200;  
  41.     case 38400:  
  42.         return B38400;  
  43.     case 57600:  
  44.         return B57600;  
  45.     case 115200:  
  46.         return B115200;  
  47.     case 230400:  
  48.         return B230400;  
  49.     default:  
  50.         return -1;  
  51.     }  
  52. }  
  53.   
  54. //设置端口   
  55. int set_port(Port_Info p_info)  
  56. {  
  57.     struct termios old_opt,new_opt;  
  58.     int baud_rate,parity;  
  59.   
  60.     memset(&old_opt,0,sizeof(old_opt));  
  61.     memset(&new_opt,0,sizeof(new_opt));  
  62.   
  63.     cfmakeraw(&new_opt);  
  64.     tcgetattr(p_info->port_fd,&old_opt);  
  65.   
  66.     //设置串口波特率   
  67.     baud_rate = get_baud_rate(p_info->baud_rate);  
  68.     //修改new_opt结构中的串口输入/输出波特率槽参数   
  69.     cfsetispeed(&new_opt,baud_rate);  
  70.     cfsetospeed(&new_opt,baud_rate);  
  71.   
  72.     //修改控制模式,保证程序不会占用串口   
  73.     new_opt.c_cflag |= CLOCAL;  
  74.     //修改控制模式,使得能够从串口读取输入数据   
  75.     new_opt.c_cflag |= CREAD;  
  76.   
  77.     //设置数据流控制   
  78.     switch (p_info->flow_ctrl)  
  79.     {  
  80.     case '0':  
  81.         {  
  82.             //不使用流控制   
  83.             new_opt.c_cflag &= ~CRTSCTS;  
  84.             break;  
  85.         }  
  86.     case '1':  
  87.         {  
  88.             //使用硬件进行流控制   
  89.             new_opt.c_cflag |= CRTSCTS;  
  90.             break;  
  91.         }  
  92.     case '2':  
  93.         {  
  94.             new_opt.c_cflag |= IXON | IXOFF | IXANY;  
  95.             break;  
  96.         }  
  97.     }  
  98.   
  99.     //设置数据位   
  100.     new_opt.c_cflag &= ~CSIZE;  
  101.     switch (p_info->data_bits)  
  102.     {  
  103.     case '5':  
  104.         {  
  105.             new_opt.c_cflag |= CS5;  
  106.             break;  
  107.         }  
  108.     case '6':  
  109.         {  
  110.             new_opt.c_cflag |= CS6;  
  111.             break;  
  112.         }  
  113.     case '7':  
  114.         {  
  115.             new_opt.c_cflag |= CS7;  
  116.             break;  
  117.         }  
  118.     case '8':  
  119.         {  
  120.             new_opt.c_cflag |= CS8;  
  121.             break;  
  122.         }  
  123.     default:  
  124.         {  
  125.             new_opt.c_cflag |= CS8;  
  126.             break;  
  127.         }  
  128.     }  
  129.   
  130.     //设置奇偶校验位   
  131.     switch (p_info->parity)  
  132.     {  
  133.     case '0':  
  134.         {  
  135.             //不使用奇偶校验   
  136.             new_opt.c_cflag &= ~PARENB;  
  137.             break;  
  138.         }  
  139.     case '1':  
  140.         {  
  141.             //使用偶校验   
  142.             new_opt.c_cflag |= PARENB;  
  143.             new_opt.c_cflag &= ~PARODD;  
  144.             break;  
  145.         }  
  146.     case '2':  
  147.         {  
  148.             //使用奇校验   
  149.             new_opt.c_cflag |= PARENB;  
  150.             new_opt.c_cflag |= PARODD;  
  151.             break;  
  152.         }  
  153.     }  
  154.   
  155.     //设置停止位   
  156.     if (p_info->stop_bit == '2')  
  157.     {  
  158.         new_opt.c_cflag |= CSTOPB;  
  159.     }  
  160.     else  
  161.     {  
  162.         new_opt.c_cflag &= ~CSTOPB;  
  163.     }  
  164.   
  165.     //修改输出模式,原始数据输出   
  166.     new_opt.c_oflag *= ~OPOST;  
  167.     //修改控制字符,读取字符最小个数为1   
  168.     new_opt.c_cc[VMIN] = 1;  
  169.     //修改控制字符,读取第一个字符等待等待1 *(1/10)s   
  170.     new_opt.c_cc[VTIME] = 1;  
  171.   
  172.     //如果发生数据溢出,接收数据,但是不再读取   
  173.     tcflush(p_info->port_fd,TCIFLUSH);  
  174.   
  175.     int result;  
  176.     result = tcsetattr(p_info->port_fd,TCSANOW,&new_opt);  
  177.     if (result == -1)  
  178.     {  
  179.         perror("cannot set the serial port parameters");  
  180.         return -1;  
  181.     }  
  182.   
  183.     tcgetattr(p_info->port_fd,&old_opt);  
  184.     return result;  
  185. }  
  186.   
  187. Widget::Widget(QWidget *parent) :  
  188.     QWidget(parent),  
  189.     ui(new Ui::Widget)  
  190. {  
  191.     ui->setupUi(this);  
  192.   
  193.     //串口初始化   
  194.     //打开串口   
  195.     Fd_Com = open_port(COM);  
  196.     //设置串口通信参数   
  197.     struct _Port_Info info;  
  198.     info.baud_rate = 115200;  
  199.     info.data_bits = 8;  
  200.     info.flow_ctrl = 0;  
  201.     info.port_fd = Fd_Com;  
  202.     info.stop_bit = 1;  
  203.     info.parity = 0;  
  204.   
  205.     if (set_port(&info) == -1)  
  206.     {  
  207.         printf("set com para wrong!!!!!!!!!!!!!");  
  208.     }  
  209.   
  210.     int err = 0;  
  211.     struct timeval wait_time;  
  212.     fd_set read_fds;  
  213.     int len_com = 0;  
  214.   
  215.     char *data = "jdh";  
  216.     int len = write(Fd_Com,data,3);  
  217.     if (len != 3)  
  218.     {  
  219.         //如果出现溢出情况   
  220.         qDebug() << "yi chu";  
  221.         tcflush(Fd_Com,TCOFLUSH);  
  222.     }  
  223.   
  224.     while (1)  
  225.     {  
  226.         wait_time.tv_sec = 0;  
  227.         wait_time.tv_usec = 20000;  
  228.         FD_ZERO(&read_fds);  
  229.         FD_SET(Fd_Com,&read_fds);  
  230.   
  231.         //err = select(Fd_Com + 1,&read_fds,NULL,NULL,&wait_time);   
  232.         err = select(Fd_Com + 1,&read_fds,NULL,NULL,NULL);  
  233.         if (err < 0)  
  234.         {  
  235.             perror("select fail");  
  236.             continue;  
  237.         }  
  238.         else  
  239.         {  
  240.             if (err == 0)  
  241.             {  
  242.                 //超时返回   
  243.                 //qDebug() << "chao shi";   
  244.                 continue;  
  245.             }  
  246.         }  
  247.   
  248.         //读取串口声卡   
  249.         //判断声卡是否允许读,不允许读退出   
  250.         if (FD_ISSET(Fd_Com,&read_fds))  
  251.         {  
  252.             qDebug() << "du qu sheng ka";  
  253.             //读取串口缓存所有数据   
  254.             len_com = read(Fd_Com,buffer_read_com,1024);  
  255.             qDebug() << "read com byte = " << len_com;  
  256.   
  257.             QByteArray temp;  
  258.             temp.append(buffer_read_com,len_com);  
  259.             qDebug() << temp;  
  260.         }  
  261.     }  
  262.   
  263.     qDebug() << "end";  
  264. }  
  265.   
  266. Widget::~Widget()  
  267. {  
  268.     delete ui;  
  269. }  

说明:

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

  • 1
  • 2
  • 下一页

相关内容