|     1.實驗目(mu)的     通過編寫(xie)多路復用(yong)式(shi)串口讀(du)寫(xie),進(jin)一步(bu)理(li)解多路復用(yong)函(han)數的用(yong)法(fa),同時更(geng)加熟(shu)練地掌握Linux設備文(wen)件的讀(du)寫(xie)方法(fa)。     2.實驗內容     本實(shi)驗中,實(shi)現兩臺(tai)機(ji)器(qi)(qi)(宿主機(ji)和目標板)之間的串口(kou)(kou)通信,而且每臺(tai)機(ji)器(qi)(qi)均(jun)可以發送數據(ju)(ju)和接收數據(ju)(ju)。 除了(le)串口(kou)(kou)設(she)備名(ming)稱(cheng)不同(tong)(宿主機(ji)上使(shi)用串口(kou)(kou)1:/dev/ttyS0,而在目標板上使(shi)用串口(kou)(kou)2:/dev/ttyS1),兩臺(tai)機(ji)器(qi)(qi)上的程序基本相同(tong)。     首先,程(cheng)序打開(kai)串口(kou)設(she)備文(wen)件并(bing)進行相關配(pei)置,調用select()函數(shu),使它等待從標(biao)準輸(shu)(shu)入(ru)(ru)(終端)文(wen)件中的(de)輸(shu)(shu)入(ru)(ru)數(shu)據(ju)(ju)及從串口(kou)設(she)備的(de)輸(shu)(shu)入(ru)(ru)數(shu)據(ju)(ju)。如果(guo)有標(biao)準輸(shu)(shu)入(ru)(ru)文(wen)件上的(de)數(shu)據(ju)(ju),則寫入(ru)(ru)到串口(kou),使對方讀取。如果(guo)有串口(kou)設(she)備上的(de)輸(shu)(shu)入(ru)(ru)數(shu)據(ju)(ju),則將(jiang)數(shu)據(ju)(ju)寫入(ru)(ru)到普(pu)通文(wen)件中。     3.實驗步驟     (1)畫出流程(cheng)圖。圖2.6所示為程(cheng)序流程(cheng)圖,兩(liang)臺機(ji)器上的程(cheng)序使用同樣的流程(cheng)圖。  圖(tu)2.6  宿主(zhu)機/目標板程序的流(liu)程圖(tu)
     (2)編寫代碼。編寫宿主機和目標板上(shang)的代碼,在這些程序中用到(dao)的open_port()和set_com_config()函數請參(can)照(zhao)后續章節所述,這里只列出宿主機上(shang)的代碼。     /* com_host.c */#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <errno.h>
 #include "uart_api.h"
 
 int main(void)
 {
 int fds[SEL_FILE_NUM], recv_fd, maxfd;
 char buff[BUFFER_SIZE];
 fd_set inset,tmp_inset;
 struct timeval tv;
 unsigned loop = 1;
 int res, real_read, i;
 /* 將從串口讀取的數據寫入到這個文件中 */
 if ((recv_fd = open(RECV_FILE_NAME, O_CREAT|O_WRONLY, 0644)) < 0)
 {
 perror("open");
 return 1;
 }
 
 fds[0] = STDIN_FILENO; /* 標準輸入 */
 if ((fds[1] = open_port(HOST_COM_PORT)) < 0) /* 打開串口 */
 {
 perror("open_port");
 return 1;
 }
 
 if (set_com_config(fds[1], 115200, 8, 'N', 1) < 0) /* 配置串口 */
 {
 perror("set_com_config");
 return 1;
 }
 
 FD_ZERO(&inset);
 FD_SET(fds[0], &inset);
 FD_SET(fds[1], &inset);
 maxfd = (fds[0] > fds[1])?fds[0]:fds[1];
 tv.tv_sec = TIME_DELAY;
 tv.tv_usec = 0;
 printf("Input some words(enter 'quit' to exit):\n");
 while (loop && (FD_ISSET(fds[0], &inset) || FD_ISSET(fds[1], &inset)))
 {
 tmp_inset = inset;
 res = select(maxfd + 1, &tmp_inset, NULL, NULL, &tv);
 switch(res)
 {
 case -1: /* 錯誤 */
 {
 perror("select");
 loop = 0;
 }
 break;
 
 case 0: /* 超時 */
 {
 perror("select time out");
 loop = 0;
 }
 break;
 
 default:
 {
 for (i = 0; i < SEL_FILE_NUM; i++)
 {
 if (FD_ISSET(fds[i], &tmp_inset))
 {
 memset(buff, 0, BUFFER_SIZE);
 /* 讀取標準輸入或者串口設備文件 */
 real_read = read(fds[i], buff, BUFFER_SIZE);
 if ((real_read < 0) && (errno != EAGAIN))
 {
 loop = 0;
 }
 else if (!real_read)
 {
 close(fds[i]);
 FD_CLR(fds[i], &inset);
 }
 else
 {
 buff[real_read] = '\0';
 if (i == 0)
 { /* 將從終端讀取的數據寫入到串口 */
 write(fds[1], buff, strlen(buff));
 printf("Input some words
 (enter 'quit' to exit):\n");
 }
 else if (i == 1)
 { /* 將從串口讀取的數據寫入到普通文件中 */
 write(recv_fd, buff, real_read);
 }
 if (strncmp(buff, "quit", 4) == 0)
 { /* 如果讀取為quit則退出 */
 loop = 0;
 }
 }
 } /* end of if FD_ISSET */
 } /* for i */
 }
 } /* end of switch */
 } /* end of while */
 close(recv_fd);
 return 0;
 }
     (3)接下來,將目標板的串口程序交(jiao)叉編(bian)譯,再將宿主(zhu)機的串口程序在PC上編(bian)譯。     (4)連(lian)接PC的(de)(de)串(chuan)口(kou)1和開發(fa)(fa)板(ban)(ban)的(de)(de)串(chuan)口(kou)2,然(ran)后將目標(biao)板(ban)(ban)串(chuan)口(kou)程序(xu)下載到開發(fa)(fa)板(ban)(ban)上,分別在(zai)兩臺機器(qi)上運行串(chuan)口(kou)程序(xu)。     4.實驗結果(guo)     宿(su)主機上的運行(xing)結果(guo)如下(xia)所示:     $ ./com_host Input some words(enter 'quit' to exit):
 Hello, Target!
 Input some words(enter 'quit' to exit):
 I'm host program!
 Input some words(enter 'quit' to exit):
 Byebye!
 Input some words(enter 'quit' to exit):
 quit  	/* 這個(ge)輸入使雙方的(de)程序都結(jie)束(shu) */
     從串口讀(du)取的(de)(de)數據(即目標板(ban)中發送過來(lai)的(de)(de)數據)寫入到同目錄下的(de)(de)recv.dat文件中。     $ cat recv.dat Hello, Host!
 I'm target program!
 Byebye!
     目標板上的運行結果(guo)如下所示:     $ ./com_target Input some words(enter 'quit' to exit):
 Hello, Host!
 Input some words(enter 'quit' to exit):
 I'm target program!
 Input some words(enter 'quit' to exit):
 Byebye!
     與宿主(zhu)機上的代碼相(xiang)同,從串(chuan)口讀取的數(shu)據(ju)(即目(mu)標板中發送(song)過來(lai)的數(shu)據(ju))寫(xie)入到同目(mu)錄下的recv.dat文件中。     $ cat recv.dat Hello, Target!
 I'm host program!
 Byebye!
 Quit
     請讀者用poll()函數(shu)實現具有以上功(gong)能的代碼。     本文選自華清遠見嵌入式培訓教材《從實踐中學嵌入式Linux應用程序開發》    熱點鏈接(jie):     
         1、Linux下多路復用I/O接口2、嵌入式Linux串口應用編程之串口讀寫
 3、嵌入式Linux串口應用編程之串口配置
 4、嵌入式Linux串口應用編程基礎知識
 5、標準I/O操作的緩沖存儲類型
 
 更多新聞>>  |