串口通讯相关
程序员文章站
2022-07-13 21:04:01
...
https://bbs.csdn.net/wap/topics/350150286
https://blog.csdn.net/wzmsltw/article/details/50723267
https://blog.csdn.net/henhen2002/article/details/4485186
https://www.cnblogs.com/chucks123/p/7545660.html
https://blog.csdn.net/alaseven/article/details/8875906
https://www.cnblogs.com/memset/archive/2012/12/24/common.html
https://www.cnblogs.com/wangweifeng/p/7599888.html
https://www.cnblogs.com/chucks123/p/7545660.html
https://blog.csdn.net/wzmsltw/article/details/50723267
https://blog.csdn.net/henhen2002/article/details/4485186
https://www.cnblogs.com/chucks123/p/7545660.html
https://blog.csdn.net/alaseven/article/details/8875906
https://www.cnblogs.com/memset/archive/2012/12/24/common.html
https://www.cnblogs.com/wangweifeng/p/7599888.html
https://www.cnblogs.com/chucks123/p/7545660.html
/*************************************************************************************************/ /*! \file SerialPort.h \attention Copyright (c) 2018 XXX. All Rights Reserved. \History [V1.00][2018-11-05][Jacky] - Init Version */ /*************************************************************************************************/ #ifndef SERIAL_PORT_H #define SERIAL_PORT_H /*** Include files *******************************************************************************/ #include <windows.h> #ifdef __cplusplus extern "C" { #endif /*** Defines/Macros/Constants/Typedefs ***********************************************************/ #define SERIAL_PORT_READ_BUFFER_SIZE 1024 typedef enum EM_SERIAL_PORT_PARITY { /*0-4=None,Odd,Even,Mark,Space*/ SerialPort_NoParity = NOPARITY, SerialPort_OddParity = ODDPARITY, SerialPort_EvenParity = EVENPARITY, SerialPort_MarkParity = MARKPARITY, SerialPort_SpaceParity = SPACEPARITY }SERIAL_PORT_PARITY; typedef enum EM_SERIAL_PORT_STOPBITS { /* 0,1,2 = 1, 1.5, 2 */ SerialPort_OneStopBit = ONESTOPBIT, SerialPort_OneFiveStopBits = ONE5STOPBITS, SerialPort_TwoStopBits = TWOSTOPBITS }SERIAL_PORT_STOPBITS; typedef enum EM_SERIAL_PORT_DATABITS {/* Number of bits/byte, 4-8 */ SerialPort_4DataBits = 4, SerialPort_5DataBits = 5, SerialPort_6DataBits = 6, SerialPort_7DataBits = 7, SerialPort_8DataBits = 8 }SERIAL_PORT_DATABITS; typedef enum EM_SERIAL_PORT_FLOWCONTROL {/* Number of bits/byte, 4-8 */ SerialPort_FlowControl_None = 0, SerialPort_FlowControl_HW = 1, SerialPort_FlowControl_SW = 2 }SERIAL_PORT_FLOWCONTROLS; typedef struct tag_SerialPortSetting { DWORD dwBaudRate; /* Baud rate at which running */ // The value should be equals followings which defined in WinBase.h //CBR_110/CBR_300/CBR_600/CBR_1200/CBR_2400/CBR_4800/CBR_9600 //CBR_14400/CBR_19200/CBR_38400/CBR_56000/CBR_57600/CBR_115200/CBR_128000/CBR_256000 SERIAL_PORT_DATABITS emDataBits; SERIAL_PORT_PARITY emParity; SERIAL_PORT_STOPBITS emStopBits; SERIAL_PORT_FLOWCONTROLS emFlowControl; DWORD dwIntervalTimeout; tag_SerialPortSetting() { dwBaudRate = CBR_115200; emDataBits = SerialPort_8DataBits; emParity = SerialPort_NoParity; emStopBits = SerialPort_OneStopBit; emFlowControl = SerialPort_FlowControl_None; dwIntervalTimeout = MAXDWORD; } }SerialPortSetting, *PSerialPortSetting; /*************************************************************************************************/ /*! \brief OpenSerialPort Opens a serial port(I/O). \param[in] strPort - The name of the file or device to be created or opened. You may use either forward slashes (/) or backslashes () in this name. \param[in] cSerialPortSetting - Detailed settings for the serial port. \return If the function succeeds, the return value is an open handle to the specified file, device, named pipe, or mail slot. If the function fails, the return value is INVALID_HANDLE_VALUE. */ /*************************************************************************************************/ HANDLE OpenSerialPort(IN CONST CString strPortName, IN CONST SerialPortSetting cSerialPortSetting); /*************************************************************************************************/ /*! \brief CloseSerialPort Closes a serial port(I/O). \param[in] hSerialPort - Pointer to the handle of the serial port. \return Return TRUE if the function succeeds else return FALSE. */ /*************************************************************************************************/ BOOL CloseSerialPort(IN CONST HANDLE hSerialPort); /*************************************************************************************************/ /*! \brief WriteDataToSerialPort Send data to specific serial port. \param[in] hSerialPort - Pointer to the handle of the serial port. \param[in] pbyData - Pointer to the buffer that specifies the data you want to send. \param[in] dwSize - The size of data buffer. \return Return TRUE if the function succeeds else return FALSE. */ /*************************************************************************************************/ BOOL WriteDataToSerialPort(IN CONST HANDLE hSerialPort, IN CONST BYTE* pbyData, IN CONST DWORD dwSize); /*************************************************************************************************/ /*! \brief ReadDataFromSerialPort Stores received data into a destination buffer. \param[in] hSerialPort - Pointer to the handle of the serial port. \param[in] pbyBuffer - Pointer to the raw destination buffer. \param[in/out] dwSize - The total size of data buffer/Used data buffer size. \return Return TRUE if the function succeeds else return FALSE. */ /*************************************************************************************************/ BOOL ReadDataFromSerialPort(IN CONST HANDLE hSerialPort, OUT BYTE* pbyBuffer, IN OUT DWORD& dwSize); #ifdef __cplusplus } #endif #endif//SERIAL_PORT_H
/*************************************************************************************************/ /*! \file SerialPort.cpp \attention Copyright (c) 2018 XXX. All Rights Reserved. \History [V1.00][2018-11-05][Jacky] - Init Version */ /*************************************************************************************************/ /*** Include files *******************************************************************************/ #include "stdafx.h" #include "SerialPort.h" #ifdef __cplusplus extern "C" { #endif /*************************************************************************************************/ /*! \brief OpenSerialPort Opens a serial port(I/O). \param[in] strPort - The name of the file or device to be created or opened. You may use either forward slashes (/) or backslashes () in this name. \param[in] cSerialPortSetting - Detailed settings for the serial port. \return If the function succeeds, the return value is an open handle to the specified file, device, named pipe, or mail slot. If the function fails, the return value is INVALID_HANDLE_VALUE. */ /*************************************************************************************************/ HANDLE OpenSerialPort(CONST CString strPortName, CONST SerialPortSetting cSerialPortSetting) { HANDLE hSerialPort = INVALID_HANDLE_VALUE; hSerialPort = CreateFile(strPortName, GENERIC_READ | GENERIC_WRITE, 0, // exclusive share NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == hSerialPort) { #ifdef DEBUG OutputDebugString(_T("Failed to open serial port!\n")); #endif return hSerialPort; } //Get Current Settings ////////////////////////////////////////////////////////////////////////// DCB cPortDCB; cPortDCB.DCBlength = sizeof(DCB); if (!GetCommState(hSerialPort, &cPortDCB))// Get the default serial parameter. { #ifdef DEBUG OutputDebugString(_T("Failed to call GetCommState()!\n")); #endif CloseHandle(hSerialPort); return INVALID_HANDLE_VALUE; } else { //Apply serial port settings ////////////////////////////////////////////////////////////////////////// cPortDCB.BaudRate = cSerialPortSetting.dwBaudRate; cPortDCB.ByteSize = cSerialPortSetting.emDataBits; cPortDCB.Parity = cSerialPortSetting.emParity; cPortDCB.StopBits = cSerialPortSetting.emStopBits; switch(cSerialPortSetting.emFlowControl) { case SerialPort_FlowControl_HW: { cPortDCB.fOutxCtsFlow = 1; cPortDCB.fRtsControl = RTS_CONTROL_HANDSHAKE; cPortDCB.fOutX = 0; cPortDCB.fInX = 0; break; } case SerialPort_FlowControl_SW: { cPortDCB.fOutxCtsFlow = 0; cPortDCB.fRtsControl = 0; cPortDCB.fOutX = 1; cPortDCB.fInX = 1; break; } case SerialPort_FlowControl_None: default: { cPortDCB.fOutxCtsFlow = 0; cPortDCB.fRtsControl = 0; cPortDCB.fOutX = 0; cPortDCB.fInX = 0; break; } } if (!SetCommState(hSerialPort, &cPortDCB)) { //config the serial port failed. CloseHandle(hSerialPort); return (INVALID_HANDLE_VALUE); } } //Config the serial port timeout property. ////////////////////////////////////////////////////////////////////////// COMMTIMEOUTS CommTimeouts; if (!GetCommTimeouts(hSerialPort, &CommTimeouts))//Get the serial port default timeout. { CloseHandle(hSerialPort); return INVALID_HANDLE_VALUE; } else { CommTimeouts.ReadIntervalTimeout = cSerialPortSetting.dwIntervalTimeout; CommTimeouts.ReadTotalTimeoutMultiplier = 10; CommTimeouts.ReadTotalTimeoutConstant = 10; CommTimeouts.WriteTotalTimeoutMultiplier = 50; CommTimeouts.WriteTotalTimeoutConstant = 100; if (!SetCommTimeouts(hSerialPort, &CommTimeouts)) { //config the serial port timeout failed; CloseHandle(hSerialPort); return INVALID_HANDLE_VALUE; } } return hSerialPort; //Everything should be fine. (~v~) - Cheers!!! } /*************************************************************************************************/ /*! \brief CloseSerialPort Closes a serial port(I/O). \param[in] hSerialPort - Pointer to the handle of the serial port. \return Return TRUE if the function succeeds else return FALSE. */ /*************************************************************************************************/ BOOL CloseSerialPort(CONST HANDLE hSerialPort) { return CloseHandle(hSerialPort); } /*************************************************************************************************/ /*! \brief WriteDataToSerialPort Send data to specific serial port. \param[in] hSerialPort - Pointer to the handle of the serial port. \param[in] pbyData - Pointer to the buffer that specifies the data you want to send. \param[in] dwSize - The size of data buffer. \return Return TRUE if the function succeeds else return FALSE. */ /*************************************************************************************************/ BOOL WriteDataToSerialPort(CONST HANDLE hSerialPort, CONST BYTE* pbyData, CONST DWORD dwSize) { BOOL bRet = FALSE; DWORD nHasBeenSend = 0; DWORD dwRet = 0; while (TRUE) { DWORD dwSendBytes = 0; if (!WriteFile(hSerialPort, pbyData+nHasBeenSend, dwSize-nHasBeenSend, &dwSendBytes, NULL)) { #ifdef DEBUG OutputDebugString(_T("Failed to call WriteFile()!\n")); #endif dwRet = GetLastError(); bRet = FALSE; break; } else { if (dwSendBytes > 0) { nHasBeenSend += dwSendBytes; } if (nHasBeenSend > dwSize) { #ifdef DEBUG OutputDebugString(_T("OverStack!\n")); #endif bRet = FALSE; break; } else if (dwSize == nHasBeenSend) { bRet = TRUE; break; } } } return bRet; } /*************************************************************************************************/ /*! \brief ReadDataFromSerialPort Stores received data into a destination buffer. \param[in] hSerialPort - Pointer to the handle of the serial port. \param[in] pbyBuffer - Pointer to the raw destination buffer. \param[in/out] dwSize - The total size of data buffer/Used data buffer size. \return Return TRUE if the function succeeds else return FALSE. */ /*************************************************************************************************/ BOOL ReadDataFromSerialPort(CONST HANDLE hSerialPort, BYTE* pbyBuffer, DWORD& dwSize) { //SetCommMask (hSerialPort, EV_RXCHAR); DWORD dwHasBeenReadSize = 0; BYTE byTempBuffer = 0x00; BOOL bRet = FALSE; DWORD dwMask = EV_RXCHAR; #ifdef DEBUG DWORD dwError = 0; #endif if (!WaitCommEvent(hSerialPort, &dwMask, NULL)) { #ifdef DEBUG OutputDebugString(_T("Failed to call WaitCommEvent()!\n")); #endif dwError = GetLastError(); //return FALSE; } if (!SetCommMask(hSerialPort, EV_RXCHAR)) { #ifdef DEBUG OutputDebugString(_T("Failed to call SetCommMask()!\n")); #endif //return FALSE; } while (TRUE) { DWORD dwReadBytes = 0; if (ReadFile(hSerialPort, &byTempBuffer, 1, &dwReadBytes, 0)) { if (dwReadBytes > 0) { if (dwHasBeenReadSize+dwReadBytes > dwSize) { //out of bounds ? #ifdef DEBUG OutputDebugString(_T("out of bounds!\n")); #endif bRet = FALSE; break; } else { memcpy(&pbyBuffer[dwHasBeenReadSize], &byTempBuffer, dwReadBytes); dwHasBeenReadSize += dwReadBytes; } } else { bRet = TRUE; break; } } else { #ifdef DEBUG OutputDebugString(_T("Failed to call ReadFile!\n")); #endif bRet = FALSE; break; } } dwSize = dwHasBeenReadSize; return bRet; } #ifdef __cplusplus } #endif
//===========================SerialPort.H的开始========================= #pragma once #include <windows.h> #include <string> using namespace std; HANDLE OpenSerialPort(string & strPort, ULONG ulBaudrate); void CloseSerialPort(HANDLE hSerial); bool WriteSerial(char* btData, ULONG ulSize, HANDLE hSerial); bool ReadSerial(BYTE *btData, ULONG *ulSize, HANDLE hSerial); //===========================SerialPort.H的结束=========================
#include "SerialPort.h" HANDLE OpenSerialPort(string & strPort, ULONG ulBaudrate) { HANDLE hSerial; hSerial = CreateFile((strPort.c_str()), GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, NULL, NULL); if (hSerial == INVALID_HANDLE_VALUE)//Open serial port failed. { return hSerial; } //Config serial port DCB PortDCB; PortDCB.DCBlength = sizeof(DCB); // Get the default serial parameter. GetCommState(hSerial, &PortDCB); PortDCB.BaudRate = ulBaudrate; // baudrate PortDCB.ByteSize = 8; // Number of bits/byte, 4-8 PortDCB.Parity = NOPARITY; PortDCB.StopBits = ONESTOPBIT; if (!SetCommState(hSerial, &PortDCB)) { //config the serial port failed. CloseHandle(hSerial); return (INVALID_HANDLE_VALUE); } //Config the serial port timeout property. COMMTIMEOUTS CommTimeouts; GetCommTimeouts(hSerial, &CommTimeouts); //Get the serial port default timeout. CommTimeouts.ReadIntervalTimeout = MAXDWORD; CommTimeouts.ReadTotalTimeoutMultiplier = 10; CommTimeouts.ReadTotalTimeoutConstant = 10; CommTimeouts.WriteTotalTimeoutMultiplier = 50; CommTimeouts.WriteTotalTimeoutConstant = 100; if (!SetCommTimeouts(hSerial, &CommTimeouts)) { //config the serial port timeout failed; CloseHandle(hSerial); return (INVALID_HANDLE_VALUE); } return (hSerial); }; void CloseSerialPort(HANDLE hSerial) { CloseHandle(hSerial); }; bool WriteSerial(char* btData, ULONG ulSize, HANDLE hSerial) { DWORD dwNumBytes, dwRet; dwRet = WriteFile(hSerial, //Handle btData, //Data buffer ulSize, //Buffer size &dwNumBytes, //written bytes NULL); //don't support return (dwRet != 0); }; bool ReadSerial(BYTE *btData, ULONG *ulSize, HANDLE hSerial) { //SetCommMask (hSerial, EV_RXCHAR); ULONG ulRdSize = 0; BYTE Byte; DWORD dwBytes; bool blRd = false; DWORD dwMask = EV_RXCHAR; //WaitCommEvent(hSerial,&dwMask,NULL); SetCommMask(hSerial, EV_RXCHAR); while (ReadFile(hSerial, &Byte, 1, &dwBytes, 0) != 0) { if (dwBytes>0) { btData[ulRdSize++] = Byte; if (ulRdSize == *ulSize) { blRd = true; break; } } else { blRd = true; break; } } *ulSize = ulRdSize; return (blRd); };
///////////////////////////////main.cpp//////////////////////////////////////// //使用代码示例: #include "SerialPort.h" #include <iostream> using namespace std; HANDLE hSerialPort; int main() { string portname = "COM4:"; string buff = "HELLO!"; char c[20]; strcpy_s(c, buff.c_str()); hSerialPort = OpenSerialPort( portname, 9600);//Open serial port com1 if (hSerialPort != INVALID_HANDLE_VALUE) { if (!WriteSerial(c, 7, hSerialPort))//Send data hello to com1 //MessageBox(0, "ERROR", "ERROR", MB_ICONWARNING);//show error message printf("ERROR!!"); //CloseSerialPort(hSerialPort); } system("pause"); }