這幾天一直再看串口相關知識,對於其總結爲以下串口類:ide
頭文件聲明以下:函數
1 #pragma once 2 3 // 聲明當串口接收到線程的時候調用的函數指針 4 // 參數: 1,接收到的數據; 2,數據長度; 3,發送的目標地址 5 typedef void (*DataArriveProc)(char *data, int len, DWORD dest); 6 7 /*********************************** 8 1,實現一個串口類,用於進行串口的通訊; 9 2,其中的特性是,主動發送數據,被動接受 10 作出響應,其中開闢一個線程進型串口讀取; 11 3,線程函數響應時,應該將接受到的數據轉 12 發給使用此串口的上層應用; 13 ************************************/ 14 class CSerialPort 15 { 16 public: 17 CSerialPort(void); 18 virtual ~CSerialPort(void); 19 20 // 串口操做函數 21 BOOL OpenPort(LPCTSTR portName, DWORD baudRate, int dataBits, int stopBits, int parity, DataArriveProc proc, DWORD dest); 22 BOOL ClosePort(); // 關閉串口 23 DWORD WritePort(char *data, DWORD size); // 往串口寫數據 24 25 // 串口讀操做線程的操做函數 26 static UINT AFX_CDECL ReadPortProc(LPVOID lpParam);// 往串口讀數據的線程函數 27 BOOL Activate(); // 激活串口的讀操做 28 BOOL Deactivate(); // 取消串口的讀操做 29 BOOL IsActivate(); // 窗口是否已經準備好進行讀操做 30 31 private: 32 HANDLE m_hPortHandle; // 串口句柄 33 HANDLE m_hReadThread; // 讀線程 34 BOOL m_bReading; // 讀線程是否處於工做狀態 35 DCB m_dcbPort; // 串口的工做參數 36 COMMTIMEOUTS m_tmOut; // 串口通訊超時參數 37 38 DataArriveProc m_pDataArriveProc; // 接收到數據後的調用的方法 39 DWORD m_dwDestAddress; // 數據發送的目的地址 40 };
源文件定義以下:測試
1 #include "StdAfx.h" 2 #include "SerialPort.h" 3 #include "Resource.h" 4 5 CSerialPort::CSerialPort(void) 6 { 7 m_hPortHandle = INVALID_HANDLE_VALUE; 8 m_hReadThread = INVALID_HANDLE_VALUE; 9 m_bReading = FALSE; 10 } 11 12 CSerialPort::~CSerialPort(void) 13 { 14 if(INVALID_HANDLE_VALUE != m_hPortHandle){ 15 ClosePort(); 16 } 17 if(INVALID_HANDLE_VALUE != m_hReadThread){ 18 Deactivate(); 19 } 20 } 21 22 // 打開串口 23 // 1,打開串口文件; 24 // 2,設置串口屬性 25 // 3,完成操做; 26 BOOL CSerialPort::OpenPort(LPCTSTR portName, DWORD baudRate, int dataBits, int stopBits, int parity, DataArriveProc proc, DWORD dest) 27 { 28 if(INVALID_HANDLE_VALUE != m_hPortHandle){ 29 // 串口已經打開 30 return TRUE; 31 } 32 33 CString temp; 34 35 // 保存數據到達後的響應地址,及目的地 36 m_pDataArriveProc = proc; 37 m_dwDestAddress = dest; 38 39 // 1, 打開串口文件 40 m_hPortHandle = ::CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 41 if(INVALID_HANDLE_VALUE == m_hPortHandle){ 42 temp.LoadString(IDS_OPENPORT_FAIL); 43 AfxMessageBox(temp); 44 return FALSE; 45 } 46 47 // 2, 獲取串口的工做參數並從新賦值 48 GetCommState(m_hPortHandle, &m_dcbPort); 49 m_dcbPort.BaudRate = baudRate; // 設置波特率(外部設置) 50 m_dcbPort.ByteSize = dataBits; // 通訊字節位數 51 m_dcbPort.fParity = 1; // 奇偶校驗使能,1能夠 52 m_dcbPort.Parity = parity; // 校驗方式:外設 53 m_dcbPort.StopBits = stopBits;// 中止位 54 m_dcbPort.fBinary = 1; 55 m_dcbPort.fDtrControl = 0; 56 m_dcbPort.fRtsControl = 0; 57 m_dcbPort.fOutX= m_dcbPort.fInX= m_dcbPort.fTXContinueOnXoff=0; 58 59 // 3,設置一組監視串口設備的事件,什麼信息到達時通知 60 SetCommMask(m_hPortHandle, EV_RXCHAR); 61 // 4,設置串口的通訊參數,主要是緩衝區大小 62 SetupComm(m_hPortHandle, 10240, 10240); 63 // 5,設置工做參數 64 if(!SetCommState(m_hPortHandle, &m_dcbPort)){ 65 temp.LoadString(IDS_SETSTATE_FAIL); 66 AfxMessageBox(temp); 67 ClosePort(); 68 return FALSE; 69 } 70 71 // 6,獲取通訊超時信息並從新設置 72 GetCommTimeouts(m_hPortHandle, &m_tmOut); 73 m_tmOut.ReadIntervalTimeout = 100; 74 m_tmOut.ReadTotalTimeoutConstant = 100; 75 m_tmOut.ReadTotalTimeoutMultiplier = 100; 76 m_tmOut.WriteTotalTimeoutMultiplier = 100; 77 m_tmOut.WriteTotalTimeoutConstant = 100; 78 if(!SetCommTimeouts(m_hPortHandle, &m_tmOut)){ 79 temp.LoadString(IDS_SETTTMOUT_FAIL); 80 AfxMessageBox(temp); 81 ClosePort(); 82 return FALSE; 83 } 84 85 // 7,清空串口緩衝區 86 PurgeComm(m_hPortHandle, PURGE_RXCLEAR | PURGE_TXCLEAR); 87 return TRUE; 88 } 89 // 關閉串口 90 // 1,清空通訊設備監聽事件; 91 // 2,清空串口緩衝區; 92 // 3,關閉串口文件句柄; 93 BOOL CSerialPort::ClosePort() 94 { 95 if(INVALID_HANDLE_VALUE != m_hPortHandle){ 96 SetCommMask(m_hPortHandle, 0); 97 PurgeComm(m_hPortHandle, PURGE_RXCLEAR | PURGE_TXCLEAR); 98 CloseHandle(m_hPortHandle); 99 m_hPortHandle = INVALID_HANDLE_VALUE; 100 return TRUE; 101 } 102 103 return TRUE; 104 } 105 106 // 往串口寫數據 107 // 1,首先檢查串口是否處於工做狀態; 108 // 2,向串口寫入內容; 109 // 3,返回寫入的內容大小; 110 DWORD CSerialPort::WritePort(char *data, DWORD size) 111 { 112 if(INVALID_HANDLE_VALUE == m_hPortHandle){ 113 return 0; 114 } 115 116 DWORD writeLen = 0; 117 BOOL ret = FALSE; 118 119 ret = WriteFile(m_hPortHandle, data, size*sizeof(char), &writeLen, NULL); 120 121 return writeLen; 122 } 123 124 // 激活串口的讀操做 125 // 1,判斷串口是否已經打開; 126 // 2,判斷串口讀線程是否已經建立; 127 // 3,設置成員變量; 128 BOOL CSerialPort::Activate() 129 { 130 if(INVALID_HANDLE_VALUE == m_hPortHandle){ 131 return FALSE; 132 } 133 134 if(!m_bReading){ 135 m_hReadThread = AfxBeginThread(ReadPortProc, this); 136 m_bReading = TRUE; 137 } 138 139 if(INVALID_HANDLE_VALUE !=m_hReadThread){ 140 // ResumeThread(m_hReadThread); 141 return TRUE; 142 }else{ 143 m_bReading = FALSE; 144 return FALSE; 145 } 146 147 return FALSE; 148 } 149 // 取消串口的讀操做 150 // 1, 判斷串口是否已經打開; 151 // 2,判斷讀線程是否已經建立; 152 // 3,設置成員變量; 153 BOOL CSerialPort::Deactivate() 154 { 155 if(INVALID_HANDLE_VALUE == m_hPortHandle){ 156 return FALSE; 157 } 158 159 if(INVALID_HANDLE_VALUE == m_hReadThread){ 160 return FALSE; 161 } 162 163 if(m_bReading){ 164 WaitForSingleObject(m_hReadThread, INFINITE); 165 CloseHandle(m_hReadThread); 166 m_hReadThread = INVALID_HANDLE_VALUE; 167 m_bReading = FALSE; 168 return TRUE; 169 } 170 171 return FALSE; 172 } 173 // 窗口是否已經準備好進行讀操做 174 BOOL CSerialPort::IsActivate() 175 { 176 return m_bReading; 177 } 178 179 // 往串口讀數據的線程函數 180 // 對於線程處理函數須要是一個全局的或者靜態的 181 // 因此你須要知道你當前須要知道你用的是哪一個串口 182 // 實例,顧此函數參數爲串口實例指針 183 UINT CSerialPort::ReadPortProc(LPVOID lpParam) 184 { 185 // 1, 變量準備 186 CSerialPort *pPort = (CSerialPort*)lpParam; 187 CString temp; 188 char *buffer = NULL; 189 int buferSize = 512; 190 DWORD dwRead = 0; 191 BOOL bRead = FALSE; 192 193 // 2,基本條件判斷 194 buffer = new char[buferSize]; 195 while((pPort->m_hPortHandle != INVALID_HANDLE_VALUE) && (pPort->m_bReading)){ 196 bRead = ReadFile(pPort->m_hPortHandle, buffer, buferSize, &dwRead, NULL); 197 if(!bRead){ 198 temp.LoadString(IDS_READFILE_FAIL); 199 AfxMessageBox(temp); 200 }else{ 201 if(0 != dwRead) 202 pPort->m_pDataArriveProc(buffer, buferSize, pPort->m_dwDestAddress); 203 } 204 } 205 206 return 0; 207 }
對於上述代碼已編譯經過,可是具體的還未測試,等後續完善!this
謝謝支持!spa