新聞中心
隨著計(jì)算機(jī)技術(shù)逐漸普及,串口通信逐漸成為計(jì)算機(jī)與外設(shè)之間數(shù)據(jù)交換的常用方式。在Linux系統(tǒng)中,使用串口通信可以通過串口設(shè)備文件進(jìn)行操作。

然而,Linux中的串口通信并非一件易事,特別是在處理多個(gè)串口設(shè)備的情況下。在這種情況下,使用select函數(shù)可有效地提高串口通信的效率和穩(wěn)定性。
本文將介紹如何使。
一、select函數(shù)簡(jiǎn)介
select函數(shù)是Linux提供的一種I/O多路復(fù)用機(jī)制,通過該函數(shù)可同時(shí)監(jiān)聽多個(gè)文件描述符的讀寫狀態(tài),當(dāng)某個(gè)文件描述符就緒(可以讀寫)時(shí),select函數(shù)會(huì)通知應(yīng)用程序進(jìn)行相應(yīng)的操作。
select函數(shù)的原型為:
“`c
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set * exceptfds, struct timeval *timeout);
“`
其中,nfds為要監(jiān)聽的文件描述符的數(shù)量,readfds、writefds、exceptfds是三個(gè),分別包含了要監(jiān)聽的文件描述符的讀、寫、異常情況的文件描述符,timeout為用于設(shè)置超時(shí)等待的時(shí)間。
2、使用select函數(shù)實(shí)現(xiàn)串口通信
對(duì)于串口通信來說,每個(gè)串口設(shè)備都有一個(gè)單獨(dú)的文件描述符(file descriptor)與之對(duì)應(yīng),我們可以通過打開串口設(shè)備文件得到該描述符。這些描述符可以通過select函數(shù)統(tǒng)一進(jìn)行管理,以便在需要的時(shí)候監(jiān)聽它們的讀寫情況。
以下是使的基本步驟:
(1)打開串口設(shè)備
在使用select函數(shù)之前,我們需要首先打開串口設(shè)備,并將其配置為合適的工作模式。具體的打開串口及配置方法可參考相關(guān)的Linux開發(fā)書籍,這里不再贅述。
(2)在select函數(shù)中添加要監(jiān)聽的文件描述符
在打開串口設(shè)備后,需要將該設(shè)備的文件描述符添加到select函數(shù)中進(jìn)行監(jiān)聽。首先需要?jiǎng)?chuàng)建一個(gè)fd_set類型的。該結(jié)構(gòu)體實(shí)為一個(gè)位掩碼,用于標(biāo)志要監(jiān)聽的文件描述符。其定義如下:
“`c
typedef struct {
unsigned long fds_bits[FD_SETSIZE / __NFDBITS];
} fd_set;
“`
其中,F(xiàn)D_SETSIZE為的更大值(通常為1024),__NFDBITS為每個(gè)long型數(shù)據(jù)可以存儲(chǔ)的位數(shù),所以fds_bits數(shù)組的大小為FD_SETSIZE / __NFDBITS。
將文件描述符添加到fd_set中可通過FD_SET宏實(shí)現(xiàn),例如:
“`c
fd_set read_set;
FD_ZERO(&read_set); //清空
FD_SET(fd, &read_set); //添加fd到中
“`
以上代碼將讀取串口數(shù)據(jù)用到的文件描述符fd添加到了read_set中。
(3)調(diào)用select函數(shù)進(jìn)行監(jiān)聽
將文件描述符添加到fd_set后,接下來需要在select函數(shù)中使用該進(jìn)行監(jiān)聽。此時(shí),select函數(shù)將會(huì)阻塞進(jìn)程,等待任一一個(gè)文件描述符就緒。
以下是一個(gè)簡(jiǎn)單的select函數(shù)調(diào)用示例:
“`c
fd_set read_set;
FD_ZERO(&read_set);
FD_SET(fd, &read_set);
//timeout為超時(shí)時(shí)間
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
int ret = select(fd + 1, &read_set, NULL, NULL, &timeout);
if (ret == -1) {
perror(“select”);
}
else if (ret > 0) {
//有數(shù)據(jù)可讀
}
else {
//超時(shí)
}
“`
上述代碼將串口文件描述符添加到read_set中,并在timeout時(shí)間內(nèi)等待串口數(shù)據(jù)到來。如果串口數(shù)據(jù)準(zhǔn)備就緒,select函數(shù)將返回大于0的值,此時(shí)可以進(jìn)行讀取操作;如果超時(shí)時(shí)間到達(dá),select函數(shù)將返回0。
(4)讀取串口數(shù)據(jù)
當(dāng)select函數(shù)返回大于0的值時(shí),表示有串口數(shù)據(jù)已經(jīng)準(zhǔn)備就緒。此時(shí),我們可以通過read函數(shù)讀取數(shù)據(jù)并進(jìn)行相應(yīng)的處理。
讀取串口數(shù)據(jù)的具體操作可參照Linux串口開發(fā)相關(guān)文檔,這里不再贅述。
二、
使用select函數(shù)可以有效地簡(jiǎn)化Linux系統(tǒng)中的串口通信代碼,提高系統(tǒng)的性能和穩(wěn)定性。需要注意的是,當(dāng)使用select函數(shù)實(shí)現(xiàn)串口通信時(shí),需要在串口設(shè)備打開后將其文件描述符添加到fd_set中,同時(shí)還需要排除串口設(shè)置過程中的輸入/輸出操作。
在Linux系統(tǒng)中實(shí)現(xiàn)串口通信時(shí),使用select函數(shù)能為我們帶來諸多好處,值得開發(fā)者們一試。
相關(guān)問題拓展閱讀:
- 如何查看linux下串口是否可用?串口名稱等?
- linux管道和串口
如何查看linux下串口是否可用?串口名稱等?
分析如下:
1、查看串口是否可用,可以對(duì)串口發(fā)送數(shù)據(jù)比如對(duì)com1口,echo lyjie126 > /dev/ttyS0。
2、查看串口名稱使用 ls -l /dev/ttyS* 一般情況下串口的名稱全部在dev下面,如果你沒有外插串口卡的話默認(rèn)是dev下的ttyS* ,一般ttyS0對(duì)應(yīng)com1,ttyS1對(duì)應(yīng)com2,當(dāng)然也不一定是必然的;
3、查看串口驅(qū)動(dòng):cat /proc/tty/drivers/serial。
4、查看串口設(shè)備:dmesg | grep ttyS*。
擴(kuò)展資料
串口控制器顧名思義,就是可通過串口實(shí)現(xiàn)控制功能的一臺(tái)控制器。即由上位機(jī)通過串口發(fā)送特定協(xié)議格式的指令給控制器,進(jìn)而來控制外圍設(shè)備或器件,也叫單片機(jī)串口控制器。
串口控制器就是1臺(tái)寫入了串口通信程序的單片機(jī)控制器,有2種工作模式:
1)上位機(jī)監(jiān)控模式:可由上位機(jī)串口控制,實(shí)現(xiàn)串口監(jiān)控;
2)脫機(jī)控制模式:在通過上位機(jī)設(shè)置好相關(guān)參數(shù)后,也可脫離上位機(jī)進(jìn)行獨(dú)立控制。
串口控制器就是1臺(tái)寫入了串口通信程序的單片機(jī)控制器,有2種工作模式:
1)上位機(jī)監(jiān)控模式:可由上位機(jī)串口控制,實(shí)現(xiàn)串口監(jiān)控;
2)脫機(jī)控制模式:在通過上位機(jī)設(shè)置好相關(guān)參數(shù)后,也可脫離上位機(jī)進(jìn)行獨(dú)立控制。
參考資料來源:
百度百科:串口控制器
linux管道和串口
在游手linux下用
# include
# include
# include
# include
# include
# include
# include
# include
# include
int CommFd, TtyFd;
static void Error(const char *Msg)
{
fprintf (stderr, “%s\n”, Msg);
fprintf (stderr, “strerror() is %s\n”, strerror(errno));
exit(1);
}
static void Warning(const char *Msg)
{
fprintf (stderr, “Warning: %s\n”, Msg);
}
static int SerialSpeed(const char *SpeedString)
{
int SpeedNumber = atoi(SpeedString);
# define TestSpeed(Speed) if (SpeedNumber == Speed) return B##Speed
TestSpeed(1200);
TestSpeed(2400);
TestSpeed(4800);
TestSpeed(9600);
TestSpeed(19200);
TestSpeed(38400);
TestSpeed(57600);
TestSpeed(115200);
TestSpeed(230400);
Error(“Bad speed”);
return -1;
}
static void PrintUsage(void)
{
fprintf(stderr, “comtest – interactive program of comm port\n”);
fprintf(stderr, “press 3 times to quit\n\n”);
fprintf(stderr, “Usage: comtest \n”);
fprintf(stderr, “bit\喚磨扮n”);
fprintf(stderr, “x hex mode\n”);
fprintf(stderr, “o output to stdout too\n”);
fprintf(stderr, “c stdout output use color\n”);
fprintf(stderr, “和灶h print this help\n”);
exit(-1);
}
static inline void WaitFdWriteable(int Fd)
{
fd_set WriteSetFD;
FD_ZERO(&WriteSetFD);
FD_SET(Fd, &WriteSetFD);
if (select(Fd + 1, NULL, &WriteSetFD, NULL, NULL) = (y)) ? (x) : (y) )
if (select(max(CommFd, TtyFd) + 1, &ReadSetFD, NULL, NULL, NULL) = 3)
goto ExitLabel;
} else
EscKeyCount = 0;
}
}
}
ExitLabel:
if (tcsetattr(TtyFd, TCSANOW, &BackupTtyAttr)
Error(“Unable to set tty”);
return 0;
}
關(guān)于linux 串口 select的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。
成都創(chuàng)新互聯(lián)建站主營(yíng):成都網(wǎng)站建設(shè)、網(wǎng)站維護(hù)、網(wǎng)站改版的網(wǎng)站建設(shè)公司,提供成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、成都網(wǎng)站推廣、成都網(wǎng)站優(yōu)化seo、響應(yīng)式移動(dòng)網(wǎng)站開發(fā)制作等網(wǎng)站服務(wù)。
分享標(biāo)題:用select函數(shù)實(shí)現(xiàn)Linux串口通信(linux串口select)
當(dāng)前地址:http://www.fisionsoft.com.cn/article/djipoeg.html


咨詢
建站咨詢
