版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領
文檔簡介
1、在 Linux 串口編程的一些問題解決其實在linux下對串口的設置主要是通過termios這個結(jié)構(gòu)體實現(xiàn)的,但是這個結(jié)構(gòu)體卻沒有提供控制RTS或獲得CTS等串口引腳狀態(tài)的接口,可以通過ioctl系統(tǒng)調(diào)用來獲得/控制。獲得:ioctl(fd, TIOCMGET, &controlbits);if (controlbits & TIOCM_CTS)printf(“有信n號” );elseprintf(“無信n號” );設置:ioctl(fd, TIOCMGET, &ctrlbits) ; if (flag)ctrlbits |= TIOCM_RTS;elsectrlbits &= TIOCM_R
2、TS;ioctl(fd, TIOCMSET, &ctrlbits);其實 TIOCM_RTS有效后是把串口的RTS 設置為有信號,但串口的電平為低時是有信號,為高時為無信號,和用TIOCMGET獲得的狀態(tài)正好相反,也就是說TIOCMGET/TIOCMSET只是獲得 /控制串口的相應引腳是否有信號,并不反應當前串口的真實電平高低。網(wǎng)上許多流行的linux 串口編程的版本中都沒對c_iflag(termios 成員變量)這個變量進行有效的設置,這樣傳送ASCII 碼時沒什么問題,但傳送二進制數(shù)據(jù)時遇到0 x0d,0 x11和 0 x13 卻會被丟掉。不用說也知道, 這幾個肯定是特殊字符,被用作特殊
3、控制了。關(guān)掉 ICRNL 和 IXON 選項即可解決。c_iflag &= (ICRNL | IXON);0 x0d回車符 CR0 x11Q VSTART字符0 x13S VSTOP字符ICRNL 將輸入的CR 轉(zhuǎn)換為 NLIXON使起動 /停止輸出控制流起作用在 UNIX 環(huán)境高級編程第二版第 18 章第 11 小節(jié)看到把終端I/O 設置為原始模式(串口通訊就是終端I/O 的原始模式)時輸入屬性設置為term.c_iflag &= (BRKINT | ICRNL | INPCK |ISTRIP | IXON);屏蔽了許多屬性,怪不得有人說如果是使用串口通訊c_iflag和 c_oflag 都
4、設置為 0 就行了!以下是我的設置的一些重要的串口屬性term.c_cflag |= CLOCAL | CREAD;term.c_lflag &= (ICANON | ECHO | ECHOE | ISIG);term.c_oflag &= OPOST;term.c_iflag &= (BRKINT | ICRNL | INPCK | ISTRIP | IXON);static void request_send(void)ioctl(fd,TIOCMGET, &status);status&= TIOCM_RTS;RTS 引腳高電平ioctl(fd,TIOCMSET, &status);st
5、atic void clear_send(void)ioctl(fd,TIOCMGET, &status);status |=TIOCM_RTS;/RTS引腳低電平ioctl(fd,TIOCMSET, &status);int main(int argc, char *argv)intfd;structtermios opt;intlen;charcmd;/待發(fā)送數(shù)據(jù)charsbuf128=Hello,this is a Serial_Port test!n0;/使用 open 函數(shù)打開串口, 獲得串口設備文件的文件描述符if(fd=open(/dev/ttyAMA1,O_RDWR| O_NO
6、CTTY)=-1)perror(Cannot open the serial port);return 1;tcgetattr(fd, &opt);cfsetispeed(&opt,B115200 );/指定輸入波特率,9600bpscfsetospeed(&opt,B115200);/指定輸出波特率,9600bpsopt.c_cflag&=CSIZE;/將數(shù)據(jù)位修改為8bitopt.c_cflag|=CS8;opt.c_cflag|=CBAUD;無校驗opt.c_cflag&= PARENB;opt.c_cflag|=IXON|IXOFF|IXANY;軟件數(shù)據(jù)流控制/opt.c_cflag|
7、=CRTSCTS;硬件數(shù)據(jù)流控制/opt.c_cflag &=CRTSCTS;/ 不使用數(shù)據(jù)流控制tcsetattr(fd, TCSANOW , &opt);intstatus;ioctl(fd,TIOCMGET, &status);printf(status = xn, status);status &=TIOCM_RTS;/ RTS引腳高電平status |=TIOCM_RTS;/RTS引腳低電平printf(status = xn, status);ioctl(fd,TIOCMSET, &status);ioctl(fd,TIOCMGET, &status);printf(status
8、= xn, status);while(1)printf(sellect: w|r|qn);cmd = getchar();switch(cmd)case w:printf(test writen);/發(fā)送緩沖區(qū)字節(jié)數(shù)定義len= write(fd,sbuf,strlen(sbuf);if(len = -1)printf(Wirte sbuf error.n);elseprintf(Wirte:%s, sbuf);break;case r:printf(test readn);len = read(fd, sbuf, sizeof(sbuf);if(len = -1)printf(Read s
9、buf error.n);elseprintf(Read:%s, sbuf);break;case q:close(fd);return 0;case n:break;default:printf(worry cmd!n);break;close(fd);return0;Linux下串口編程遇到的接收數(shù)據(jù)錯誤及原因近日在調(diào)試串口的時候發(fā)現(xiàn),另一設備向我ARM板的串口發(fā)送 0 x0d ,我接收之后變成了0 x0a ,這是問題一;另外當對方向我發(fā)送一串數(shù)據(jù),如果其中有0 x11 ,那么我總是漏收此數(shù),這是問題二。由于問題莫名其妙,以為是筆記本的USB 轉(zhuǎn) 232 線纜的問題,換,問題依舊。以為是對
10、方設備的問題,采用串口調(diào)試助手模擬通訊設備與 ARM 板通訊,問題依舊。無奈才去查看資料,最終得以解決,現(xiàn)總結(jié)如下:1. 串口操作需要的頭文件#include /標準輸入輸出定義#include /標準函數(shù)庫定義#include /Unix標準函數(shù)定義#include #include #include /文件控制定義#include /POSIX中斷控制定義#include /錯誤號定義2. 打開串口串口位于/dev 中,可作為標準文件的形式打開,其中:串口 1 /dev/ttyS0串口 2 /dev/ttyS1代碼如下:int fd;fd = open(“ /dev/ttyS0” , O_
11、RDWR);if(fd = -1)Perror(“串口1 打開失?。 ?;/else/fcntl(fd, F_SETFL, FNDELAY);除了使用 O_RDWR標志之外,通常還會使用O_NOCTTY和 O_NDELAY 這兩個標志。O_NOCTTY :告訴 Unix 這個程序不想成為“控制終端”控制的程序,不說明這個標志的話, 任何輸入都會影響你的程序。O_NDELAY :告訴 Unix 這個程序不關(guān)心DCD 信號線狀態(tài),即其他端口是否運行,不說明這個標志的話,該程序就會在DCD 信號線為低電平時停止。3. 設置波特率最基本的串口設置包括波特率、校驗位和停止位設置,且串口設置主要使用ter
12、mios.h 頭文件中定義的termios 結(jié)構(gòu),如下:struct termiostcflag_t c_iflag; / 輸入模式標志tcflag_t c_oflag; /輸出模式標志tcflag_t c_cflag; /控制模式標志tcflag_t c_lflag; / 本地模式標志cc_t c_line; /line disciplinecc_t c_ccNCC; /control characters代碼如下: int speed_arr = B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600,
13、 B4800, B2400, B1200, B300, ;int name_arr = 38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, ;voidSetSpeed(int fd, int speed)int i;struct termios Opt; / 定義 termios 結(jié)構(gòu) if(tcgetattr(fd, &Opt) != 0)perror(“ tcgetattr fd” );return;for(i = 0; i sizeof(speed_arr) / siz
14、eof(int); i+)if(speed = name_arri)tcflush(fd, TCIOFLUSH);cfsetispeed(&Opt, speed_arri);cfsetospeed(&Opt, speed_arri);if(tcsetattr(fd, TCSANOW, &Opt) != 0)perror(“ tcsetattr fdreturn;tcflush(fd, TCIOFLUSH);” );注意 tcsetattr 函數(shù)中使用的標志:TCSANOW :立即執(zhí)行而不等待數(shù)據(jù)發(fā)送或者接受完成。TCSADRAIN :等待所有數(shù)據(jù)傳遞完成后執(zhí)行。TCSAFLUSH :Flush
15、 input and output buffers and make thechange4. 設置數(shù)據(jù)位、停止位和校驗位以下是幾個數(shù)據(jù)位、停止位和校驗位的設置方法:(以下均為1 位停止位)位數(shù)據(jù)位、無校驗位:Opt.c_cflag &= PARENB;Opt.c_cflag &= CSTOPB;Opt.c_cflag &= CSIZE;Opt.c_cflag |= CS8;位數(shù)據(jù)位、奇校驗:Opt.c_cflag |= PARENB;Opt.c_cflag |= PARODD;Opt.c_cflag &= CSTOPB;Opt.c_cflag &= CSIZE;Opt.c_cflag |= C
16、S7;位數(shù)據(jù)位、偶校驗:Opt.c_cflag |= PARENB;Opt.c_cflag &= PARODD;Opt.c_cflag &= CSTOPB;Opt.c_cflag &= CSIZE;Opt.c_cflag |= CS7;7 位數(shù)據(jù)位、 Space 校驗:Opt.c_cflag &= PARENB;Opt.c_cflag &= CSTOPB;Opt.c_cflag &= CSIZE;Opt.c_cflag |= CS7;代碼如下: int SetParity(int fd, int databits, int stopbits, int parity)struct termios
17、 Opt;if(tcgetattr(fd, &Opt) != 0)perror(tcgetattr fd);return FALSE;Opt.c_cflag |= (CLOCAL | CREAD); / 一般必設置的標志 switch(databits) / 設置數(shù)據(jù)位數(shù)case 7:Opt.c_cflag &= CSIZE;Opt.c_cflag |= CS7;break;case 8:Opt.c_cflag &= CSIZE;Opt.c_cflag |= CS8;berak;default:fprintf(stderr, Unsupported data size.n);return FA
18、LSE;switch(parity) /設置校驗位case n:case N:Opt.c_cflag &= PARENB; /清除校驗位Opt.c_iflag &= INPCK; /enable parity checkingbreak;case o:case O:Opt.c_cflag |= PARENB; /enable parityOpt.c_cflag |= PARODD; /奇校驗Opt.c_iflag |= INPCK /disable parity checkingbreak;case e:case E:Opt.c_cflag |= PARENB; /enable parityO
19、pt.c_cflag &= PARODD; /偶校驗Opt.c_iflag |= INPCK; /disable pairty checkingbreak;case s:case S:Opt.c_cflag &= PARENB; /清除校驗位Opt.c_cflag &= CSTOPB; /?Opt.c_iflag |= INPCK; /disable pairty checkingbreak;default:fprintf(stderr, Unsupported parity.n);return FALSE;switch(stopbits) /設置停止位case 1:Opt.c_cflag &
20、= CSTOPB;break;case 2:Opt.c_cflag |= CSTOPB;break;default:fprintf(stderr, Unsupported stopbits.n);return FALSE;opt.c_cflag |= (CLOCAL | CREAD);opt.c_lflag &= (ICANON | ECHO | ECHOE | ISIG);opt.c_oflag &= OPOST;opt.c_oflag &= (ONLCR | OCRNL); /添加的opt.c_iflag &= (ICRNL | INLCR);opt.c_iflag &= (IXON |
21、IXOFF | IXANY); /添加的tcflush(fd, TCIFLUSH);Opt.c_ccVTIME = 0; /設置超時為15secOpt.c_ccVMIN = 0; /Update the Opt and do it nowif(tcsetattr(fd, TCSANOW, &Opt) != 0)perror(tcsetattr fd);return FALSE;return TRUE;5.某些設置項在第四步中我們看到一些比較特殊的設置,下面簡述一下他們的作用。c_cc 數(shù)組的 VSTART 和 VSTOP 元素被設定成 DC1 和 DC3 ,代表 ASCII 標準的 XON 和
22、 XOFF 字符,如果在傳輸這兩個字符的時候就傳不過去,需要把軟件流控制屏蔽,即:Opt.c_iflag &= (IXON | IXOFF | IXANY);有時候,在用write 發(fā)送數(shù)據(jù)時沒有鍵入回車,信息就發(fā)送不出去,這主要是因為我們在輸入輸出時是按照規(guī)范模式接收到回車或換行才發(fā)送,而更多情況下我們是不必鍵入回車或換行的。此時應轉(zhuǎn)換到行方式輸入,不經(jīng)處理直接發(fā)送,設置如下:Opt.c_lflag &= (ICANON | ECHO | ECHOE | ISIG);還存在這樣的情況:發(fā)送字符0X0d 的時候,往往接收端得到的字符是0X0a,原因是因為在串口設置中c_iflag和c_ofla
23、g中存在從NL-CR和CR-NL的映射,即串口能把回車和換行當成同一個字符,可以進行如下設置屏蔽之:Opt.c_iflag &= (INLCR | ICRNL | IGNCR);Opt.c_oflag &= (ONLCR | OCRNL);6.讀寫串口發(fā)送數(shù)據(jù)方式如下, write 函數(shù)將返回寫的位數(shù)或者當錯誤時為-1 。char buffer1024;int length;int nByte;nByte = write(fd, buffer, length);讀取數(shù)據(jù)方式如下,原始數(shù)據(jù)模式下每個read 函數(shù)將返回實際串口收到的字符數(shù),如果串口中沒有字符可用,回叫將會阻塞直到以下幾種情況:有
24、字符進入;一個間隔計時器失效;錯誤發(fā)送。在打開串口成功后,使用fcntl(fd, F_SETFL, FNDELAY)語句,可以使 read 函數(shù)立即返回而不阻塞。FNDELAY選項使read 函數(shù)在串口無字符時立即返回且為0。char buffer1024;int length;int readByte;readByte = read(fd, buffer, len);注意:設置為原始模式傳輸數(shù)據(jù)的話,read 函數(shù)返回的字符數(shù)是實際串口收到的字符數(shù)。Linux 下直接用read 讀串口可能會造成堵塞,或者數(shù)據(jù)讀出錯誤,此時可使用tcntl 或者 select 等函數(shù)實現(xiàn)異步讀取。用selec
25、t 先查詢 com 口,再用 read 去讀就可以避免上述錯誤。關(guān)閉串口串口作為文件來處理,所以一般的關(guān)閉文件函數(shù)即可:close(fd);8. 例子這個例子中,需要打開串口1,設置 9600波特率、8 位數(shù)據(jù)位、 1 位停止位以及空校驗, 之后利用 while 語句循環(huán)判斷串口中是否可以讀出數(shù)據(jù),將串口中數(shù)據(jù)連續(xù)讀出后重新寫回到串口中。該程序可與minicom 聯(lián)合測試。 #include #include #include #include #include #include #include #include main()int fd;int i;int len;int n = 0;ch
26、ar read_buf256;char write_buf256;struct termios opt;fd = open(/dev/ttyS0, O_RDWR | O_NOCTTY); / 默認為阻塞讀方式if(fd = -1)perror(open serial 0n);exit(0);tcgetattr(fd, &opt);cfsetispeed(&opt, B9600);cfsetospeed(&opt, B9600);if(tcsetattr(fd, TCSANOW, &opt) != 0 )perror(tcsetattr error);return -1;opt.c_cflag
27、&= CSIZE;opt.c_cflag |= CS8;opt.c_cflag &= CSTOPB;opt.c_cflag &= PARENB;opt.c_cflag &= INPCK;opt.c_cflag |= (CLOCAL | CREAD);opt.c_lflag &= (ICANON | ECHO | ECHOE | ISIG);opt.c_oflag &= OPOST;opt.c_oflag &= (ONLCR | OCRNL); /添加的opt.c_iflag &= (ICRNL | INLCR);opt.c_iflag &= (IXON | IXOFF | IXANY); /添
28、加的opt.c_ccVTIME = 0;opt.c_ccVMIN = 0;tcflush(fd, TCIOFLUSH);printf(configure completen);if(tcsetattr(fd, TCSANOW, &opt) != 0)perror(serial error);return -1;printf(start send and receive datan);while(1)n = 0;len = 0;bzero(read_buf, sizeof(read_buf); /類似于 memsetbzero(write_buf, sizeof(write_buf);while
29、( (n = read(fd, read_buf, sizeof(read_buf) 0 )for(i = len; i (len + n); i+)write_bufi = read_bufi - len;len += n;write_buflen = 0;printf(Len %d n, len);printf(%s n, write_buf);n = write(fd, write_buf, len);printf(write %d charsn,n);sleep(2);9.附錄 c_cflag 用于設置控制參數(shù),除了波特率外還包含以下內(nèi)容:EXTA External rate cloc
30、kEXTB External rate clockCSIZE Bit mask for data bitsCS5 5 個數(shù)據(jù)位CS6 6 個數(shù)據(jù)位CS7 7 個數(shù)據(jù)位CS8 8 個數(shù)據(jù)位CSTOPB 2個停止位(清除該標志表示1 個停止位PARENB允許校驗位PARODD使用奇校驗(清除該標志表示使用偶校驗)CREAD Enable receiverHUPCL Hangup (drop DTR) on last closeCLOCAL Local linedo not change“ owner ” of portLOBLK Block job control outpuc_cflag 標志可
31、以定義CLOCAL 和 CREAD ,這將確保該程序不被其他端口控制和信號干擾,同時串口驅(qū)動將讀取進入的數(shù)據(jù)。 CLOCAL 和 CREAD 通??偸潜皇悄艿?。c_lflag 用于設置本地模式,決定串口驅(qū)動如何處理輸入字符,設置內(nèi)容如下:ISIG Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signalsICANON Enable canonical input (else raw)XCASE Map uppercase lowercase (obsolete)ECHO Enable echoing of input charactersECH
32、OE Echo erase character as BS-SP-BSECHOK Echo NL after kill characterECHONL Echo NLNOFLSH Disable flushing of input buffers after interrupt or quit charactersIEXTEN Enable extended functionsECHOCTL Echo control characters as char and delete as ?ECHOPRT Echo erased character as character erasedECHOKE
33、 BS-SP-BS entire line on line killFLUSHO Output being flushedPENDIN Retype pending input at next read or input charTOSTOP Send SIGTTOU for background outputc_iflag 用于設置如何處理串口上接收到的數(shù)據(jù),包含如下內(nèi)容:INPCK Enable parity checkIGNPAR Ignore parity errorsPARMRK Mark parity errorsISTRIP Strip parity bitsIXON Enabl
34、e software flow control (outgoing)IXOFF Enable software flow control (incoming)IXANY Allow any character to start flow againIGNBRK Ignore break conditionBRKINT Send a SIGINT when a break condition is detectedINLCR Map NL to CRIGNCR Ignore CRICRNL Map CR to NLIUCLC Map uppercase to lowercaseIMAXBEL E
35、cho BEL on input line too longc_oflag用于設置如何處理輸出數(shù)據(jù),包含如下內(nèi)容:OPOST Postprocess output (not set = raw output)OLCUC Map lowercase to uppercaseONLCR Map NL to CR-NLOCRNL Map CR to NLNOCR No CR output at column 0ONLRET NL performs CR functionOFILL Use fill characters for delayOFDEL Fill character is DELNLDL
36、Y Mask for delay time needed between linesNL0 No delay for NLsNL1 Delay further output after newline for 100 millisecondsCRDLY Mask for delay time needed to return carriage to left columnCR0 No delay for CRsCR1 Delay after CRs depending on current column positionCR2 Delay 100 milliseconds after send
37、ing CRsCR3 Delay 150 milliseconds after sending CRsTABDLY Mask for delay time needed after TABsTAB0 No delay for TABsTAB1 Delay after TABs depending on current column positionTAB2 Delay 100 milliseconds after sending TABsTAB3 Expand TAB characters to spacesBSDLY Mask for delay time needed after BSsB
38、S0 No delay for BSsBS1 Delay 50 milliseconds after sending BSsVTDLY Mask for delay time needed after VTsVT0 No delay for VTsVT1 Delay 2 seconds after sending VTsFFDLY Mask for delay time needed after FFsFF0 No delay for FFsFF1 Delay 2 seconds after sending FFsc_cc定義了控制字符,包含以下內(nèi)容:VINTR Interrupt CTRL-CVQUIT Quit CTRL-ZVERASE Erase Backspace (BS)VKILL Kill-line CTRL-UVEOF End-of-file CTRL-DVEOL End-of-line Carriage return (CR)VEOL2 Second end-of-line Line feed (LF)VMIN Minimum number of characters to readVSTART Start flow CTRL-Q (XON)VS
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 個性化租房協(xié)議范本:2024年版版A版
- 2025年度綠色環(huán)保型不銹鋼宣傳欄廣告制作與安裝一體化服務合同
- 科技企業(yè)中的定制化服務解決方案
- 家用紡織品材料的技術(shù)創(chuàng)新與市場機遇
- 流程再造小微企業(yè)貸款審批新思路
- 個人自建房屋承包建設合同2024
- 個人對個人簡易借款合同(2024年新版)版B版
- 個人二零二四年度房地產(chǎn)經(jīng)紀服務合同5篇
- 家教中的音樂教育方案創(chuàng)新研究
- 教育與技術(shù)融合下的新型小學環(huán)保教學模式探索
- 2024年萍鄉(xiāng)衛(wèi)生職業(yè)學院單招職業(yè)技能測試題庫標準卷
- 2024年高考數(shù)學(理)試卷(全國甲卷)(空白卷)
- DB32-T 4444-2023 單位消防安全管理規(guī)范
- 臨床三基考試題庫(附答案)
- 合同簽訂執(zhí)行風險管控培訓
- 人員密集場所消防安全管理培訓
- JCT587-2012 玻璃纖維纏繞增強熱固性樹脂耐腐蝕立式貯罐
- 典范英語2b課文電子書
- 員工信息登記表(標準版)
- 春節(jié)工地停工復工計劃安排( 共10篇)
- 新教材人教版高中物理選擇性必修第二冊全冊各章節(jié)課時練習題及章末測驗含答案解析(安培力洛倫茲力電磁感應交變電流等)
評論
0/150
提交評論