Windows API編寫串口,過程一般是這樣的:
1、 通過CreateFile(“COMx:“,…) 打開串口,創建串口句柄
串口1---9,爲comN。大於10,爲\\\\.\\COM10
2、 通過配置DCB結構體和SetCommState函數,設置串口的參數。
對串口的參數進行設置,其中比較重要的是波特率(BaudRate),數據寬度(BytesBits),奇偶校驗(Parity),停止位(StopBits),當然,重要的還有端口號(Port);
3、 然後對串口進行相應的讀寫操作,這時候用到ReadFile和WriteFile函數;
4、 讀寫結束後,要關閉串口句柄,用CloseFile;
代碼示例:
#pragma once
#include <windows.h>
class CSerial
{
public:
CSerial(void);
~CSerial(void);
//打開串口
BOOL OpenSerialPort(TCHAR* port,UINT baud_rate,BYTE date_bits,BYTE stop_bit,BYTE parity=NOPARITY);
//發送數據
BOOL SendData(char* data,int len);
public:
HANDLE m_hComm;
};
#include "StdAfx.h"
#include "Serial.h"
typedef unsigned (__stdcall *PTHREAD_START) (void *);
CSerial::CSerial(void)
{
m_hComm = INVALID_HANDLE_VALUE;
}
CSerial::~CSerial(void)
{
if(m_hComm != INVALID_HANDLE_VALUE){
CloseHandle(m_hComm);
}
}
/*********************************************************************************************
* 功能 : 讀串口線程回調函數
* 描述 : 收到數據後,簡單的顯示出來
********************************************************************************************/
DWORD WINAPI CommProc(LPVOID lpParam){
CSerial* pSerial = (CSerial*)lpParam; //
//清空串口
PurgeComm(pSerial->m_hComm,PURGE_RXCLEAR|PURGE_TXCLEAR);
char buf[512];
DWORD dwRead;
while(pSerial->m_hComm != INVALID_HANDLE_VALUE){
BOOL bReadOK = ReadFile(pSerial->m_hComm,buf,512,&dwRead,NULL);
if(bReadOK && (dwRead > 0)){
buf[dwRead] = '\0';
MessageBoxA(NULL,buf,"串口收到數據",MB_OK);
}
}
return 0;
}
/*******************************************************************************************
* 功能 : 打開串口
* port : 串口號, 如_T("COM1:")
* baud_rate: 波特率
* date_bits: 數據位(有效範圍4~8)
* stop_bit : 停止位
* parity : 奇偶校驗。默認爲無校驗。NOPARITY 0; ODDPARITY 1;EVENPARITY 2;MARKPARITY 3;SPACEPARITY 4
********************************************************************************************/
BOOL CSerial::OpenSerialPort(TCHAR* port,UINT baud_rate,BYTE date_bits,BYTE stop_bit,BYTE parity){
//打開串口
m_hComm = CreateFile(port,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);//獨佔方式打開串口
TCHAR err[512];
if(m_hComm == INVALID_HANDLE_VALUE){
_stprintf(err,_T("打開串口%s 失敗,請查看該串口是否已被佔用"),port);
MessageBox(NULL,err,_T("提示"),MB_OK);
return FALSE;
}
//MessageBox(NULL,_T("打開成功"),_T("提示"),MB_OK);
//獲取串口默認配置
DCB dcb;
if(!GetCommState(m_hComm,&dcb)){
MessageBox(NULL,_T("獲取串口當前屬性參數失敗"),_T("提示"),MB_OK);
}
//配置串口參數
dcb.BaudRate = baud_rate; //波特率
dcb.fBinary = TRUE; //二進制模式。必須爲TRUE
dcb.ByteSize = date_bits; //數據位。範圍4-8
dcb.StopBits = ONESTOPBIT; //停止位
if(parity == NOPARITY){
dcb.fParity = FALSE; //奇偶校驗。無奇偶校驗
dcb.Parity = parity; //校驗模式。無奇偶校驗
}else{
dcb.fParity = TRUE; //奇偶校驗。
dcb.Parity = parity; //校驗模式。無奇偶校驗
}
dcb.fOutxCtsFlow = FALSE; //CTS線上的硬件握手
dcb.fOutxDsrFlow = FALSE; //DST線上的硬件握手
dcb.fDtrControl = DTR_CONTROL_ENABLE; //DTR控制
dcb.fDsrSensitivity = FALSE;
dcb.fTXContinueOnXoff = FALSE;//
dcb.fOutX = FALSE; //是否使用XON/XOFF協議
dcb.fInX = FALSE; //是否使用XON/XOFF協議
dcb.fErrorChar = FALSE; //是否使用發送錯誤協議
dcb.fNull = FALSE; //停用null stripping
dcb.fRtsControl = RTS_CONTROL_ENABLE;//
dcb.fAbortOnError = FALSE; //串口發送錯誤,並不終止串口讀寫
//設置串口參數
if (!SetCommState(m_hComm,&dcb)){
MessageBox(NULL,_T("設置串口參數失敗"),_T("提示"),MB_OK);
return FALSE;
}
//設置串口事件
SetCommMask(m_hComm,EV_RXCHAR); //在緩存中有字符時產生事件
SetupComm(m_hComm,16384,16384);
//設置串口讀寫時間
COMMTIMEOUTS CommTimeOuts;
GetCommTimeouts(m_hComm,&CommTimeOuts);
CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 10;
CommTimeOuts.WriteTotalTimeoutConstant = 1000;
/*若總共讀取8個字節。 間隔設置爲8ms, 總超時係數爲3ms,總超時常數爲3ms。 則總的超時時間爲3*8+3=27ms。若每個字符讀取的間隔爲7ms, 則這次操作總共能讀取4個字符。 就結束了。因爲讀取第5個字符時, 已經需要35ms, 超過總超時時間了。*/
if(!SetCommTimeouts(m_hComm,&CommTimeOuts)){
MessageBox(NULL,_T("設置串口時間失敗"),_T("提示"),MB_OK);
return FALSE;
}
//創建線程,讀取數據
HANDLE hReadCommThread = (HANDLE) _beginthreadex(NULL,0,(PTHREAD_START) CommProc,(LPVOID) this,0,NULL);
return TRUE;
}
/********************************************************************************************
* 功能 : 通過串口發送一條數據
********************************************************************************************/
BOOL CSerial::SendData(char* data,int len){
if(m_hComm == INVALID_HANDLE_VALUE){
MessageBox(NULL,_T("串口未打開"),_T("提示"),MB_OK);
return FALSE;
}
//清空串口
PurgeComm(m_hComm,PURGE_RXCLEAR|PURGE_TXCLEAR);
//寫串口
DWORD dwWrite = 0;
DWORD dwRet = WriteFile(m_hComm,data,len,&dwWrite,NULL);
//清空串口
PurgeComm(m_hComm,PURGE_RXCLEAR|PURGE_TXCLEAR);
if(!dwRet){
MessageBox(NULL,_T("發送數據失敗"),_T("提示"),MB_OK);
return FALSE;
}
return TRUE;
}
串口通訊中的DCB結構
typedef struct _DCB { // dcb
DWORD DCBlength; // sizeof(DCB)
DWORD BaudRate; // current baud rate 指定當前的波特率
DWORD fBinary: 1; // binary mode, no EOF check 指定是否允許二進制模式,WINDOWS 95中必須爲TRUE
DWORD fParity: 1; // enable parity checking 指定奇偶校驗是否允許
DWORD fOutxCtsFlow:1; // CTS output flow control 指定CTS是否用於檢測發送控制.當爲TRUE是CTS爲OFF,發送將被掛起
DWORD fOutxDsrFlow:1; // DSR output flow control 指定DSR是否用於檢測發送控制.當爲TRUE是DSR爲OFF,發送將被掛起
DWORD fDtrControl:2; // DTR flow control type DTR_CONTROL_DISABLE值將DTR置爲OFF, DTR_CONTROL_ENABLE值將DTR置爲ON, DTR_CONTROL_HANDSHAKE允許DTR"握手",
DWORD fDsrSensitivity:1; // DSR sensitivity 當該值爲TRUE時DSR爲OFF時接收的字節被忽略
DWORD fTXContinueOnXoff:1; // XOFF continues Tx 指定當接收緩衝區已滿,並且驅動程序已經發送出XoffChar字符時發送是否停止.TRUE時,在接收緩衝區接收到緩衝區已滿的字節XoffLim且驅動程序已經發送出XoffChar字符中止接收字節之後,發送繼續進行。FALSE時,在接收緩衝區接收到代表緩衝區已空的字節XonChar且驅動程序已經發送出恢復發送的XonChar之後,發送繼續進行。
DWORD fOutX: 1; // XON/XOFF out flow control TRUE時,接收到XoffChar之後便停止發送.接收到XonChar之後將重新開始
DWORD fInX: 1; // XON/XOFF in flow control TRUE時,接收緩衝區接收到代表緩衝區滿的XoffLim之後,XoffChar發送出去.接收緩衝區接收到代表緩衝區空的XonLim之後,XonChar發送出去
DWORD fErrorChar: 1; // enable error replacement 該值爲TRUE且fParity爲TRUE時,用ErrorChar 成員指定的字符代替奇偶校驗錯誤的接收字符
DWORD fNull: 1; // enable null stripping TRUE時,接收時去掉空(0值)字節
DWORD fRtsControl:2; // RTS flow control RTS_CONTROL_DISABLE時,RTS置爲OFF RTS_CONTROL_ENABLE時, RTS置爲ON RTS_CONTROL_HANDSHAKE時,當接收緩衝區小於半滿時RTS爲ON 當接收緩衝區超過四分之三滿時RTS爲OFF RTS_CONTROL_TOGGLE時,當接收緩衝區仍有剩餘字節時RTS爲ON ,否則缺省爲OFF
DWORD fAbortOnError:1; // abort reads/writes on error TRUE時,有錯誤發生時中止讀和寫操作
DWORD fDummy2:17; // reserved 未使用
WORD wReserved; // not currently used 未使用,必須爲0
WORD XonLim; // transmit XON threshold 指定在XON字符發送這前接收緩衝區中可允許的最小字節數
WORD XoffLim; // transmit XOFF threshold 指定在XOFF字符發送這前接收緩衝區中可允許的最小字節數
BYTE ByteSize; // number of bits/byte, 4-8 指定端口當前使用的數據位
BYTE Parity; // 0-4=no,odd,even,mark,space 指定端口當前使用的奇偶校驗方法,可能爲:EVENPARITY,MARKPARITY,NOPARITY,ODDPARITY
BYTE StopBits; // 0,1,2 = 1, 1.5, 2 指定端口當前使用的停止位數,可能爲:ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS
char XonChar; // Tx and Rx XON character 指定用於發送和接收字符XON的值
char XoffChar; // Tx and Rx XOFF character 指定用於發送和接收字符XOFF值
char ErrorChar; // error replacement character 本字符用來代替接收到的奇偶校驗發生錯誤時的值
char EofChar; // end of input character 當沒有使用二進制模式時,本字符可用來指示數據的結束
char EvtChar; // received event character 當接收到此字符時,會產生一個事件
WORD wReserved1; // reserved; do not use 未使用
} DCB;