歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux下基於Qt串口編程測試

Linux下基於Qt串口編程測試

日期:2017/3/1 10:38:53   编辑:Linux編程

環境:

主機:Fedora 12

開發軟件:QT

目標板:MINI6410

實現功能:

目標板接收PC串口傳過來的信息並在終端輸出,目標板串口接收信息用SELECT機制


源代碼:

widget.h:

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

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

說明:

串口在驅動中有一個緩存區,收到的數據會存放在裡面,如果一次發送數據很多,而讀取間隔很短,則每次讀取都是整個數據包的片段.

Copyright © Linux教程網 All Rights Reserved