欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報邀請碼778899分享:網(wǎng)絡協(xié)議 串口通訊理解

柚子快報邀請碼778899分享:網(wǎng)絡協(xié)議 串口通訊理解

http://yzkb.51969.com/

機器的通信方式有兩種,分別是并行通信與串行通信

并行通信:并行通信是指多比特數(shù)據(jù)同時通過并行線進行傳送,這樣數(shù)據(jù)傳送速度大大提高,但并行傳送的線路長度受到限制,因為長度增加,干擾就會增加,數(shù)據(jù)也就容易出錯。

串行通信:串行通信是指使用一條數(shù)據(jù)線,將數(shù)據(jù)一位一位地依次傳輸,每一位數(shù)據(jù)占據(jù)一個固定的時間長度。其只需要少數(shù)幾條線就可以在系統(tǒng)間交換信息,特別適用于計算機與計算機、計算機與外設之間的遠距離通信。

異步串行通信:異步串行通信是指通信雙方以一個字符(包括特定附加位)作為數(shù)據(jù)傳輸單位且發(fā)送方傳送字符的間隔時間不一定,具有不規(guī)則數(shù)據(jù)段傳送特性的串行數(shù)據(jù)傳輸。

同步串行通信:同步串行通信是指在約定的通信速率下(即相同波特率),發(fā)送端和接收端的時鐘信號頻率和相位始終保持一致(同步),這就保證了通信雙方在發(fā)送和接收數(shù)據(jù)時具有完全一致的定時關系。

比特率(Bitrate) 來表示,即每秒鐘傳輸?shù)亩M制位數(shù),單位為比特每秒(bit/s)。

“波特率”(Baudrate),它表示每秒鐘傳輸了多少個碼元。而碼元是通訊信號調制的概念,通訊中常用時間間隔相同的符號來表示一個二進制數(shù)字,這樣的信號稱為碼元。

波特率與比特率的關系為:比特率=波特率X單個調制狀態(tài)對應的二進制位數(shù)。

因為很多常見的通訊中一個碼元都是表示兩種狀態(tài),人們常常直接以波特率來表示比特率

串口通訊的數(shù)據(jù)包由發(fā)送設備通過自身的TXD 接口傳輸?shù)浇邮赵O備的RXD 接口。在串口通訊協(xié)議中,規(guī)定了數(shù)據(jù)包的內容,它由起始位、主體數(shù)據(jù)、校驗位以及停止位組成,通訊雙方的數(shù)據(jù)包格式要約定一致才能正常收發(fā)數(shù)據(jù)。

起始位占1位,為邏輯0。數(shù)據(jù)位占5 ~ 8位,可配置。校驗位占1位,可配置為奇校驗、偶校驗、無校驗,停止位的值為邏輯1。

串口通信即可以實現(xiàn)半雙工,也可以實現(xiàn)全雙工

單工:數(shù)據(jù)傳輸只支持數(shù)據(jù)在一個方向上傳輸

半雙工:允許數(shù)據(jù)在兩個方向上傳輸。但是,在某一時刻,只允許數(shù)據(jù)在一個方向上傳輸

全雙工:允許數(shù)據(jù)同時在兩個方向上傳輸

TTL 標準

理想狀態(tài)下,使用5V 表示二進制邏輯“1”,使用0V 表示邏輯“0”.

UART

UART(Universal Asynchronous Receiver Transmitter:通用異步收發(fā)器),是電腦硬件的一部分,它把將要傳輸?shù)馁Y料在串行通信與并行通信之間加以轉換,UART通常被集成于其他通訊接口的連接上。UART即我們通常說的“串口”。該總線有兩條數(shù)據(jù)線,可以實現(xiàn)全雙工的發(fā)送和接收,在嵌入式系統(tǒng)中常用于主機與輔助設備之間的通信。

UART進行串口通信使用TTL電平。5V工作電壓的MCU,使用0 ~ 0.5V表示邏輯0,2.5V ~ 5V表示邏輯1;3.3V工作電壓的MCU,使用0 ~ 0.5V表示邏輯0,2.5V ~ 3.3V表示邏輯1。5V的MUC不能與3.3V的MCU直接連接。

空閑位:不進行傳輸數(shù)據(jù)時,默認為邏輯1,為高電平;

起始位:先發(fā)出一個邏輯“0”,表示消息幀的開始;

數(shù)據(jù)位:緊接著起始位之后,可由5~8位組成,通常傳輸8位即一個字節(jié)。先發(fā)送數(shù)據(jù)的低位,后發(fā)送數(shù)據(jù)的高位;

奇偶校驗位:緊接著數(shù)據(jù)位后面(可有可無),使得“1”的位數(shù)應為偶數(shù)(偶校驗)或奇數(shù)(奇校驗),校驗數(shù)據(jù)傳輸是否正確;

停止位:它是消息傳輸結束的標志,它可以是1位、1.5位、2位的高電平, 由于數(shù)據(jù)是在傳輸線上定時的,并且每一個設備有其自己的時鐘,很可能在通信中兩臺設備間出現(xiàn)了小小的不同步。因此停止位不僅僅是表示傳輸?shù)慕Y束,并且提供計算機校正時鐘同步的機會。

波特率:是衡量數(shù)據(jù)傳輸速率的指標,表示每秒鐘傳輸?shù)奈粩?shù)。例如設置串口的波特率為9600,則表示是1s傳輸9600個bit的數(shù)據(jù),則傳送每個位的時間為 1s / 9600 ≈ 104us,從而區(qū)分消息幀中每個位傳輸?shù)臄?shù)據(jù);

缺點:UART一般直接使用TTL信號來表示0和1,但TTL信號抗干擾能力較差,數(shù)據(jù)在傳輸過程中很容易出錯;且TTL信號的通信距離也很短;

RS232

在目前的其它工業(yè)控制使用的串口通信中,一般只使用RXD、TXD 以及GND 三條信號線,直接傳輸數(shù)據(jù)信號,而RTS、CTS、DSR、DTR 及DCD 信號都被裁剪掉了,這主要是考慮到近程通信與遠程通信問題。

特性:

工作方式:單端(非平衡)

節(jié)點數(shù):點對點通訊(1收1發(fā))

最大傳輸距離:50ft ( 50 * 0.3048 = 15.24m)

最大傳輸速率:20kbit/s

連接方式:點對點(全雙工)

電氣特性:-3V ~ -15V表示邏輯1,3V ~ 15V表示邏輯0

常用芯片有max232、SP232等

缺點:通信距離短,速率低,而且只能點對點通信,無法組建多機通信系統(tǒng),且容易受外界電氣干擾導致信息傳輸錯誤。

RS-485

標準運行連接多個收發(fā)器,即具有多站能力,增加了多點、雙向的通信能力

RS-485采用平衡發(fā)送和差分接收,因此具有抑制共模干擾的能力。

RS485有兩線制和四線制兩種接線,四線制只能實現(xiàn)點對點的通信方式,現(xiàn)很少采用,多采用的是兩線制接線方式,這種接線方式為總線拓撲結構,在同一總線上最多可以掛接32個節(jié)點。

采用兩線半雙工傳輸,最大速率10Mb/s,電平邏輯是兩線的電平差來決定的,提高抗干擾能力,傳輸距離長(幾十米到上千米)。

特性:

工作方式:差分(平衡);

節(jié)點數(shù):點對多通訊(1發(fā)32收);

最大傳輸距離:4000ft ( 4000 * 0.3048 = 1219.2m);

最大傳輸速率:10Mbit/s;

連接方式:多點對多點(兩線制,半雙工);

電氣特性:2V ~ 6V表示邏輯1,-2V ~ -6V表示邏輯0;

具體編程

在32位的Windows系統(tǒng)中,串口和其它通信設備是作為文件處理的。串口的打開、關閉、讀取和寫入所用的函數(shù)與操作文件的函數(shù)完全一致。

打開串口

CreateFile()為讀訪問、寫訪問或讀寫訪問“打開”串口。返回一個句柄、

HANDLE CreateFile

(

LPCTSTR lpszName,

DWORD fdwAccess,

DWORD fdwShareMode,

LPSECURITY_ATTRIBUTES lpsa,

DWORD fdwCreate,

DWORD fdwAttrsAndFlags,

HANDLE hTemplateFile

)

lpszName:指定要打開的串口邏輯名,用字符串表示,如“COM1”和“COM2”分別表示串口1和串口2。

·fdwAccess:用來指定串口訪問的類型。與文件一樣,串口也是可以被打開以供讀取、寫入或者兩者兼有。因為大部分串口通信都是雙向的,因此常常在設置中將兩個標識符連接起來使用。如:

fdwAccess = GENERIC_READ | GENERIC_WRITE;

·fdwShareMode:指定該端口的共享屬性。對于不能共享的串口,它必須設置為0。如果在當前的應用程序調用CreateFile()時,另一個應用程序已經(jīng)打開了串口,該函數(shù)就會返回錯誤代碼,原因是兩個應用程序不能共享一個端口。

·Ipsa:引用安全性屬性結構(SECURITY_ARRTIBUTES)。將該參數(shù)設置為NULL將為該端口分配缺省的安全性屬性。

·fdwCreate:指定如果CreateFile()正在被已有的文件調用時應采取的動作。因為串口總是存在,fdwCreate必須設置成OPEN_EXISTING。該標志告訴Windows不用企圖創(chuàng)建新端口,而是打開已經(jīng)存在的端口

fdwAttrsAndFlags:描述了端口的各種屬性。對于文件來說,有可能具有很多屬性,但對于串口,異步設置為FILE_FLAG_OVERLAPPED。同步設置為0.

·hTemplateFile:指向模板文件的句柄,當端口處于打開狀態(tài)時,不使用該參數(shù),因而必須置成0。

//同步方式

hCom = CreateFileA(portname, //串口名

GENERIC_READ | GENERIC_WRITE, //支持讀寫

0, //獨占方式,串口不支持共享

NULL,//安全屬性指針,默認值為NULL

OPEN_EXISTING, //打開現(xiàn)有的串口文件

0, //0:同步方式,F(xiàn)ILE_FLAG_OVERLAPPED:異步方式

NULL);//用于復制文件句柄,默認值為NULL,對串口而言該參數(shù)必須置為NULL

關閉串口

只需要調用CloseHandle()函數(shù)關閉由CreateHandle()函數(shù)返回得句柄即可。

設置緩沖區(qū)

通過調用SetupComm()實現(xiàn)其它初始化工作。也可以不調用SetupComm()函數(shù),Windows系統(tǒng)也會分配缺省的發(fā)送和接收緩沖區(qū)。

BOOL SetupComm

(

HANDLE hFile, // 通信設備句柄

DWORD dwInQueue, // 輸入緩沖區(qū)大小

DWORD dwOutQueue // 輸出緩沖區(qū)大小

);

BOOL PurgeComm

(

HANDLE hFile, // 返回的句柄

DWORD dwFlags // 執(zhí)行的動作

);

參數(shù)hFile指向由CreateFile函數(shù)返回的句柄,dwFlags表示執(zhí)行的動作,這個參數(shù)可以是表表5中的任一個。參數(shù)hFile指向由CreateFile函數(shù)返回的句柄,可以調用GetLastError()函數(shù)獲得進一步的錯誤信息。

值 描述 PURGE_TXABORT即使發(fā)送操作沒有完成,也終止所有的重疊發(fā)送操作,立即返回 PURGE_RXABORT即使接收操作沒有完成,也終止所有的重疊接收操作,立即返回 PURGE_TXCLEAR清除發(fā)送緩沖區(qū) PURGE_RXCLEAR清除接收緩沖區(qū)

BOOL FlushFileBuffers

(

HANDLE hFile // 函數(shù)打開的句柄

);

如果要保證緩沖區(qū)的所有字符都被發(fā)送,應該調用FlushFileBuffer()函數(shù)。該函數(shù)只受流量控制的支配,不受超時控制的支配,它在所有的寫操作完成后才返回。

獲取配置

使用GetCommState()函數(shù)獲取串口的當前配置。

BOOL GetCommState

(

HANDLE hFile, // 通信設備句柄

LPDCB lpDCB // 指向device-control block structure的指針

);

如果GetCommState()函數(shù)調用成功,則返回值不為零。若函數(shù)調用失敗,則返回值為零,如果想得到進一步的錯誤信息,可以調用GetLastError()函數(shù)來獲取。

使用GetCommState()函數(shù)獲取串口的當前配置

設置配置

調用SetCommState()函數(shù)配置修改過的DCB來配置端口。

BOOL SetCommState

(

HANDLE hFile, // 已打開的串口的句柄

LPDCB lpDCB // 指向DCB結構的指針

);

DCB結構的主要參數(shù)說明如下:

·DCBLength: 一字節(jié)為單位指定的DCB結構的大小。

·Baudrate: 用于指定串口設備通信的數(shù)據(jù)傳輸速率,它可以是實際的數(shù)據(jù)傳輸速率數(shù)值,也可以是下列數(shù)據(jù)之一:CBR_110, CBR_19200, CBR_300, CBR_38400, CBR_600, CBR_56000, CBR_1200, CBR_57600, CBR_2400, CBR_115200, CBR_4800, CBR_12800, CBR_9600, CBR_25600, CBR_14400。

·fBinary: 指定是否允許二進制。Win32API不支持非二進制傳輸,因此這個參數(shù)必須設置為TRUE,如果設置為FALSE則不能正常工作。

·fParity: 指定是否允許奇偶校驗,如果這個參數(shù)設置為TRUE,則執(zhí)行奇偶校驗并報告錯誤信息。

·fOutxCtsFlow: 指定CTS是否用于檢測發(fā)送流控制。當該成員為TRUE,而CTS為OFF時,發(fā)送將被掛起,直到CTS置ON。

·fOutxDsrFlow: 指定DSR是否用于檢測發(fā)送流控制,當該成員為TRUE,而DSR為OFF時,發(fā)送將被掛起,直到DSR置ON。

·fDtrControl: 指定DTR流量控制,可以是表1中的任一值。

值 功能描述 DTR_CONTROL_DISABLE禁止DTR線,并保持禁止狀態(tài) DTR_CONTROL_ENABLE允許DTR線,并保持允許狀態(tài) DTR_CONTROL_HANDSHAKE允許DTR握手,如果允許握手,則不允許應用程序使用EscapeCommFunction函數(shù)調整線路

·fDsrSensitivity: 指定通信驅動程序對DTR信號線是否敏感,如果該位置設為TRUE時,DSR信號為OFF,接收的任何字節(jié)將被忽略。

·fTXContinueOnXoff: 指定當接收緩沖區(qū)已滿,并且驅動程序已經(jīng)發(fā)送出XoffChar字符時發(fā)送是否停止。當該成員為TRUE時,在接收緩沖區(qū)內接收到了緩沖區(qū)已滿的字節(jié)XoffLim,并且驅動程序已經(jīng)發(fā)送出XoffChar字符終止接收字節(jié)之后,發(fā)送繼續(xù)進行。該成員為FALSE時,接收緩沖區(qū)接收到代表緩沖區(qū)已空的字節(jié)XonLim,并且驅動程序已經(jīng)發(fā)送出恢復發(fā)送的XonChar字符后,發(fā)送可以繼續(xù)進行。

·fOutX: 該成員為TRUE時,接收到XoffChar之后停止發(fā)送,接收到XonChar之后發(fā)送將重新開始。

·fInX: 該成員為TRUE時,接收緩沖區(qū)內接收到代表緩沖區(qū)滿的字節(jié)XoffLim之后,XoffChar發(fā)送出去,接收緩沖區(qū)接收到代表緩沖區(qū)已空的字節(jié)XonLim之后,XonChar發(fā)送出去。

·fErrorChar: 當該成員為TRUE,并且fParity為TRUE時,就會用ErrorChar成員指定的字符來代替奇偶校驗錯誤的接收字符。

·fNull: 指明是否丟棄接收到的NULL( ASCII 0 )字符,該成員為TRUE時,接收時去掉空(零值)字節(jié);反之則不丟棄。

表2 RTS 流量控制

值 功能描述RTS_CONTROL_DISABLE打開設備時禁止RTS線,并保持禁止狀態(tài)RTS_CONTROL_ENABLE打開設備時允許RTS線,并保持允許狀態(tài)DTR_CONTROL_HANDSHAKE允許握手。在接收緩沖區(qū)小于半滿時將RTS 置為ON,在接收緩沖區(qū)超過3/4時將RTS置為OFF。如果允許握手,則不允許應用程序使用EscapeCommFunction函數(shù)調整線路DTR_CONTROL_TOGGLE當發(fā)送的字節(jié)有效,將RTS置為 ON,發(fā)送完緩沖區(qū)的所有字節(jié)后, RTS置為OFF

·fRtsControl: 指定 RTS 流量控制,可以取表2中的值。0值和DTR_CONTROL_HANDSHAKE等價。

·fAbortOnError: 如果發(fā)送錯誤,指定是否可以終止讀、寫操作。如果該位為TRUE,當發(fā)生錯誤時,驅動程序以出錯狀態(tài)終止所有的讀寫操作。只有當應用程序調用ClearCommError()函數(shù)處理后,串口才能接收隨后的通信操作。

·fDummy2: 保留的位,沒有使用。

·wReserved:沒有使用,必須為零。

·XonLim: 指定在XOFF字符發(fā)送之前接收到緩沖區(qū)中可允許的最小字節(jié)數(shù)。

·XoffLim: 指定在XOFF字符發(fā)送之前緩沖區(qū)中可允許的最小可用字節(jié)數(shù)

·ByteSize: 指定端口當前使用的數(shù)據(jù)位數(shù)。

·Parity: 指定端口當前使用的奇偶校驗方法。它的可能值如表3所示。

·StopBits: 指定串口當前使用的停止位數(shù),可能值如表4所示。

表3 奇偶校驗方法

值 功能描述 EVENPARITY 偶校驗 MARKPARITY 標號校驗 NOPARITY 無校驗 ODDPARITY 奇校驗 SPACEPARITY 空格效益

表4 停止位數(shù)描述

值 功能描述 ONESTOPBIT 1位停止位 ONE5STOPBITS 1.5位停止位 TWOSTOPBITS 2位停止位

·XonChar: 指明發(fā)送和接收的XON字符值,它表明允許繼續(xù)傳輸。

·XoffChar: 指明發(fā)送和接收的XOFF字符值,它表示暫停數(shù)據(jù)傳輸。

·ErrorChar: 本字符用來代替接收到的奇偶校驗發(fā)生錯誤的字符。

·EofChar: 用來表示數(shù)據(jù)的結束。

·EvtChar: 事件字符。當接收到此字符的時候,會產(chǎn)生一個事件。

·wReserved1: 保留的位,沒有使用。

// 配置參數(shù)

DCB p;

memset(&p, 0, sizeof(p));

p.DCBlength = sizeof(p);

p.BaudRate = baudrate; // 波特率

p.ByteSize = databit; // 數(shù)據(jù)位

switch (parity) //校驗位

{

case 0:

p.Parity = NOPARITY; //無校驗

break;

case 1:

p.Parity = ODDPARITY; //奇校驗

break;

case 2:

p.Parity = EVENPARITY; //偶校驗

break;

case 3:

p.Parity = MARKPARITY; //標記校驗

break;

}

switch (stopbit) //停止位

{

case 1:

p.StopBits = ONESTOPBIT; //1位停止位

break;

case 2:

p.StopBits = TWOSTOPBITS; //2位停止位

break;

case 3:

p.StopBits = ONE5STOPBITS; //1.5位停止位

break;

}

if (!SetCommState(hCom, &p))

{

// 設置參數(shù)失敗

return false;

}

超時設置

超時結構直接影響讀和寫的操作行為。當事先設定的超時間隔消逝時,ReadFile() 、ReadFileEx()、 WriteFile()和 WriteFileEx()操作仍未結束,那么超時設置將無條件結束讀寫操作,而不管是否已讀出或已寫入指定數(shù)量的字符。

在讀或寫操作期間發(fā)生的超時將不按錯誤處理,即讀或寫操作返回指定成功的值。對于同步讀或寫操作,實際傳輸?shù)淖止?jié)數(shù)由ReadFile()和Write()函數(shù)報告。對于異步操作,則有OVERLAPPED結構來獲取。

如果欲獲得當前超時參數(shù),應用程序可以調用GetCommTimeouts()函數(shù)

BOOL GetCommTimeouts

(

HANDLE hFile,

LPCOMMTIMEOUTS lpCommTimeouts

);

如果要設置或改變原來的超時參數(shù),應用程序可以調用SetCommTimeouts()函數(shù)

BOOL SetCommTimeouts

(

HANDLE hFile,

LPCOMMTIMEOUTS lpCommTimeouts

);

typedef struct_COMMTIMEOUTS

{

DWORD ReadIntervalTimeout;

DWORD ReadTotalTimeoutMultiplier;

DWORD ReadTotalTimeoutConstant;

DWORD WriteTotalTimeoutMultiplier;

DWORD WriteTotalTimeoutConstant;

} COMMTIMEOUTS,*LPCOMMTIMEOUTS;

ReadIntervalTimeout:以ms為單位指定通信線路上兩個字符到達之間的最大時間間隔。在ReadFile()操作期間,從接收到第一個字符時開始計時。如果任意兩個字符到達之間的時間間隔超過這個最大值,則ReadFile()操作完成,并返回緩沖數(shù)據(jù)。如果被置為0,則表示不使用間隔超時。

·ReadTotalTimeoutMultiplier:以ms為單位指定一個系數(shù),該系數(shù)用來計算讀操作的總超時時間。

·ReadTotalTimeoutConstant:以ms為單位指定一個常數(shù),該常數(shù)也用來計算讀操作的總超時時間。

·WriteTotalTimeoutMultiplier:以ms為單位指定一個系數(shù),該系數(shù)用來計算寫操作的總超時時間。

·WriteTotalTimeoutConstant:以ms為單位指定一個常數(shù),該常數(shù)也用來計算寫操作的總超時時間。

Windows使用下面的式子計算總超時時間:

ReadTotalTimeout=( ReadTotalTimeoutMultiplier*bytes_to_read )+ ReadTotalTimeoutConstant;

WriteTotalTimeout=( WriteTotalTimeoutMultiplier*bytes_to_write )+ WriteTotalTimeoutConstant;

//超時處理,單位:毫秒

//總超時=時間系數(shù)×讀或寫的字符數(shù)+時間常量

COMMTIMEOUTS TimeOuts;

TimeOuts.ReadIntervalTimeout = 1000; //讀間隔超時

TimeOuts.ReadTotalTimeoutMultiplier = 500; //讀時間系數(shù)

TimeOuts.ReadTotalTimeoutConstant = 5000; //讀時間常量

TimeOuts.WriteTotalTimeoutMultiplier = 500; // 寫時間系數(shù)

TimeOuts.WriteTotalTimeoutConstant = 2000; //寫時間常量

SetCommTimeouts(hCom, &TimeOuts);

讀串口

程序可以使用Win32API ReadFile()函數(shù)或者ReadFileEx()函數(shù)從串口中讀取數(shù)據(jù)。ReadFile()函數(shù)對同步或異步操作都支持,而ReadFileEx()只支持異步操作。這兩個函數(shù)都受到函數(shù)是否異步操作、超時操作等有關參數(shù)的影響和限定。

BOOL ReadFile

(

HANDLE hFile, // 指向標識的句柄

LPVOID lpBuffer, // 指向一個緩沖區(qū)

DWORD nNumberOfBytesToRead, // 讀取的字節(jié)數(shù)

LPDWORD lpNumberOfBytesRead, // 指向調用該函數(shù)讀出的字節(jié)數(shù)

LPOVERLAPPED lpOverlapped // 一個OVERLAPPED的結構

);

·hFile:指向標識的句柄。對串口來說,就是由CreateFile函數(shù)返回的句柄。該句柄必須擁有GENERIC_READ的權限。

·lpBuffer:指向一個緩沖區(qū),該緩沖區(qū)主要用來存放從串口設備中讀取的數(shù)據(jù)。

·nNumberOfBytesToRead:指定要從串口設備讀取的字節(jié)數(shù)。

·lpNumberOfBytesRead:指向調用該函數(shù)讀出的字節(jié)數(shù)。ReadFile()在讀操作前,首先將其設置為0。Windows NT/2000中當lpOverlapped沒有設置時,lpNumberOfBytesRead必須設置。當lpOverlapped設置時,lpNumberOfBytesRead可以不設置。這是可以調用GetOverlappedResult()函數(shù)獲取實際的讀取數(shù)值。Windows 9x中這個參數(shù)一定要設置。

·lpOverlapped:是一個OVERLAPPED的結構,該結構將在后面介紹。如果hFile以FILE_FLAG_OVERLAPPED方式常見,則需要此結構;否則,不需要此結構。

需要注意的是如果該函數(shù)因為超時而返回,那么返回值是TRUE。參數(shù)lpOverlapped 在操作時應該指向一個OVERLAPPED的結構,如果該參數(shù)為NULL ,那么函數(shù)將進行同步操作,而不管句柄是否是由 FILE_FLAG_OVERLAPPED 標志建立的。當ReadFile返回FALSE時,不一定就是操作失敗,線程應該調用GetLastError函數(shù)分析返回的結果。例如,在重疊操作時如果操作還未完成函數(shù)返回,那么函數(shù)就返回FALSE,而且GetLastError函數(shù)返回ERROR_IO_PENDING。

寫串口操作

可以使用Win32API函數(shù)WriteFile() 或者WriteFileEx()向串口中寫數(shù)據(jù)。WriteFile()函數(shù)對同步或異步操作都支持,而WriteFileEx()只支持異步操作。這兩個函數(shù)都受到函數(shù)是否異步操作、超時操作等有關參數(shù)的影響和限定。

BOOL WriteFile

(

HANDLE hFile, // 指向標識的句柄

LPCVOID lpBuffer, // 指向一個緩沖區(qū)

DWORD nNumberOfBytesToWrite, // 指定要向串口設備寫入的字節(jié)數(shù)

LPDWORD lpNumberOfBytesWritten, // 指向調用該函數(shù)已寫入的字節(jié)數(shù)

LPOVERLAPPED lpOverlapped // 一個OVERLAPPED的結構

);

·hFile:指向標識的句柄。對串口來說,就是由CreateFile函數(shù)返回的句柄。該句柄必須擁有GENERIC_WRITE的權限。

·lpBuffer:指向一個緩沖區(qū),該緩沖區(qū)主要用來存放待寫入串口設備的數(shù)據(jù)。

·nNumberOfBytesToWrite:指定要向串口設備寫入的字節(jié)數(shù)。

·lpNumberOfBytesWritten:指向調用該函數(shù)已寫入的字節(jié)數(shù)。WriteFile()在寫操作前,首先將其設置為0。Windows NT/2000中當lpOverlapped沒有設置時,lpNumberOfBytesWritten必須設置。當lpOverlapped設置時,lpNumberOfBytesWritten可以不設置。這是可以調用GetOverlappedResult()函數(shù)獲取實際的讀取數(shù)值。Windows 9x中這個參數(shù)一定要設置。

·lpOverlapped:是一個OVERLAPPED的結構,該結構將在后面介紹。如果hFile以FILE_FLAG_OVERLAPPED方式常見,則需要此結構;否則,不需要此結構。

如果函數(shù)調用成功,則返回值不為零;若函數(shù)調用失敗,則返回值為零。調用GetLastError()函數(shù)可以獲得進一步的出錯信息。

通信狀態(tài)和通信錯誤

如果在串口通信中發(fā)生錯誤,如發(fā)生中斷,奇偶錯誤等,I/O操作將會終止。如果程序要進一步執(zhí)行I/O操作,必須調用ClearCommError()函數(shù)。ClearCommError()函數(shù)有兩個作用:第一個作用是清除錯誤條件;第二個作用是確定串口通信狀態(tài)。ClearCommError()函數(shù)的聲明如下:

BOOL ClearCommError

(

HANDLE hFile,

LPDWORD lpErrors,

LPCOMSTAT lpStat

);

其中主要參數(shù)介紹如下:

·hFile :標識通信設備,CreateFile()函數(shù)返回該句柄。

·lpErrors:指向用一個指明錯誤類型的掩碼填充的32位變量。該參數(shù)可以是表6中各值的組合。

·lpStat:指向一個COMSTAT結構,該結構接收設備的狀態(tài)信息。如果lpStat參數(shù)不設置,則沒有設備狀態(tài)信息被返回。

表6 通信錯誤列表

值 描述 CE_BREAK硬件檢測到一個中斷條件 CE_FRAME硬件檢測到一個幀出錯 CE_IOE發(fā)生I/O錯誤 CE_MODE模式出錯,或者是句柄無效 CE_OVERRUN超速錯誤 CE_RXOVER接收緩沖區(qū)超限,或者是輸入緩沖區(qū)中沒有空間,或者實在文件結束符(EOF)接收后接收到一個字符 CE_RXPARITY奇偶校驗錯誤 CE_TXFULL發(fā)送緩沖區(qū)滿 CE_DNS沒有檢測到并行設備 CE_OOP并行設備缺紙 CE_PTO并行設備發(fā)生超時錯誤

如果該函數(shù)調用成功,則返回值不為零;若函數(shù)調用失敗,則返回值為零。調用GetLastError()函數(shù)可以獲得進一步的出錯信息。在同步操作時,可以調用ClearCommError()函數(shù)來確定串口的接收緩沖區(qū)處于等待狀態(tài)的字節(jié)數(shù),而后可以使用ReadFile()或者WriteFile()函數(shù)一次讀寫完。

COMSTAT結構存放有關通信設備的當前信息。該結構內容由ClearCommError()函數(shù)填寫。COMSTAT結構聲明如下:

typedef struct_COMSTAT

(

DWORD fCtsHold: 1;

DWORD fDsrHold: 1;

DWORD fRlsdHold: 1;

DWORD fXoffSent: 1;

DWORD fEof: 1;

DWORD fTxim: 1;

DWORD fReserved: 25;

DWORD cbInQue;

DWORD cbOutQue;

} COMSTAT,*LPCOMSTAT;

其中主要參數(shù)介紹如下:

·fCtsHold:指明是否等待CRS信號,如果為1,則發(fā)送等待。

·fDsrHold:指明是否等到DRS信號,如果為1,則發(fā)送等待。

·fRlsdHold:指明是否等待RLSD信號,如果為1,則發(fā)送等待。

·fXoffSent:指明收到XOFF字符后發(fā)送是否等待。如果為1,則發(fā)送等待。如果把XOFF字符發(fā)送給一系統(tǒng)時,該系統(tǒng)就把下一個字符當成XON,而不管實際字符是什么,此時發(fā)送將停止。

·fEof:EOF字符送出。

·fTxim:指明字符是否正等待被發(fā)送,如果為1,則字符正等待被發(fā)送。

·fReserved:系統(tǒng)保留。

·cbInQue:指明串行設備接收到的字節(jié)數(shù)。并不是指ReadFile操作要求讀的字節(jié)數(shù)。

·cbOutQue:指明發(fā)送緩沖區(qū)尚未發(fā)送的字節(jié)數(shù)。如果進行不重疊寫操作時值為0。

代碼示例

#ifndef _WZSERIALPORT_H

#define _WZSERIALPORT_H

#include

#include

#include

using namespace std;

class WZSerialPort

{

public:

WZSerialPort();

~WZSerialPort();

// 打開串口,成功返回true,失敗返回false

// portname(串口名): 在Windows下是"COM1""COM2"等,在Linux下是"/dev/ttyS1"等

// baudrate(波特率): 9600、19200、38400、43000、56000、57600、115200

// parity(校驗位): 0為無校驗,1為奇校驗,2為偶校驗,3為標記校驗

// databit(數(shù)據(jù)位): 4-8,通常為8位

// stopbit(停止位): 1為1位停止位,2為2位停止位,3為1.5位停止位

// synchronizable(同步、異步): 0為異步,1為同步

//在這里已經(jīng)對配置進行了初始化,你們可以自己改配置使用

bool open(const char* portname, int baudrate = 115200, char parity = 0, char databit = 8, char stopbit = 1, char synchronizeflag = 1);

//關閉串口,參數(shù)待定

void close();

//發(fā)送數(shù)據(jù)或寫數(shù)據(jù),成功返回發(fā)送數(shù)據(jù)長度,失敗返回0

int send(string dat);

//接受數(shù)據(jù)或讀數(shù)據(jù),成功返回讀取實際數(shù)據(jù)的長度,失敗返回0

string receive();

//vector revcmsg;

private:

int pHandle[16];

char synchronizeflag;

};

#endif

#include "client.h"

#include

#include

#include

#include

WZSerialPort::WZSerialPort()

{

}

WZSerialPort::~WZSerialPort()

{

}

bool WZSerialPort::open(const char* portname,

int baudrate,

char parity,

char databit,

char stopbit,

char synchronizeflag)

{

this->synchronizeflag = synchronizeflag;

HANDLE hCom = NULL;

if (this->synchronizeflag)

{

//同步方式

hCom = CreateFileA(portname, //串口名

GENERIC_READ | GENERIC_WRITE, //支持讀寫

0, //獨占方式,串口不支持共享

NULL,//安全屬性指針,默認值為NULL

OPEN_EXISTING, //打開現(xiàn)有的串口文件

0, //0:同步方式,F(xiàn)ILE_FLAG_OVERLAPPED:異步方式

NULL);//用于復制文件句柄,默認值為NULL,對串口而言該參數(shù)必須置為NULL

}

else

{

//異步方式

hCom = CreateFileA(portname, //串口名

GENERIC_READ | GENERIC_WRITE, //支持讀寫

0, //獨占方式,串口不支持共享

NULL,//安全屬性指針,默認值為NULL

OPEN_EXISTING, //打開現(xiàn)有的串口文件

FILE_FLAG_OVERLAPPED, //0:同步方式,F(xiàn)ILE_FLAG_OVERLAPPED:異步方式

NULL);//用于復制文件句柄,默認值為NULL,對串口而言該參數(shù)必須置為NULL

}

if (hCom == (HANDLE)-1)

{

return false;

}

//配置緩沖區(qū)大小

if (!SetupComm(hCom, 1024, 1024))

{

return false;

}

// 配置參數(shù)

DCB p;

memset(&p, 0, sizeof(p));

p.DCBlength = sizeof(p);

p.BaudRate = baudrate; // 波特率

p.ByteSize = databit; // 數(shù)據(jù)位

switch (parity) //校驗位

{

case 0:

p.Parity = NOPARITY; //無校驗

break;

case 1:

p.Parity = ODDPARITY; //奇校驗

break;

case 2:

p.Parity = EVENPARITY; //偶校驗

break;

case 3:

p.Parity = MARKPARITY; //標記校驗

break;

}

switch (stopbit) //停止位

{

case 1:

p.StopBits = ONESTOPBIT; //1位停止位

break;

case 2:

p.StopBits = TWOSTOPBITS; //2位停止位

break;

case 3:

p.StopBits = ONE5STOPBITS; //1.5位停止位

break;

}

if (!SetCommState(hCom, &p))

{

// 設置參數(shù)失敗

return false;

}

//超時處理,單位:毫秒

//總超時=時間系數(shù)×讀或寫的字符數(shù)+時間常量

COMMTIMEOUTS TimeOuts;

TimeOuts.ReadIntervalTimeout = 1000; //讀間隔超時

TimeOuts.ReadTotalTimeoutMultiplier = 500; //讀時間系數(shù)

TimeOuts.ReadTotalTimeoutConstant = 5000; //讀時間常量

TimeOuts.WriteTotalTimeoutMultiplier = 500; // 寫時間系數(shù)

TimeOuts.WriteTotalTimeoutConstant = 2000; //寫時間常量

SetCommTimeouts(hCom, &TimeOuts);

PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);//清空串口緩沖區(qū)

memcpy(pHandle, &hCom, sizeof(hCom));// 保存句柄

return true;

}

void WZSerialPort::close()

{

HANDLE hCom = *(HANDLE*)pHandle;

CloseHandle(hCom);

}

int WZSerialPort::send(string dat)

{

HANDLE hCom = *(HANDLE*)pHandle;

if (this->synchronizeflag)

{

// 同步方式

DWORD dwBytesWrite = dat.length(); //成功寫入的數(shù)據(jù)字節(jié)數(shù)

BOOL bWriteStat = WriteFile(hCom, //串口句柄

(char*)dat.c_str(), //數(shù)據(jù)首地址

dwBytesWrite, //要發(fā)送的數(shù)據(jù)字節(jié)數(shù)

&dwBytesWrite, //DWORD*,用來接收返回成功發(fā)送的數(shù)據(jù)字節(jié)數(shù)

NULL); //NULL為同步發(fā)送,OVERLAPPED*為異步發(fā)送

if (!bWriteStat)

{

return 0;

}

return dwBytesWrite;

}

else

{

//異步方式

DWORD dwBytesWrite = dat.length(); //成功寫入的數(shù)據(jù)字節(jié)數(shù)

DWORD dwErrorFlags; //錯誤標志

COMSTAT comStat; //通訊狀態(tài)

OVERLAPPED m_osWrite; //異步輸入輸出結構體

//創(chuàng)建一個用于OVERLAPPED的事件處理,不會真正用到,但系統(tǒng)要求這么做

memset(&m_osWrite, 0, sizeof(m_osWrite));

m_osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, L"WriteEvent");

ClearCommError(hCom, &dwErrorFlags, &comStat); //清除通訊錯誤,獲得設備當前狀態(tài)

BOOL bWriteStat = WriteFile(hCom, //串口句柄

(char*)dat.c_str(), //數(shù)據(jù)首地址

dwBytesWrite, //要發(fā)送的數(shù)據(jù)字節(jié)數(shù)

&dwBytesWrite, //DWORD*,用來接收返回成功發(fā)送的數(shù)據(jù)字節(jié)數(shù)

&m_osWrite); //NULL為同步發(fā)送,OVERLAPPED*為異步發(fā)送

if (!bWriteStat)

{

if (GetLastError() == ERROR_IO_PENDING) //如果串口正在寫入

{

WaitForSingleObject(m_osWrite.hEvent, 1000); //等待寫入事件1秒鐘

}

else

{

ClearCommError(hCom, &dwErrorFlags, &comStat); //清除通訊錯誤

CloseHandle(m_osWrite.hEvent); //關閉并釋放hEvent內存

return 0;

}

}

return dwBytesWrite;

}

}

string WZSerialPort::receive()

{

HANDLE hCom = *(HANDLE*)pHandle;

string rec_str = "";

char buf[1024];

if (this->synchronizeflag)

{

//同步方式

DWORD wCount = 1024; //成功讀取的數(shù)據(jù)字節(jié)數(shù)

BOOL bReadStat = ReadFile(hCom, //串口句柄

buf, //數(shù)據(jù)首地址

wCount, //要讀取的數(shù)據(jù)最大字節(jié)數(shù)

&wCount, //DWORD*,用來接收返回成功讀取的數(shù)據(jù)字節(jié)數(shù)

NULL); //NULL為同步發(fā)送,OVERLAPPED*為異步發(fā)送

for (int i = 0; i < strlen(buf); i++)

{

if (buf[i] != -52)

{

//cout << buf[i];

rec_str += buf[i];

//revcmsg.push_back(buf[i]);

}

else

{

break;

}

}

return rec_str;

}

else

{

//異步方式

DWORD wCount = 1024; //成功讀取的數(shù)據(jù)字節(jié)數(shù)

DWORD dwErrorFlags; //錯誤標志

COMSTAT comStat; //通訊狀態(tài)

OVERLAPPED m_osRead; //異步輸入輸出結構體

//創(chuàng)建一個用于OVERLAPPED的事件處理,不會真正用到,但系統(tǒng)要求這么做

memset(&m_osRead, 0, sizeof(m_osRead));

m_osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, L"ReadEvent");

ClearCommError(hCom, &dwErrorFlags, &comStat); //清除通訊錯誤,獲得設備當前狀態(tài)

if (!comStat.cbInQue)

return ""; //如果輸入緩沖區(qū)字節(jié)數(shù)為0,則返回false

//std::cout << comStat.cbInQue << std::endl;

BOOL bReadStat = ReadFile(hCom, //串口句柄

buf, //數(shù)據(jù)首地址

wCount, //要讀取的數(shù)據(jù)最大字節(jié)數(shù)

&wCount, //DWORD*,用來接收返回成功讀取的數(shù)據(jù)字節(jié)數(shù)

&m_osRead); //NULL為同步發(fā)送,OVERLAPPED*為異步發(fā)送

if (!bReadStat)

{

if (GetLastError() == ERROR_IO_PENDING) //如果串口正在讀取中

{

//GetOverlappedResult函數(shù)的最后一個參數(shù)設為TRUE

//函數(shù)會一直等待,直到讀操作完成或由于錯誤而返回

GetOverlappedResult(hCom, &m_osRead, &wCount, TRUE);

}

else

{

ClearCommError(hCom, &dwErrorFlags, &comStat); //清除通訊錯誤

CloseHandle(m_osRead.hEvent); //關閉并釋放hEvent的內存

return "";

}

}

for (int i = 0; i < strlen(buf); i++)

{

if (buf[i] != -52)

{

rec_str += buf[i];

//revcmsg.push_back(buf[i]);

}

else

{

break;

}

}

return rec_str;

}

}

// test.cpp : 此文件包含 "main" 函數(shù)。程序執(zhí)行將在此處開始并結束。

//

#include

#include "client.h"

using namespace std;

int main()

{

std::cout << "Hello World!\n";

WZSerialPort w;

//這里是選擇端口號,其他波特率信息可在頭文件修改,或者在下面重新賦值。

if (w.open("COM3"))

{

cout << "打開成功" << endl;

cout << "在這里我發(fā)送:恭喜發(fā)財" << endl;

w.send("恭喜發(fā)財");

//w.close();

}

else

{

cout << "打開失敗" << endl;

}

while (true)

{

//w.receive();

cout << "receive: " << w.receive() << endl;

//w.revcmsg.clear();

}

}

// 運行程序: Ctrl + F5 或調試 >“開始執(zhí)行(不調試)”菜單

// 調試程序: F5 或調試 >“開始調試”菜單

// 入門使用技巧:

// 1. 使用解決方案資源管理器窗口添加/管理文件

// 2. 使用團隊資源管理器窗口連接到源代碼管理

// 3. 使用輸出窗口查看生成輸出和其他消息

// 4. 使用錯誤列表窗口查看錯誤

// 5. 轉到“項目”>“添加新項”以創(chuàng)建新的代碼文件,或轉到“項目”>“添加現(xiàn)有項”以將現(xiàn)有代碼文件添加到項目

// 6. 將來,若要再次打開此項目,請轉到“文件”>“打開”>“項目”并選擇 .sln 文件

虛擬串口工具和串口工具見:

鏈接:https://pan.baidu.com/s/15BfvpeWpIPRauCico3Y44Q

提取碼:zd4y

另外可以借鑒:https://blog.csdn.net/qq_41480046/article/details/82220155?spm=1001.2101.3001.6650.13&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-13-82220155-blog-104156394.pc_relevant_aa2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-13-82220155-blog-104156394.pc_relevant_aa2&utm_relevant_index=21

柚子快報邀請碼778899分享:網(wǎng)絡協(xié)議 串口通訊理解

http://yzkb.51969.com/

參考文章

評論可見,查看隱藏內容

本文內容根據(jù)網(wǎng)絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉載請注明,如有侵權,聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/18998561.html

發(fā)布評論

您暫未設置收款碼

請在主題配置——文章設置里上傳

掃描二維碼手機訪問

文章目錄