Linux串口通信編程(Linux Serial Programming HOWTO)-基礎(chǔ)電子_第1頁(yè)
Linux串口通信編程(Linux Serial Programming HOWTO)-基礎(chǔ)電子_第2頁(yè)
Linux串口通信編程(Linux Serial Programming HOWTO)-基礎(chǔ)電子_第3頁(yè)
Linux串口通信編程(Linux Serial Programming HOWTO)-基礎(chǔ)電子_第4頁(yè)
Linux串口通信編程(Linux Serial Programming HOWTO)-基礎(chǔ)電子_第5頁(yè)
已閱讀5頁(yè),還剩6頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

精品文檔-下載后可編輯Linux串口通信編程(LinuxSerialProgrammingHOWTO)-基礎(chǔ)電子的偵錯(cuò)你程式碼的方法是建構(gòu)另一臺(tái)Linuxbox,并把兩臺(tái)電腦用null-modem纜線連接.用miniterm以傳送字元到你的Linuxbox.Miniterm很容易編譯而它會(huì)把所有輸入到鍵盤(pán)的字元透過(guò)序列埠傳送.只有這個(gè)宣告定義會(huì)被檢查#defineMODEMDEVICE"/dev/ttyS0".如果是COM1設(shè)定為ttyS0,如果是COM2設(shè)定為ttyS1等等..先前的測(cè)試是必要的,所有的字元都將以raw方式(不經(jīng)任何處理)直接傳送.測(cè)試是否連接正確,在兩臺(tái)電腦上都啟動(dòng)miniterm然後隨便在鍵盤(pán)上亂按.在其中一臺(tái)上輸入的字元應(yīng)該會(huì)顯示在另一臺(tái)電腦上反之亦同.但輸入的字元不會(huì)回應(yīng)到與之相連的螢?zāi)簧?

要自制null-modem的電纜,你必需要把TxD(傳送)及RxD(接收)兩線對(duì)調(diào).

當(dāng)然也可以只用一臺(tái)電腦來(lái)作相同的測(cè)試,只要電腦上有兩個(gè)未使用的序列埠.當(dāng)然你也就要執(zhí)行兩個(gè)miniterm來(lái)當(dāng)虛擬控制臺(tái).如果你是藉由拔去滑鼠來(lái)取得另一個(gè)序列埠,記得要把/dev/mouse裝置重新導(dǎo)向,如果它存在的話.如果你使用多埠的序列埠控制卡,請(qǐng)確定它已設(shè)定正確.當(dāng)我在我的電腦上測(cè)試時(shí)也曾經(jīng)因?yàn)樵O(shè)定錯(cuò)誤而出過(guò)槌.當(dāng)我連到另一臺(tái)電腦,通訊埠開(kāi)始傳送字元.就因?yàn)閯偤眠@不是完整的非同步式傳輸,所以可在同一臺(tái)電腦上執(zhí)行兩個(gè)程式.連接埠設(shè)定/dev/ttyS*裝置會(huì)被當(dāng)成連接到你的Linuxbox的終端機(jī),并且在啟動(dòng)後就設(shè)定好了.這個(gè)觀念在你寫(xiě)raw裝置的通訊程式時(shí)必需記住.也就是說(shuō)這個(gè)連接埠被設(shè)定為回應(yīng)所有自這個(gè)裝置送出的字元,而用在資料傳輸時(shí)通常這種要改變這種工作模式.

所有的參數(shù)可以由一個(gè)小程式簡(jiǎn)單的完成.設(shè)定參數(shù)被放在一個(gè)結(jié)構(gòu)體內(nèi)structtermios,他的定義檔在:

#defineNCCS19structtermios{tcflag_tc_iflag;/*輸入模式旗標(biāo)*/tcflag_tc_oflag;/*輸出模式旗標(biāo)*/tcflag_tc_cflag;/*控制模式旗標(biāo)*/tcflag_tc_lflag;/*區(qū)域模式旗標(biāo)*/cc_tc_line;/*行控制(linediscipline)*/cc_tc_cc[NCCS];/*控制特性*/};

這個(gè)檔案也包含所有的旗標(biāo)定義.輸入模式旗標(biāo)在c_iflag掌管所有的輸入處理,這就意謂著由裝置上傳來(lái)的字元在還沒(méi)用read功能讀取前可以先處理過(guò).同理c_oflag掌管所有的輸出處理.c_cflag包含連接埠的設(shè)定,如鮑率,每字元多少位元,停止位元,等等..區(qū)域模式旗標(biāo)放在c_lflag用來(lái)偵測(cè)字元是否回應(yīng),而訊號(hào)會(huì)送到你的程式,等等..後c_cc陣列定義了檔案終了的控制字元,停止,等等..預(yù)設(shè)的控制字元值放在.有關(guān)旗標(biāo)的細(xì)節(jié)擺在使用手冊(cè)termios(3).termios結(jié)構(gòu)體內(nèi)的c_line行控制(linediscipline)元素,不能在POSIX相容的系統(tǒng)下使用譯者注:這里所說(shuō)的linediscipline雖然我翻成行控制但還是很難說(shuō)出那是舍.如果想知道請(qǐng)看看kernel:(.

序列裝置的輸入觀念有三個(gè)輸入的觀念要說(shuō)明.按照所要寫(xiě)的應(yīng)用程式選用適合的觀念.盡量避免使用回圈來(lái)讀取單一的字元再組成字串.我曾這樣做過(guò),會(huì)掉字元,且對(duì)read而言不會(huì)顯示任何錯(cuò)誤.

標(biāo)準(zhǔn)輸入程序這是終端機(jī)的標(biāo)準(zhǔn)處理程序,但用來(lái)與其他dl型式的以行為單位的輸入通訊也很有用,也就是read會(huì)傳回一整行完整的輸入資料.行預(yù)設(shè)的終止字元是NL(ASCIILF),檔案結(jié)束符,或行終止字元.預(yù)設(shè)環(huán)境下,CR(是DOS/Windows預(yù)設(shè)的行終止符)不會(huì)終止一行的敘述.

標(biāo)準(zhǔn)的輸入處理程序還可以處理清除,刪除字,重印字元,及轉(zhuǎn)換CR為NL等等功能..

非標(biāo)準(zhǔn)輸入程序非標(biāo)準(zhǔn)輸入程序可以用在需要每次讀取固定數(shù)量字元的情況,并允許使用字元輸入時(shí)間的計(jì)時(shí)器.這種模式可以用在讀取固定字元數(shù)量的應(yīng)用程式,或者所連接的裝置會(huì)突然送出大量字元的狀況.

非同步式輸入以上所敘述的兩種模式都可以用在非同步與同步的傳輸模式.預(yù)設(shè)是在同步的模式下工作,也就是在尚未讀取完之前,read的狀態(tài)會(huì)被阻斷.而非同步模式下read的狀態(tài)會(huì)直接返回并送出訊號(hào)到所叫用的程式直到完成工作.這個(gè)訊號(hào)可以由訊號(hào)的處理程式handler...來(lái)接收.

等待來(lái)自多個(gè)訊號(hào)的輸入這并不是一個(gè)不一樣的輸入模式.如果你要透過(guò)序列埠連接并處理多個(gè)裝置的話,它是滿有用的.在我的應(yīng)用程式中我必需在幾乎同一時(shí)間內(nèi),透過(guò)TCP/IPsocket及序列埠處理來(lái)自其他電腦的輸入訊號(hào).下面這個(gè)□例程式將等待來(lái)自兩個(gè)不同輸入源的訊號(hào).如果其中一個(gè)信號(hào)源出現(xiàn),他就會(huì)被處理,而程式會(huì)繼續(xù)等待新的輸入訊號(hào).

以下這個(gè)方法看起來(lái)相當(dāng)覆雜,但請(qǐng)記住Linux是一個(gè)多工的作業(yè)系統(tǒng).select這個(gè)系統(tǒng)呼叫并不會(huì)在等待輸入訊號(hào)時(shí)把CPU負(fù)載加重,而如果你用回圈方式來(lái)等待輸入訊號(hào)將使得其它同時(shí)執(zhí)行的行程被拖慢.

程序范例所有的范例自miniterm.c.Thetypeahead暫存器被限制在255個(gè)字元,就跟標(biāo)準(zhǔn)輸入程序的字串長(zhǎng)度相同(或).參考程式碼中的注解它會(huì)解釋不同輸入模式的使用.我希望這些程式碼都能被了解.標(biāo)準(zhǔn)輸入程序的程式范例的注解寫(xiě)得,其它的范例都只在不同於其它范例的地方做注解.敘述不是很完整,但可以激勵(lì)你對(duì)這范例做實(shí)驗(yàn),以延生出合於你所需應(yīng)用程式的解.別忘記要把序列埠的權(quán)限設(shè)定正確(也就是:chmoda+rw/dev/ttyS1)!標(biāo)準(zhǔn)輸入程序#include#include#include#include#include/*鮑率設(shè)定被定義在,這在被引入*/#defineBAUDRATEB38400/*定義正確的序列埠*/#defineMODEMDEVICE"/dev/ttyS1"#define_POSIX_SOURCE1/*POSIX系統(tǒng)相容*/#defineFALSE0#defineTRUE1volatileintSTOP=FALSE;main(){intfd,c,res;structtermiosoldtio,newtio;charbuf[255];/*開(kāi)啟數(shù)據(jù)機(jī)裝置以讀取并寫(xiě)入而不以控制tty的模式因?yàn)槲覀儾幌氤淌皆谒统鯟TRL-C後就被殺掉.*/fd=open(MODEMDEVICE,O_RDWR|O_NOCTTY);if(fd0){perror(MODEMDEVICE);exit(-1);}tcgetattr(fd,oldtio);/*儲(chǔ)存目前的序列埠設(shè)定*/bzero(newtio,sizeof(newtio));/*清除結(jié)構(gòu)體以放入新的序列埠設(shè)定值*//*BAUDRATE:設(shè)定bps的速度.你也可以用cfsetispeed及cfsetospeed來(lái)設(shè)定.CRTSCTS:輸出資料的硬體流量控制(只能在具完整線路的纜線下工作參考Serial-HOWTO第七節(jié))CS8:8n1(8位元,不做同位元檢查,1個(gè)終止位元)CLOCAL:本地連線,不具數(shù)據(jù)機(jī)控制功能CREAD:致能接收字元*/newtio.c_cflag=BAUDRATE|CRTSCTS|CS8|CLOCAL|CREAD;/*IGNPAR:忽略經(jīng)同位元檢查後,錯(cuò)誤的位元組ICRNL:比CR對(duì)應(yīng)成NL(否則當(dāng)輸入訊號(hào)有CR時(shí)不會(huì)終止輸入)在不然把裝置設(shè)定成raw模式(沒(méi)有其它的輸入處理)*/newtio.c_iflag=IGNPAR|ICRNL;/*Raw模式輸出.*/newtio.c_oflag=0;/*ICANON:致能標(biāo)準(zhǔn)輸入,使所有回應(yīng)機(jī)能停用,并不送出信號(hào)以叫用程式*/newtio.c_lflag=ICANON;/*初始化所有的控制特性預(yù)設(shè)值可以在/usr/include/termios.h找到,在注解中也有,但我們?cè)谶@不需要看它們*/newtio.c_cc[VINTR]=0;/*Ctrl-c*/newtio.c_cc[VQUIT]=0;/*Ctrl-\*/newtio.c_cc[VERASE]=0;/*del*/newtio.c_cc[VKILL]=0;/*@*/newtio.c_cc[VEOF]=4;/*Ctrl-d*/newtio.c_cc[VTIME]=0;/*不使用分割字元組的計(jì)時(shí)器*/newtio.c_cc[VMIN]=1;/*在讀取到1個(gè)字元前先停止*/newtio.c_cc[VSWTC]=0;/*'\0'*/newtio.c_cc[VSTART]=0;/*Ctrl-q*/newtio.c_cc[VSTOP]=0;/*Ctrl-s*/newtio.c_cc[VSUSP]=0;/*Ctrl-z*/newtio.c_cc[VEOL]=0;/*'\0'*/newtio.c_cc[VREPRINT]=0;/*Ctrl-r*/newtio.c_cc[VDISCARD]=0;/*Ctrl-u*/newtio.c_cc[VWERASE]=0;/*Ctrl-w*/newtio.c_cc[VLNEXT]=0;/*Ctrl-v*/newtio.c_cc[VEOL2]=0;/*'\0'*//*現(xiàn)在清除數(shù)據(jù)機(jī)線并啟動(dòng)序列埠的設(shè)定*/tcflush(fd,TCIFLUSH);tcsetattr(fd,TCSANOW,newtio);/*終端機(jī)設(shè)定完成,現(xiàn)在處理輸入訊號(hào)在這個(gè)□例,在一行的開(kāi)始處輸入'z'會(huì)退出此程式.*/while(STOP==FALSE){/*回圈會(huì)在我們發(fā)出終止的訊號(hào)後跳出*//*即使輸入超過(guò)255個(gè)字元,讀取的程式段還是會(huì)一直等到行終結(jié)符出現(xiàn)才停止.如果讀到的字元組低於正確存在的字元組,則所剩的字元會(huì)在下讀取時(shí)取得.res用來(lái)存放真正讀到的字元組個(gè)數(shù)*/res=read(fd,buf,255);buf[res]=0;/*設(shè)定字串終止字元,所以我們能用printf*/printf(":%s:%d\n",buf,res);if(buf[0]=='z')STOP=TRUE;}/*回存舊的序列埠設(shè)定值*/tcsetattr(fd,TCSANOW,oldtio);}3.2非標(biāo)準(zhǔn)輸入程序在非標(biāo)準(zhǔn)的輸入程序模式下,輸入的資料不會(huì)被組合成一行而輸入後的處理功能(清除,殺掉,刪除,等等.)都不能使用.這個(gè)模式有兩個(gè)功能控制參數(shù):c_cc[VTIME]設(shè)定字元輸入時(shí)間計(jì)時(shí)器,及c_cc[VMIN]設(shè)定滿足讀取功能的字元接收個(gè)數(shù).如果MIN0且TIME=0,MIN設(shè)定為滿足讀取功能的字元接收個(gè)數(shù).由於TIME是零,所以計(jì)時(shí)器將不被使用.如果MIN=0且TIME0,TIME將被當(dāng)做逾時(shí)設(shè)定值.滿足讀取功能的情況為讀取到單一字元,或者超過(guò)TIME所定義的時(shí)間(t=TIME*0.1s).如果超過(guò)TIME所定義的時(shí)間,則不會(huì)傳回任何字元.如果MIN0且TIME0,TIME將被當(dāng)做一個(gè)分割字元組的計(jì)時(shí)器.滿足讀取功能的條件為接收到MIN個(gè)數(shù)的字元,或兩個(gè)字元的間隔時(shí)間超過(guò)TIME所定義的值.計(jì)時(shí)器會(huì)在每讀到一個(gè)字元後重新計(jì)時(shí),且只會(huì)在個(gè)字元收到後才會(huì)啟動(dòng).如果MIN=0且TIME=0,讀取功能就馬上被滿足.目前所存在的字元組個(gè)數(shù),或者將回傳的字元組個(gè)數(shù).根據(jù)Antonino(參考貢獻(xiàn))所說(shuō),你可以用fcntl(fd,F_SETFL,FNDELAY);在讀取前得到相同的結(jié)果.藉由修改newtio.c_cc[VTIME]及newtio.c_cc[VMIN]上述的模式就可以測(cè)試了.#include#include#include#include#include#defineBAUDRATEB38400#defineMODEMDEVICE"/dev/ttyS1"#define_POSIX_SOURCE1/*POSIX系統(tǒng)相容*/#defineFALSE0#defineTRUE1volatileintSTOP=FALSE;main(){intfd,c,res;structtermiosoldtio,newtio;charbuf[255];fd=open(MODEMDEVICE,O_RDWR|O_NOCTTY);if(fd0){perror(MODEMDEVICE);exit(-1);}tcgetattr(fd,oldtio);/*儲(chǔ)存目前的序列埠設(shè)定*/bzero(newtio,sizeof(newtio));newtio.c_cflag=BAUDRATE|CRTSCTS|CS8|CLOCAL|CREAD;newtio.c_iflag=IGNPAR;newtio.c_oflag=0;/*設(shè)定輸入模式(非標(biāo)準(zhǔn)型,不回應(yīng),...)*/newtio.c_lflag=0;newtio.c_cc[VTIME]=0;/*不使用分割字元組計(jì)時(shí)器*/newtio.c_cc[VMIN]=5;/*在讀取到5個(gè)字元前先停止*/tcflush(fd,TCIFLUSH);tcsetattr(fd,TCSANOW,newtio);while(STOP==FALSE){/*輸入回圈*/res=read(fd,buf,255);/*在輸入5個(gè)字元後即返回*/buf[res]=0;/*所以我們能用printf...*/printf(":%s:%d\n",buf,res);if(buf[0]=='z')STOP=TRUE;}tcsetattr(fd,TCSANOW,oldtio);}3.3非同步式輸入#include#include#include#include#include#include#defineBAUDRATEB38400#defineMODEMDEVICE"/dev/ttyS1"#define_POSIX_SOURCE1/*POSIX系統(tǒng)相容*/#defineFALSE0#defineTRUE1volatileintSTOP=FALSE;voidsignal_handler_IO(intstatus);/*定義訊號(hào)處理程序*/intwait_flag=TRUE;/*沒(méi)收到訊號(hào)的話就會(huì)是TRUE*/main(){intfd,c,res;structtermiosoldtio,newtio;structsigactionsaio;/*definitionofsignalaction*/charbuf[255];/*開(kāi)啟裝置為non-blocking(讀取功能會(huì)馬上結(jié)束返回)*/fd=open(MODEMDEVICE,O_RDWR|O_NOCTTY|O_NONBLOCK);if(fd0){perror(MODEMDEVICE);exit(-1);}/*在使裝置非同步化前,安裝訊號(hào)處理程序*/saio.sa_handler=signal_handler_IO;saio.sa_mask=0;saio.sa_flags=0;saio.sa_restorer=NULL;sigaction(SIGIO,saio,NULL);/*允許行程去接收SIGIO訊號(hào)*/fcntl(fd,F_SETOWN,getpid());/*使檔案akethefiledescriptor非同步(使用手冊(cè)上說(shuō)只有O_APPEND及O_NONBLOCK,而F_SETFL也可以用...)*/fcntl(fd,F_SETFL,FASYNC);tcgetattr(fd,oldtio);/*儲(chǔ)存目前的序列埠設(shè)定值*//*設(shè)定新的序列埠為標(biāo)準(zhǔn)輸入程序*/newtio.c_cflag=BAUDRATE|CRTSCTS|CS8|CLOCAL|CREAD;newtio.c_iflag=IGNPAR|ICRNL;newtio.c_oflag=0;newtio.c_lflag=ICANON;newtio.c_cc[VMIN]=1;newtio.c_cc[VTIME]=0;tcflush(fd,TCIFLUSH);tcsetattr(fd,TCSANOW,newtio);/*等待輸入訊號(hào)的回圈.很多有用的事我們將在這做*/while(STOP==FALSE){printf(".\n");usleep(100000);/*在收到SIGIO後,wait_flag=FALSE,輸入訊號(hào)存在則可以被讀取*/if(wait_flag==FALSE){res=read(fd,buf,255);buf[res]=0;printf(":%s:%d\n",buf,res);if(res==1)STOP=TRUE;/*如果只輸入CR則停止回圈*/wait_flag=TRUE;/*等待新的輸入訊號(hào)*/}}/*回存舊的序列埠設(shè)定值*/tcsetattr(fd,TCSANOW,oldtio);}/****************************************************************************訊號(hào)處理程序.設(shè)定wait_flag為FALSE,以使上述的回圈能接收字元****************************************************************************/voidsignal_handler_IO(intstatus){printf("receivedSIGIOsignal.\n");wait_flag=FALSE;}3.4等待來(lái)自多個(gè)訊號(hào)的輸入這一段很短.它只能被拿來(lái)當(dāng)成寫(xiě)程式時(shí)的提示,故□例程式也很簡(jiǎn)短.但這個(gè)□例不只能用在序列埠上,還可以用在被當(dāng)成檔案來(lái)使用的裝置上.select呼叫及伴隨它所引發(fā)的巨集共用fd_set.fd_set則是一個(gè)位元陣列,而其中每一個(gè)位元代表一個(gè)有效的檔案敘述結(jié)構(gòu).select呼叫接受一個(gè)有效的檔案敘述結(jié)構(gòu)并傳回fd_set位元陣列,而該位元陣列中若有某一個(gè)位元為1,就表示相對(duì)映的檔案敘述結(jié)構(gòu)的檔案發(fā)生了輸入,輸出或有例外事件.而這些巨集提供了所有處理fd_set的功能.亦可參考手冊(cè)select(2).#include#include#includemain(){intfd1,fd2;/*輸入源1及2*/fd_setr

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論