⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 porttrans.cpp

📁 一个dll演示代码 用于串口通信的。 类似于工控的驱动
💻 CPP
字号:
// ComTrans.cpp: implementation of the CPortTrans  class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "PortTrans.h"
#include "stdio.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CPortTrans ::CPortTrans ()
{
    m_bOpenFlag = false;
	m_iComName = 2; 
	m_iBaudRate = 9600;
	m_iParity = 2;
	m_iByteSize = 7; 
	m_iStopBits = 0;	
	m_iTimeCount = 5;
	m_pEQData = "";
	m_iEquipmentAddress = 0;
	m_fEQcommdata = 0.00;
	m_fSVData = 0.00;
	m_fPVData = 0.00;
	m_iErrorNumber = 0;
	memset(m_pErrorData,0,sizeof(m_pErrorData));
	strcpy(m_pErrorData,"正常");
}

CPortTrans ::~CPortTrans ()
{
	
}

float CPortTrans ::GetEquipmentData()
{
	//返回设备通用数据
	return m_fEQcommdata;
}

float CPortTrans ::GetSVData()
{
	//返回SV数据
	return  m_fSVData ;
}

float CPortTrans ::GetPVData()
{
	//返回PV数据
    return m_fPVData ;
}

char * CPortTrans ::GetLastErrorText()
{
	//返回错误代码
    return m_pErrorData;
}
/*
思路:转换地址-构造命令-操作串口
*/
bool CPortTrans ::SendGetSVCommand(const int EquipmentAddress)
{
	
	//转换串口地址
	m_iEquipmentAddress = EquipmentAddress;
	char * strAddress = ConvertAdress(EquipmentAddress);
	//构造串口命令
	char strCommand [64];
	memset(strCommand,0,sizeof(strCommand));
	strcpy(strCommand,"\x04");
	strcat(strCommand,strAddress);
	strcat(strCommand,"\x53\x4c\x05");
	//操作串口
	if (OperateCom(strCommand))
	{
		//整理采集到的数据
	    if (CheckComData(false,EquipmentAddress)) 
	{
		m_fSVData = TransGetData();
		return true;
	}
		
	    else	
	
	{
		//进行错误处理
		memset(strCommand,0,sizeof(strCommand));
		strcpy(strCommand,"获取sv失败");
		SetErrorData(DATA_GET_ERROR,strCommand,EquipmentAddress);
		return false;
	}
	}
	return false;
}
/*
思路:转换地址-构造命令-操作串口
*/
bool CPortTrans ::SendGetPVCommand(const int EquipmentAddress)
{
	//转换串口地址
	m_iEquipmentAddress = EquipmentAddress;
	char * strAddress = ConvertAdress(EquipmentAddress);
	//构造串口命令
	char strCommand [64];
	memset(strCommand,0,sizeof(strCommand));
	strcpy(strCommand,"\x04");
	strcat(strCommand,strAddress);
	strcat(strCommand,"\x50\x56\x05");
	
	//操作串口
	if (OperateCom(strCommand))
	{
		if (CheckComData(false,EquipmentAddress)) 

		{
		m_fPVData = TransGetData();
		return true;
		}		
	   else
	   {
		//出错处理
		memset(strCommand,0,sizeof(strCommand));
		strcpy(strCommand,"获取pv失败");
		SetErrorData(DATA_GET_ERROR,strCommand,EquipmentAddress);
		return false;
	   }
	}
	return false;
}
/*
思路:转换地址-构造命令-操作串口
*/
bool CPortTrans ::SetEquipmentData(const int EquipmentAddress, const int Pro, const int Setvalue)
{	
    //临时字符串,用于计算ETX
	 char pB[15];
	 memset(pB,0,sizeof(pB));
	//转换地址
	m_iEquipmentAddress = EquipmentAddress;
	char  strAddress[10];
	memset(strAddress,0,sizeof(strAddress));
	strcpy(strAddress,ConvertAdress(EquipmentAddress ));
	//转换设定值
	char * strData = ConvertData(Setvalue);
	//构造串口命令
	//尾部
	char strCommend[1];
	//头部
	char * strCommandStart = "\x04";
	//命令字符串
	char strLinkCommand[64];
	//命令
	char  *strCommand;
	//命令名
	char *strCommandName;
	//根据Pro选择属性字符串
	switch(Pro) {
	case 0:
		//设定值
        strCommand = "\x53\x4C";
		strCommandName = "设定值";
		break;
	case 1:
		//al1报警值
		strCommand ="\x48\x41";
		strCommandName = "al1报警值";
		break;
	case 2:
		//al2报警值
		strCommand = "\x4c\x41";
		strCommandName = "al2报警值";
		break;
	default:
		//没有符合条件命令
		SetErrorData(DATA_SET_ERROR,"没有找到设置命令",EquipmentAddress);
		return false;
	}
	//构造串口命令
	memset(strLinkCommand,0,sizeof(strLinkCommand));
	strcpy(strLinkCommand,strCommandStart);
	strcat(strLinkCommand,strAddress);
	strcat(strLinkCommand,"\x02");
	//
    strcpy(pB,strCommand);
	strcat(pB,strData);
	strcat(pB,"\x03");
	//
	memset(strCommend,0,sizeof(strCommend));
	sprintf(strCommend,"%c",GetBCC(pB,strlen(pB)));
	//
	strcat(strLinkCommand,pB);
	strcat(strLinkCommand,strCommend);
	//操作串口
    if (OperateCom(strLinkCommand,true)) 
	{
		//判断是否操作成功
		if (CheckComData(true,EquipmentAddress)) return true;
		else
			
		{
			//错误处理
			memset(strLinkCommand,0,sizeof(strLinkCommand));
			strcpy(strLinkCommand,"设置设备");
			strcat(strLinkCommand,strCommandName);
			strcat(strLinkCommand,"失败");
			SetErrorData(DATA_SET_ERROR,strLinkCommand,EquipmentAddress);
		}
    }
	return false;
}
/*
思路:转换地址-构造命令-操作串口
*/
bool CPortTrans ::SendEquipmentCommand(const int EquipmentAddress, const int CommandID)
{
	//转换地址信息
	m_iEquipmentAddress = EquipmentAddress;
	char *  strAddress=ConvertAdress(EquipmentAddress );
	//尾部
	char *  strCommend= "\x05";
	//头部
	char * strCommandStart = "\x04";
	//合成的命令字符串
	char strLinkCommand[64];
    //命令
	char * strCommand;
	//命令名称
	char *strCommandName;
	//根据CommandID选择命令字符串
	switch(CommandID) {
	case 0:
		//温度
		strCommand = "\x50\x56";
		strCommandName = "当前温度";
		break;
	case 1:
		//设定值
		strCommand= "\x53\x4c";
        strCommandName = "当前设定值";
		break;
	case 2:
		//输出功率
		strCommand = "\x4f\x50";
		strCommandName = "输出功率";
		break;
	case 3:
		//al1报警值
		strCommand = "\x48\x41";
		strCommandName = "al1报警值";
		break;
	case 4:
        //al2报警值
		strCommand = "\x4c\x41";
		strCommandName = "al2报警值";
		break;
	default:
		SetErrorData(DATA_GET_ERROR,"没有找到设备命令",EquipmentAddress);
		return false;
	}
	//构造串口命令
	memset(strLinkCommand,0,sizeof(strLinkCommand));
	strcpy(strLinkCommand,strCommandStart);
	strcat(strLinkCommand,strAddress);
	strcat(strLinkCommand,strCommand);
	strcat(strLinkCommand,strCommend);
	
	//操作串口
	if (OperateCom(strLinkCommand)) 
	{ 
		if (CheckComData(false,EquipmentAddress)) 
		{
		m_fEQcommdata = TransGetData();
		return true;
		}
	 else	
	 {
		//错误处理
		memset(strLinkCommand,0,sizeof(strLinkCommand));
		strcpy(strLinkCommand,"获取设备");
		strcat(strLinkCommand,strCommandName);
		strcat(strLinkCommand,"失败");
		SetErrorData(DATA_GET_ERROR,strLinkCommand,EquipmentAddress);
		return false;
	 }
	}
	return false;
}

int CPortTrans ::GetComSet(const int Pro)
{
	int iReturn;
	//根据Pro选择相应的串口属性
	switch(Pro) 
	{
		//进行数据类型转换。但是没有找到库文件
	case 0 :
		//串口名
		iReturn = m_iComName ;
		break;
	case 1 :
		//波特率
		iReturn =  m_iBaudRate;
		break;
	case 2 :
		//数据宽度
		iReturn =  m_iByteSize;
		break;
	case 3:
		//奇偶校验
		iReturn = m_iParity ;
		break;
	case 4:
		//停止位
	   iReturn =  m_iStopBits;
	   break;
	default:
		SetErrorData(COM_GET_ERROR,"没有找到串口属性");
		iReturn = -100;
	}
	return iReturn ;
}

bool CPortTrans ::SetCom(const int Pro,  int Value)
{
	
	//根据Pro选择相应的设置属性
	switch(Pro) 
	{
		
	case 0 :
		//串口名
		m_iComName =Value; 
		break;
	case 1 :
		//波特率
		m_iBaudRate = Value;
		break;
	case 2 :
		//数据宽度
		m_iByteSize = Value;
		break;
	case 3:
		//奇偶校验
		m_iParity = Value;
		break;	
	case 4:
		//停止位
		m_iStopBits = Value;
		break;
	default:
		SetErrorData(COM_SET_ERROR,"没有找到串口属性");
		return false;
	}
	return OpenCom();
}

bool CPortTrans ::CloseCom()
{
	bool Flag = CloseHandle(m_Handle);
	if (Flag) 
		m_bOpenFlag = false;
	else
		SetErrorData(COM_SET_ERROR,"com口关闭错误");
	return Flag;
	
}

bool CPortTrans ::OpenCom()
{
	//如果串口已经打开,先关闭
	if (m_bOpenFlag) CloseCom();
   //转换串口名
	char Comnamebuffer[6];
	char Numberbuffer[2];
	char *name = "com";
	memset(Comnamebuffer,0,sizeof(Comnamebuffer));
	memset(Numberbuffer,0,sizeof(Numberbuffer));
	itoa(m_iComName,Numberbuffer,10);
	strcpy(Comnamebuffer,name);
	strcat(Comnamebuffer,Numberbuffer);
    //设置参数
	COMMTIMEOUTS timeouts = {	// 串口超时控制参数
		100,				// 读字符间隔超时时间: 100 ms
			1,					// 读操作时每字符的时间: 1 ms (n个字符总共为n ms)
			500,				// 基本的(额外的)读超时时间: 500 ms
			1,					// 写操作时每字符的时间: 1 ms (n个字符总共为n ms)
			100};				// 基本的(额外的)写超时时间: 100 ms
		//打开串口
		m_Handle = CreateFile(Comnamebuffer,	// 串口名称或设备路径
			GENERIC_READ | GENERIC_WRITE,	// 读写方式
			0,				// 共享方式:独占
			NULL,			// 默认的安全描述符
			OPEN_EXISTING,	// 创建方式
		    0,	// 异步通信
			NULL);			// 不需参照模板文件
		
		if(m_Handle == INVALID_HANDLE_VALUE) 
		{   
			SetErrorData(COM_SET_ERROR,"串口初始化失败");
			m_bOpenFlag = false;
		     return FALSE;	
		}// 打开串口失败
		//设置串口属性
		GetCommState(m_Handle, &m_Dcb);		// 取DCB
		m_Dcb.BaudRate = m_iBaudRate;
		m_Dcb.ByteSize = m_iByteSize;
		m_Dcb.Parity = m_iParity;
		m_Dcb.StopBits = m_iStopBits;
		 if(!SetCommState(m_Handle, &m_Dcb))
		 {
			 SetErrorData(COM_SET_ERROR,"串口设置失败,请检查串口参数");
		     return false;
		 }// 设置DCB
	    GetCommState(m_Handle, &m_Dcb);
		SetupComm(m_Handle, 4096, 1024);	// 设置输入输出缓冲区大小
		SetCommTimeouts(m_Handle, &timeouts);	// 设置超时
		m_bOpenFlag = true;
		return TRUE;
		
}

bool CPortTrans ::InitComExt(int nCom, int nBaudRate, int nParity, 
							 int nByteSize, int nStopBits,int nTimeout)
{
	//设置串口
	 m_iComName = nCom;
	//设置波特率
	m_iBaudRate = nBaudRate;
	//设置奇偶校验
	m_iParity = nParity ;
	//设置数据宽度
	m_iByteSize = nByteSize ;
	//设置停止位
	m_iStopBits = nStopBits ;
	//设置连接超时时间
	m_iTimeCount = nTimeout;
	return OpenCom();
}
void CPortTrans ::WritToCom(char *pData, int nLength)
{   
	// 串口发出的数据长度
    DWORD dwNumWrite;	
	WriteFile(m_Handle, pData, (DWORD)nLength, &dwNumWrite, NULL);
}

void CPortTrans ::ReadFromCom(char *pData, int nLength)
{   
	// 串口收到的数据长度
	DWORD dwNumRead;	
	ReadFile(m_Handle, pData, (DWORD)nLength, &dwNumRead, NULL);
	
}
/*
思路与算法:
定义两个字符串和两个个int变量,用来存储转换后的十位和个位

*/
char *  CPortTrans ::ConvertAdress(int address)

{   
	//转换用数据,转换设备地址,
	char sShiwei[10],sGewei[10],sData[30];
	int iShiwei,iGewei;
	//转换算法
	//如果地址是0
	if (address ==0)
	{
		itoa(0,sShiwei,10);
		itoa(0,sGewei,10);
	}
	else
	{
		
		//取address的十位
		iShiwei = address/10;
		//将十位转换成字符
		itoa(iShiwei,sShiwei,10);
		//取address的个位
		iGewei = address%10;
		//将个位转换成字符
		itoa(iGewei,sGewei,10);
	}
	//构造命令用字符串
	memset(sData,0,sizeof(sData));
	//十位重复复制
	strcpy(sData,sShiwei);
	strcat(sData,sShiwei);
	//个位重复复制
	strcat(sData,sGewei);
	strcat(sData,sGewei);
	//返回地址
    return sData;
}

char * CPortTrans ::ConvertData(long data)
{
	char pData[20];
	memset(pData,0,sizeof(pData));
	sprintf(pData,"%d",data);
	return pData;
}

bool CPortTrans::CheckComData(bool bCheckSet,int nEquipmentAddress)
{
	//判断设置是否成功 06h为成功,其他为失败

	if (bCheckSet)
	{	
		if (strcmp(m_pEQData,"\x06") ==0) 
			return true;
		else	
			if (strcmp(m_pEQData,"\x15") == 0) 
			SetErrorData(DATA_SET_ERROR,"设置设备属性错误",nEquipmentAddress);	
			return false;
	}
	//判断数据是否有效,
	//负数判断为字符串' - '
	//进行bcc校验
	  char pTempBuffer[15];
	  memset(pTempBuffer,0,sizeof(pTempBuffer));
	  strncpy(pTempBuffer,(m_pEQData+1),8);
	  char a = m_pEQData[9];
	   int ct = strlen(m_pEQData);
	  if(GetBCC(pTempBuffer,strlen(pTempBuffer))!=a)
	  {
		  SetErrorData(DATA_GET_ERROR,"数据校验错误",nEquipmentAddress);
		  return false;
	  }
	//
	for (int i = 3;i<8;i++)
	{
		//如果是空格 . 和-负号就不做判断
		if (m_pEQData[i]== ' '||m_pEQData[i]== '.'||m_pEQData[i]== '-')continue;
		//判断是否十0-9
		if (m_pEQData[i]<48||m_pEQData[i]>57)
			return false;
	}
	return true;
	
}

float CPortTrans::TransGetData()
{
	//根据type转换得到的设备数据
	char pData[6];
	memset(pData,0,sizeof(pData));
	strncpy(pData,(m_pEQData+3),5);
	return atof(pData);
}



bool CPortTrans::OperateCom(char *pstrCommand,bool bSetFlag)
{
	//读写串口 ,判断连接情况
	int iTemp = m_iTimeCount;
	memset(m_pBuffer,0,sizeof(m_pBuffer));
	WritToCom(pstrCommand,strlen(pstrCommand));
	Sleep(10);
	ReadFromCom (m_pBuffer,sizeof(m_pBuffer));
	//如果没有数据返回,测试连接
	while (strcmp(m_pBuffer,"")==0) 
	{
		if (m_iTimeCount == 0)
		{
			SetErrorData(COM_LINK_ERROR,"没有数据返回,连接超时,请检查网络,");
			return false;
		}
		else	
		{
			WritToCom(pstrCommand,strlen(pstrCommand));
			Sleep(10);
			ReadFromCom (m_pBuffer,sizeof(m_pBuffer));
			m_iTimeCount --;
			continue;
		}
	}	
	m_iTimeCount = iTemp;
	m_pEQData = m_pBuffer;
	return true;  
}

int CPortTrans::GetLastErrorNumber()
{
	return m_iErrorNumber;
}

void CPortTrans::SetErrorData(int ErrorNumber, char *ErrorString,int EquipmentAddress)
{
	//临时变量用来存储转换后的数据
	char  strEnumber[5];
	//构造错误字符串
	memset(strEnumber,0,sizeof(strEnumber));
	memset(m_pErrorData,0,sizeof(m_pErrorData));
	strcpy(m_pErrorData,"\n串口错误: ");
	strcat(m_pErrorData,ErrorString);
	strcat(m_pErrorData,"\n机器地址:  ");
	sprintf(strEnumber,"%d",EquipmentAddress);
	strcat(m_pErrorData,strEnumber);
    m_iErrorNumber = ErrorNumber;
}

bool CPortTrans::GetComState()
{
	return m_bOpenFlag;
}

char CPortTrans::GetBCC(char *pchars, int nLenth)
{
	
	char tempchar = pchars[0];
	
	for (int i = 0;i<nLenth-1;i++) 
	{
		tempchar = tempchar^pchars[i+1];
	}
    return tempchar;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -