您的位置:首页 > 其它

MFC串口通讯

2016-10-11 12:51 246 查看

一、环境配置

使用的VS版本为VS2015. 对话框工程。
操作串口需要包含以下头文件,工程配置中注意增加依赖项:setupapi.lib
#include "stdafx.h"
#include "stdlib.h"
#include "windows.h"
#include "setupapi.h"
并且在工程配置中:链接器->输入->附加依赖项 中输入setupapi.lib

二、从设备管理器中枚举Ports类设备

Ports类设备为串口所在的设备类型分组,其他包括并口,打印机端口等都在此分组中。首先通过Windows提供的API函数,将设备信息进行提取。
wchar_t SerialName[50][100] = { 0 };		//保存串口设备名称
unsigned char COM_RecvData[200] = { 0 };

/*******************************************************************************
* @Function    : FindSerialDevice
* @Description : 枚举出所有的串口外设,将外设信息保存到SerialName数组中
* @Input       : None
* @Output      : PortsName数组
* @Return      : n,串口外设数量
* @Auth        : Solen           2016/10/11
*******************************************************************************/
int FindSerialDevice(void)
{
/*1 变量声明*/
/*2 获取当前所有设备的信息*/
/*3 依次枚举所有设备,如果枚举成功则进行以下判断*/
/*4 若枚举成功则判断是否为Ports类设备,是则将该设备的名称端口存放到PortsName数组中*/
/*5 从Ports类中提取串口*/

/*1*/
HDEVINFO hDevInfo;
SP_DEVINFO_DATA DeviceInfoData;
wchar_t PortsName[50][100] = { 0 };		//保存Ports类设备名称
DWORD t;	//计数变量
int i;		//计数变量
int m = 0;	//PortsName 序号
int n = 0;	//SerialName 序号
wchar_t szClassBuf[MAX_PATH] = { 0 };
int COM_Flag = 0;
/*2*/
hDevInfo = SetupDiGetClassDevs(NULL, 0, 0, DIGCF_PRESENT | DIGCF_ALLCLASSES);
if (hDevInfo == INVALID_HANDLE_VALUE)
return NULL;

/*3*/
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (t = 0; SetupDiEnumDeviceInfo(hDevInfo, t, &DeviceInfoData); t++)
{
SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_CLASS, NULL, (PBYTE)szClassBuf, MAX_PATH - 1, NULL); //continue;//先找到设备的类
/*4*/
if (szClassBuf[0] == 'P'&&szClassBuf[1] == 'o'&&szClassBuf[2] == 'r'&&szClassBuf[3] == 't'&&szClassBuf[4] == 's')
{
SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)PortsName[m], MAX_PATH - 1, NULL);
for (i = 0; PortsName[m][i] != 0; i++)
{
switch (PortsName[m][i])
{
case '(':
COM_Flag++;
break;
case 'C':
if (COM_Flag == 1)
COM_Flag++;
break;
case 'O':
if (COM_Flag == 2)
COM_Flag++;
break;
case 'M':
if (COM_Flag == 3)
COM_Flag++;
break;
case ')':
if (COM_Flag == 4)

COM_Flag++;
break;
default:break;
}
}
if (COM_Flag == 5)
{
COM_Flag = 0;
SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)SerialName
, MAX_PATH - 1, NULL);
n++;
}
m++;
}
}
return n;
}

三、打开串口设备

这里需要指定串口号以及波特率,其他均为默认设置。串口号可以根据(二)中扫描到的串口号信息进行提取。
/*******************************************************************************
* @Function    : OpenSerialDevice
* @Description : 打开指定的串口设备
* @Input       : None
* @Output      :
* @Return      :  1:成功 0:失败
* @Auth        : Solen           2016/10/11
*******************************************************************************/
int OpenSerialDevice(wchar_t *SerialPort,int Baudrate)
{
hCom = CreateFile(SerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (hCom == INVALID_HANDLE_VALUE)
return 0;
SetupComm(hCom, 1024, 1024);
COMMTIMEOUTS ComTimeOut;
ComTimeOut.ReadIntervalTimeout = 1000;
ComTimeOut.ReadTotalTimeoutMultiplier = 500;
ComTimeOut.ReadTotalTimeoutConstant = 5000;
ComTimeOut.WriteTotalTimeoutMultiplier = 500;
ComTimeOut.WriteTotalTimeoutConstant = 2000;
SetCommTimeouts(hCom, &ComTimeOut);
DCB ComDcb;
GetCommState(hCom, &ComDcb);
ComDcb.BaudRate = Baudrate;
ComDcb.fBinary = 0;
ComDcb.ByteSize = 8;
ComDcb.Parity = NOPARITY;
ComDcb.StopBits = ONESTOPBIT;
SetCommState(hCom, &ComDcb);
PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);
return 1;
}

四、串口写操作

这里串口的读写与USB的读写使用的都是WriteFile函数/ReadFile函数
int SerialTransmit(char *SendData,DWORD DataLength)
{
DWORD dwBytesWrite = (DWORD)DataLength;
COMSTAT ComStat;
DWORD dwErrorFlags;
BOOL bWriteStat;
OVERLAPPED m_osWrite;//建立Overlapped结构
m_osWrite.InternalHigh = 0;
m_osWrite.Offset = 0;
m_osWrite.OffsetHigh = 0;
m_osWrite.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);//初始化Overlapped结构
ClearCommError(hCom, &dwErrorFlags, &ComStat);
bWriteStat = WriteFile(hCom, SendData, dwBytesWrite, &dwBytesWrite, &m_osWrite);//异步写串口
if (!bWriteStat) {
return 0;
}
PurgeComm(hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
return 1;
}

int SerialRecv(void)
{
DWORD dwBytesRead = 1000;
memset(COM_RecvData, 0, 200);
COMSTAT ComStat;
DWORD dwErrorFlags;
OVERLAPPED m_osRead;
memset(&m_osRead, 0, sizeof(OVERLAPPED));
m_osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ClearCommError(hCom, &dwErrorFlags, &ComStat);
dwBytesRead = min(dwBytesRead, (DWORD)ComStat.cbInQue);
if (!dwBytesRead)
{
return 0;
}
BOOL bReadStatus;
bReadStatus = ReadFile(hCom, COM_RecvData, dwBytesRead, &dwBytesRead, &m_osRead);
if ((!bReadStatus)||(dwBytesRead == 0))
{
return 0;
}
return dwBytesRead;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  MFC 串口