1.實(shí)驗(yàn)?zāi)康?/p>
通過(guò)編寫(xiě)多路復(fù)用式串口讀寫(xiě),進(jìn)一步理解多路復(fù)用函數(shù)的用法,同時(shí)更加熟練地掌握Linux設(shè)備文件的讀寫(xiě)方法。
2.實(shí)驗(yàn)內(nèi)容
本實(shí)驗(yàn)中,實(shí)現(xiàn)兩臺(tái)機(jī)器(宿主機(jī)和目標(biāo)板)之間的串口通信,而且每臺(tái)機(jī)器均可以發(fā)送數(shù)據(jù)和接收數(shù)據(jù)。 除了串口設(shè)備名稱(chēng)不同(宿主機(jī)上使用串口1:/dev/ttyS0,而在目標(biāo)板上使用串口2:/dev/ttyS1),兩臺(tái)機(jī)器上的程序基本相同。
首先,程序打開(kāi)串口設(shè)備文件并進(jìn)行相關(guān)配置,調(diào)用select()函數(shù),使它等待從標(biāo)準(zhǔn)輸入(終端)文件中的輸入數(shù)據(jù)及從串口設(shè)備的輸入數(shù)據(jù)。如果有標(biāo)準(zhǔn)輸入文件上的數(shù)據(jù),則寫(xiě)入到串口,使對(duì)方讀取。如果有串口設(shè)備上的輸入數(shù)據(jù),則將數(shù)據(jù)寫(xiě)入到普通文件中。
3.實(shí)驗(yàn)步驟
(1)畫(huà)出流程圖。圖2.6所示為程序流程圖,兩臺(tái)機(jī)器上的程序使用同樣的流程圖。
 圖2.6 宿主機(jī)/目標(biāo)板程序的流程圖
(2)編寫(xiě)代碼。編寫(xiě)宿主機(jī)和目標(biāo)板上的代碼,在這些程序中用到的open_port()和set_com_config()函數(shù)請(qǐng)參照后續(xù)章節(jié)所述,這里只列出宿主機(jī)上的代碼。
/* 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;
/* 將從串口讀取的數(shù)據(jù)寫(xiě)入到這個(gè)文件中 */
if ((recv_fd = open(RECV_FILE_NAME, O_CREAT|O_WRONLY, 0644)) < 0)
{
perror("open");
return 1;
}
fds[0] = STDIN_FILENO; /* 標(biāo)準(zhǔn)輸入 */
if ((fds[1] = open_port(HOST_COM_PORT)) < 0) /* 打開(kāi)串口 */
{
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: /* 錯(cuò)誤 */
{
perror("select");
loop = 0;
}
break;
case 0: /* 超時(shí) */
{
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);
/* 讀取標(biāo)準(zhǔn)輸入或者串口設(shè)備文件 */
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)
{ /* 將從終端讀取的數(shù)據(jù)寫(xiě)入到串口 */
write(fds[1], buff, strlen(buff));
printf("Input some words
(enter 'quit' to exit):\n");
}
else if (i == 1)
{ /* 將從串口讀取的數(shù)據(jù)寫(xiě)入到普通文件中 */
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)接下來(lái),將目標(biāo)板的串口程序交叉編譯,再將宿主機(jī)的串口程序在PC上編譯。
(4)連接PC的串口1和開(kāi)發(fā)板的串口2,然后將目標(biāo)板串口程序下載到開(kāi)發(fā)板上,分別在兩臺(tái)機(jī)器上運(yùn)行串口程序。
4.實(shí)驗(yàn)結(jié)果
宿主機(jī)上的運(yùn)行結(jié)果如下所示:
$ ./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 /* 這個(gè)輸入使雙方的程序都結(jié)束 */
從串口讀取的數(shù)據(jù)(即目標(biāo)板中發(fā)送過(guò)來(lái)的數(shù)據(jù))寫(xiě)入到同目錄下的recv.dat文件中。
$ cat recv.dat
Hello, Host!
I'm target program!
Byebye!
目標(biāo)板上的運(yùn)行結(jié)果如下所示:
$ ./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!
與宿主機(jī)上的代碼相同,從串口讀取的數(shù)據(jù)(即目標(biāo)板中發(fā)送過(guò)來(lái)的數(shù)據(jù))寫(xiě)入到同目錄下的recv.dat文件中。
$ cat recv.dat
Hello, Target!
I'm host program!
Byebye!
Quit
請(qǐng)讀者用poll()函數(shù)實(shí)現(xiàn)具有以上功能的代碼。
本文選自華清遠(yuǎn)見(jiàn)嵌入式培訓(xùn)教材《從實(shí)踐中學(xué)嵌入式Linux應(yīng)用程序開(kāi)發(fā)》
熱點(diǎn)鏈接:
1、Linux下多路復(fù)用I/O接口
2、嵌入式Linux串口應(yīng)用編程之串口讀寫(xiě)
3、嵌入式Linux串口應(yīng)用編程之串口配置
4、嵌入式Linux串口應(yīng)用編程基礎(chǔ)知識(shí)
5、標(biāo)準(zhǔn)I/O操作的緩沖存儲(chǔ)類(lèi)型
更多新聞>> |