Linux操作系統(tǒng)下的串口通信學(xué)習(xí)筆記2007-04-15 17:08一、什么是串口通信
轉(zhuǎn)貼自:http://hi.baidu.com/foxberry/blog/item/ecb59718e0f0860634fa410a.html 串口通信是指計(jì)算機(jī)主機(jī)與外設(shè)之間以及主機(jī)系統(tǒng)與主機(jī)系統(tǒng)之間數(shù)據(jù)的串行傳送。使用 串口通信時(shí),發(fā)送和接收到的每一個(gè)字符實(shí)際上都是一次一位的傳送的,每一位為1或者為 0。 二、串口通信的分類 串口通信可以分為同步通信和異步通信兩類。同步通信是按照軟件識(shí)別同步字符來(lái)實(shí)現(xiàn)數(shù) 據(jù)的發(fā)送和接收,異步通信是一種利用字符的再同步技術(shù)的通信方式。 2.1同步通信 同步通信是一種連續(xù)串行傳送數(shù)據(jù)的通信方式,一次通信只傳送一幀信息。這里的信息幀 與異步通信中的字符幀不同,通常含有若干個(gè)數(shù)據(jù)字符。如圖: 單同步字符幀結(jié)構(gòu) +-----+------+-------+------+-----+--------+-------+-------+ |同步|數(shù)據(jù) |數(shù)據(jù) |數(shù)據(jù) | ... |數(shù)據(jù) |CRC1|CRC2| |字符|字符1|字符2|字符3| |字符N| | | +-----+------+-------+------+-----+--------+-------+-------+ 雙同步字符幀結(jié)構(gòu) +-----+--------+------+-------+---+-------+-------+--------+ |同步 |同步 |數(shù)據(jù) |數(shù)據(jù) | ... |數(shù)據(jù) |CRC1|CRC2| |字符1|字符2|字符1|字符2| |字符N| | | +-----+--------+------+-------+---+-------+-------+--------+ 它們均由同步字符、數(shù)據(jù)字符和校驗(yàn)字符(CRC)組成。其中同步字符位于幀開(kāi)頭,用于確 認(rèn)數(shù)據(jù)字符的開(kāi)始。數(shù)據(jù)字符在同步字符之后,個(gè)數(shù)沒(méi)有限制,由所需傳輸?shù)臄?shù)據(jù)塊長(zhǎng)度 來(lái)決定;校驗(yàn)字符有1到2個(gè),用于接收端對(duì)接收到的字符序列進(jìn)行正確性的校驗(yàn)。 同步通信的缺點(diǎn)是要求發(fā)送時(shí)鐘和接收時(shí)鐘保持嚴(yán)格的同步。 2.2異步通信 異步通信中,數(shù)據(jù)通常以字符或者字節(jié)為單位組成字符幀傳送。字符幀由發(fā)送端逐幀發(fā)送 ,通過(guò)傳輸線被接收設(shè)備逐幀接收。發(fā)送端和接收端可以由各自的時(shí)鐘來(lái)控制數(shù)據(jù)的發(fā)送 和接收,這兩個(gè)時(shí)鐘源彼此獨(dú)立,互不同步。 接收端檢測(cè)到傳輸線上發(fā)送過(guò)來(lái)的低電平邏輯"0"(即字符幀起始位)時(shí),確定發(fā)送端已開(kāi) 始發(fā)送數(shù)據(jù),每當(dāng)接收端收到字符幀中的停止位時(shí),就知道一幀字符已經(jīng)發(fā)送完畢。 在異步通行中有兩個(gè)比較重要的指標(biāo):字符幀格式和波特率。 (1)字符幀,由起始位、數(shù)據(jù)位、奇偶校驗(yàn)位和停止位組成。如圖: 無(wú)空閑位字符幀 +--+---+---+---+---+--+--+--+--+--+--+--+---+---+---+--+--+ |D7|0/1| 1 | 0 |D0|D1|D2|D3|D4|D5|D6|D7|0/1| 1 | 0 |D0|D1| +--+---+---+---+--+--+--+--+--+--+--+--+---+---+---+--+--+ 奇偶 停 起 奇偶 停 起 校驗(yàn) 止 始 校驗(yàn) 止 始 位 位 位 位 有空閑位字符幀 +---+---+--+--+--+--+--+--+--+--+---+---+---+---+---+---+--+ | 1 | 0 |D0|D1|D2|D3|D4|D5|D6|D7|0/1| 1 | 1 | 1 | 1 | 0 |D0| +---+---+--+--+--+--+--+--+--+--+---+---+---+---+---+---+--+ 空 起 奇偶 停 空 閑 位 起 閑 始 校驗(yàn) 止 始 位 位 位 位 1.起始位:位于字符幀開(kāi)頭,占1位,始終為邏輯0電平,用于向接收設(shè)備表示發(fā)送端開(kāi)始 發(fā)送一幀信息。 2.數(shù)據(jù)位:緊跟在起始位之后,可以設(shè)置為5位、6位、7位、8位,低位在前高位在后。 3.奇偶校驗(yàn)位:位于數(shù)據(jù)位之后,僅占一位,用于表示串行通信中采用奇校驗(yàn)還是偶校驗(yàn) 。 (2)波特率,波特率是每秒鐘傳送二進(jìn)制數(shù)碼的位數(shù),單位是b/s。 異步通信的優(yōu)點(diǎn)是不需要傳送同步脈沖,字符幀長(zhǎng)度也不受到限制。缺點(diǎn)是字符幀中因?yàn)? 包含了起始位和停止位,因此降低了有效數(shù)據(jù)的傳輸速率。 三、什么是RS-232 RS-232-C 接口(又稱 EIA RS-232-C)它是在 1970 年由美國(guó)電子工業(yè)協(xié)會(huì)(EISB2.0、網(wǎng) 卡接口、Modem接口、VGA接口、擴(kuò)展塢、IEEE 1394以及六合一讀卡器,常用的端口一應(yīng)俱 全。 HP Ze2022AP Ze2022AP外觀上采用了惠普經(jīng)典的Pavilion DV1000的模具,模具成熟,外觀無(wú)可挑剔。銀 白色的主色調(diào),再經(jīng)過(guò)磨砂處理,視覺(jué)效果和觸感都相當(dāng)理想。Ze2202AP外形方方正正, 棱角分明,同時(shí)惠普還頗費(fèi)心思地在前后采用了傾斜的切割,整個(gè)外形更顯精細(xì)動(dòng)感。 Ze2202AP的端口主要分布在左右兩端,右側(cè)有2個(gè)USB接口、1個(gè)1394接口, SD/MS/MMC多功 能存儲(chǔ)卡讀取插槽,還有COMBO光驅(qū),以及S端口。左側(cè)從后到前分布電源接口、VGA輸出接 口、基座擴(kuò)展接口、 RJ11/RJ45網(wǎng)絡(luò)接口,1個(gè)USB接口,以及PCMCIA擴(kuò)展插槽。除此之外 ,這款機(jī)型同樣配備擴(kuò)展端口,擴(kuò)展性無(wú)疑是相當(dāng)強(qiáng)大的。 ThinkPad R50e 1834HC1 IBM的R系列實(shí)際上是T系列的經(jīng)濟(jì)版本,有人將其形象地表示為“偷工減料版的T”,外形 上依然承襲了IBM“小黑”一貫的酷。這款R50e頂蓋材料采用了ABS工程塑料,但借助不錯(cuò) 的頂蓋框架,強(qiáng)度還是不錯(cuò)的。 R150e的端口相對(duì)齊全,不僅有ThinkPad經(jīng)典的指定桿,接口上還包括RJ45/11網(wǎng)絡(luò)接口、 兩個(gè)USB接口、PC卡插槽、VGA接口、S視頻端口,但沒(méi)有IEEE1394接口,對(duì)經(jīng)常使用數(shù)碼產(chǎn) 品的消費(fèi)者無(wú)疑是個(gè)壞消息。 五、全雙工與半雙工 1.全雙工,表示機(jī)器可以同時(shí)發(fā)送數(shù)據(jù)也可以接收數(shù)據(jù),有兩個(gè)獨(dú)立的數(shù)據(jù)通道(一個(gè)用 于發(fā)送,一個(gè)用于接收) 2.半雙工,表示機(jī)器不能在發(fā)送數(shù)據(jù)的同時(shí)也接收數(shù)據(jù)。 六、流量控制 1.使用軟件方法 使用特殊的字符來(lái)標(biāo)記數(shù)據(jù)流的開(kāi)始和結(jié)束,比如XON,DC1,八進(jìn)制021來(lái)標(biāo)志開(kāi)始,用X0F F,DC3,八進(jìn)制023來(lái)標(biāo)志結(jié)束。 2.使用硬件方法 使用RS232的CTS和RTS信號(hào)來(lái)代替特殊字符控制。當(dāng)接收方準(zhǔn)備接收更多數(shù)據(jù)時(shí),設(shè)置CTS 為0,反之設(shè)置成1。對(duì)應(yīng)的發(fā)送端準(zhǔn)備發(fā)送數(shù)據(jù)時(shí),設(shè)置RTS為0。 七、串口的訪問(wèn) 串口設(shè)備在LINUX下與所有設(shè)備一樣都是通過(guò)設(shè)備文件來(lái)進(jìn)行訪問(wèn)。 7.1打開(kāi)串口 LINUX系統(tǒng)下串口設(shè)備是通過(guò)open函數(shù)來(lái)打開(kāi)的,不過(guò)需要注意的是,一般用戶是沒(méi)有權(quán)限 訪問(wèn)設(shè)備文件的,需要將打開(kāi)的串口設(shè)備的訪問(wèn)權(quán)限設(shè)置成一般用戶可以訪問(wèn)的權(quán)限。 open函數(shù) 頭文件 #include #include #include 函數(shù)原型 int open(const char *pathname, int oflag, .../*, mode_t mode*/); 參數(shù) const char *pathname - 要打開(kāi)文件的文件名稱,例如/dev/ttyS0 int oflag - 文件打開(kāi)方式,可用標(biāo)志如下: O_RDONLY 以只讀方式打開(kāi)文件 O_WRONLY 以只寫(xiě)方式打開(kāi)文件 O_RDWR 以讀寫(xiě)方式打開(kāi)文件 O_APPEND 寫(xiě)入數(shù)據(jù)時(shí)添加到文件末尾 O_CREATE 如果文件不存在則產(chǎn)生該文件,使用該標(biāo)志需要設(shè)置訪問(wèn)權(quán)限位mode_t O_EXCL 指定該標(biāo)志,并且指定了O_CREATE標(biāo)志,如果打開(kāi)的文件存在則會(huì)產(chǎn)生一個(gè)錯(cuò)誤 O_TRUNC 如果文件存在并且成功以寫(xiě)或者只寫(xiě)方式打開(kāi),則清除文件所有內(nèi)容,使得文件 長(zhǎng)度變?yōu)? O_NOCTTY 如果打開(kāi)的是一個(gè)終端設(shè)備,這個(gè)程序不會(huì)成為對(duì)應(yīng)這個(gè)端口的控制終端,如果 沒(méi)有該標(biāo)志,任何一個(gè)輸入,例如鍵盤中止信號(hào)等,都將影響進(jìn)程。 O_NONBLOCK 該標(biāo)志與早期使用的O_NDELAY標(biāo)志作用差不多。程序不關(guān)心DCD信號(hào)線的狀態(tài) ,如果指定該標(biāo)志,進(jìn)程將一直在休眠狀態(tài),直到DCD信號(hào)線為0。 O_SYNC 對(duì)I/O進(jìn)行寫(xiě)等待 返回值 成功返回文件描述符,如果失敗返回-1 例如:以可讀寫(xiě)方式打開(kāi)/dev/ttyS0設(shè)備 int fd; /* 文件描述符 */ fd = open("/dev/ttyS0", O_RDWR | 0_NOCTTY | O_NONBLOCK); 7.2關(guān)閉串口 Linux系統(tǒng)下通過(guò)close函數(shù)來(lái)關(guān)閉串口設(shè)備 close函數(shù) 頭文件 #include 函數(shù)原型 int close(int filedes); 參數(shù) int filedes - 文件描述符 返回值 成功返回0,否則返回-1 例如:關(guān)閉打開(kāi)的串口設(shè)備fd int ret; /* 返回標(biāo)志,用于判斷是否正常關(guān)閉設(shè)備 */ ret = close(fd); 7.3寫(xiě)串口 寫(xiě)串口是通過(guò)write函數(shù)來(lái)完成的 write函數(shù) 頭文件 #include 函數(shù)原型 ssize_t write(int filedes, const void *buff, size_t nbytes); 參數(shù) int filedes - 文件描述符 const void *buff - 存儲(chǔ)寫(xiě)入數(shù)據(jù)的數(shù)據(jù)緩沖區(qū) size_t nbytes - 寫(xiě)入數(shù)據(jù)字節(jié)數(shù) 返回值 ssize_t - 返回寫(xiě)入數(shù)據(jù)的字節(jié)數(shù),該值通常等于nbytes,如果寫(xiě)入失敗返回-1 例如:向終端設(shè)備發(fā)送初始化命令 int n = 0; /* 寫(xiě)入字節(jié)數(shù) */ n = write(fd, "ATZ\r", 4); if(n == -1) { fprintf(stderr, "Wirte ATZ command error.\n"); } 7.4讀串口 讀串口是通過(guò)read函數(shù)來(lái)完成的 read函數(shù) 頭文件 #include 函數(shù)原型 ssize_t read(int filedes, void *buff, size_t nbytes); 參數(shù) int filedes - 文件描述符 void *buff - 存儲(chǔ)讀取數(shù)據(jù)的數(shù)據(jù)緩沖區(qū) size_t nbytes - 需要讀取的字節(jié)數(shù) 返回值 ssize_t - 成功讀取返回讀取的字節(jié)數(shù),否則返回-1 注意,在對(duì)串口進(jìn)行讀取操作的時(shí)候,如果是使用的RAW模式,每個(gè)read系統(tǒng)調(diào)用將返回當(dāng) 前串行輸入緩沖區(qū)中存在的字節(jié)數(shù)。如果沒(méi)有數(shù)據(jù),將會(huì)一致阻塞到有字符達(dá)到或者間隔 時(shí)鐘到期,或者發(fā)生錯(cuò)誤。如果想使read函數(shù)在沒(méi)有數(shù)據(jù)的時(shí)候立即返回則可以使用fcnt l函數(shù)來(lái)設(shè)置文件訪問(wèn)屬性。例如: fcntl(fd, F_SETFL, FNDELAY); 這樣設(shè)置后,當(dāng)沒(méi)有可讀取的數(shù)據(jù)時(shí),read函數(shù)立即返回0。 通過(guò)fcntl(fd, F_SETFL, 0)可以設(shè)置回一般狀態(tài)。 例如:從終端讀取5個(gè)字節(jié)的應(yīng)答數(shù)據(jù) int nRead; /* 從終端讀取的字節(jié)數(shù) */ char buffer[256]; /* 接收緩沖區(qū) */ nRead = read(fd, buffer, 5); if(nRead == -1) { fprintf(stderr, "Read answer message error.\n"); } 八、終端配置 8.1 POSIX終端接口 大多數(shù)系統(tǒng)都支持POSIX終端接口,POSIX終端通過(guò)一個(gè)termios結(jié)構(gòu)來(lái)進(jìn)行控制,該結(jié)構(gòu)定 義在termios.h文件中。 termios結(jié)構(gòu) struct termios { tcflag_t c_iflag; /* 輸入選項(xiàng)標(biāo)志 */ tcflag_t c_oflag; /* 輸出選項(xiàng)標(biāo)志 */ tcflag_t c_cflag; /* 控制選項(xiàng)標(biāo)志 */ tcflag_t c_lflag; /* 本地選項(xiàng)標(biāo)志 */ cc_t c_cc[NCCS]; /* 控制特性 */ }; c_iflag成員 Flag Description GNBRK 忽略輸入中的BREAK狀態(tài) BRKINT 如果設(shè)置了IGNBRK,將忽略BREAK。如果沒(méi)有設(shè)置,但是設(shè)置了BRKINT,那么BREA K將使得輸入和輸出隊(duì)列被刷新,如果終端是一個(gè)前臺(tái)進(jìn)程組的控制終端,這個(gè)進(jìn)程組中所 有進(jìn)程將收到SIGINT信號(hào)。如果既未設(shè)置IGNBRK也未設(shè)置BRKINT,BREAK將視為NUL同義字 符,除非設(shè)置了PARMRK,這種情況下被視為序列\(zhòng)377\0\0 IGNPAR 忽略楨錯(cuò)誤和奇偶校驗(yàn)錯(cuò)誤 PARMRK 如果沒(méi)有設(shè)置IGNPAR,在有奇偶校驗(yàn)錯(cuò)誤或者楨錯(cuò)誤的字符前插入\377\0。如果既 沒(méi)有設(shè)置IGNPAR也沒(méi)有設(shè)置PARMRK,將所有奇偶校驗(yàn)錯(cuò)誤或者楨錯(cuò)誤的字符視為\0。 |
|
來(lái)自: orion360doc > 《串口編程》