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

📄 sim.cpp

📁 EVC(嵌入式VC++)发的用于串口通信的程序
💻 CPP
字号:
// SIM.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "SIM.h"
#include "comport.h"
#include "inifile.h"
HANDLE m_hThread;
HANDLE m_hPollExit=CreateEvent(NULL,FALSE,FALSE,NULL);
bool m_bStart=false;
CComPort m_comPort; //串口
CIniFile m_iniFile;
HANDLE m_commEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
int m_nRev=0;  
Mod *m_pMod=NULL; //当前卡件  
CMyCriticalSection m_csMod;
DWORD m_lastTime=0;

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    switch (ul_reason_for_call)
	{
		case DLL_PROCESS_ATTACH: //进程被创建
			{
				//加载设置参数
				//获取主程序所在路径,存在sPath中
				WCHAR sPath[256];
				GetModuleFileName(NULL,sPath,MAX_PATH);//sPath返回.exe文件所在路径,类似于delphi中的Filename:=ExtractFilePath(Paramstr(0))+'sz.ini';
				int nPos;
				nPos = ReverseFind(sPath,_T("\\"));//从sPath字符串的最后面开始查找"\",\\转义字符
				if(nPos>0)
					wcscpy(sPath+nPos,_T("\0"));  //去掉.exe
				WCHAR sFile[256];
				wsprintf(sFile,_T("%s\\Dpu.ini"),sPath);
				Replace(sFile,_T("\\\\"),_T("\\")); //在sFile中比如为c:\DEBUG\\Dpu.ini中将\\替换成\

				m_iniFile.LoadIniFile(sFile);

				LoadModSet();
			}
			break;
		case DLL_THREAD_ATTACH:
		case DLL_THREAD_DETACH:
		case DLL_PROCESS_DETACH:
			break;
    }
    return TRUE;
}


// This is an example of an exported variable
SIM_API int nSIM=0;
// This is an example of an exported function.
SIM_API int fnSIM(void)
{
	return 42;
}

// This is the constructor of a class that has been exported.
// see SIM.h for the class definition
CSIM::CSIM()
{ 
	return; 
}

void DrvAddFmt(LPCTSTR sAdd)//默认地址
{
}

BOOL DrvGetDesc(DWORD hKey,LPCTSTR sDesc)		//描述
{

	return FALSE;
}

void DrvConfig()//配置驱动程序
{

}

//卡件设备地址:寄存器地址:数据类型 ,根据寄存器中每个通道的起始地址和数据长度来读对应通道的数据 比较灵活
DWORD DrvAddTag(LPCTSTR sAdd,DWORD dwCyc)//增加一个测点
{
	int i=0;
	WCHAR sAddr[256];
	WCHAR sTemp[256];
	Mod *pMod=NULL;
	if(wcslen(sAdd)>256)
		return FALSE;
	wcscpy(sAddr,sAdd);
	int nAddr=0,nRegAddr=0,nDataType=D_FLOAT;
	int nPos=0;
	nPos=Find(sAddr,_T(":"),0);
	if(nPos<0)
		return  FALSE;
	Mid(sAddr,0,nPos,sTemp);
	nAddr=_wtoi(sTemp);//卡件地址

	Mid(sAddr,nPos+1,wcslen(sAddr)-nPos,sAddr);
	nPos=Find(sAddr,_T(":"),0);
	if(nPos<0)
		return  FALSE;
	Mid(sAddr,0,nPos,sTemp);
	nRegAddr=_wtoi(sTemp)-1; //寄存器地址 

	Mid(sAddr,nPos+1,wcslen(sAddr)-nPos,sTemp);
	if(CompareNoCase(sTemp,_T("FLOAT"))==0)
		nDataType=D_FLOAT;
	else
		nDataType=D_LONG;  //数据类型
	for(i=0;i<m_arMod.size();i++)
	{
		pMod=m_arMod[i];
		if(pMod)
		{
			if(pMod->nAddr==nAddr)
				break;
			else
				pMod=NULL;
		}
	}
	
	Tag *pTag=NULL;
	pTag=new Tag;
	if(pTag)
	{
		pTag->nAddr=nRegAddr;
		pTag->nDataType=nDataType;
		pTag->pMod=pMod;
		return (DWORD)pTag;
	}
	else
		return FALSE;
}

BOOL DrvDelTag(WORD hKey,DWORD dwCyc)//删除一个测点
{
	return TRUE;

}

void DrvClear()//清除所有测点
{


}


int	DrvGetVal(DWORD hKey,double* dbVal)//读
{
	Tag *pTag=(Tag*)hKey;
	Mod *pMod=pTag->pMod;
	float fVal=0;
	if(pMod)
	{
		pMod->GetVal(pTag->nAddr,pTag->nDataType,fVal);
		*dbVal=(double)fVal;
	}
	else
		return 5;
	return 0;
}

int	DrvSetVal(DWORD hKey,double dbVal)//写
{
	return 0;
}

BOOL DrvGetMsg(int* nType,LPCTSTR sMsg)//运行消息
{
	return FALSE;
}

BOOL DrvStart()//启动扫描
{
	if(!OpenComm())
		return FALSE;

    DWORD dwThreadID;
	m_bStart=true;
	//创建数据采集线程,写线程
    m_hThread=CreateThread(NULL, 0x100000, (LPTHREAD_START_ROUTINE)DrvPoll,
                           (LPVOID)NULL, STACK_SIZE_PARAM_IS_A_RESERVATION, &dwThreadID);
	if(!m_hThread)
    {
		m_bStart=false;
		return FALSE;
    }

	return TRUE;
}

void DrvStop()//终止扫描
{
	ResetEvent(m_hPollExit);
	m_bStart=false;
	WaitForSingleObject(m_hPollExit,5000);
	//关闭串口
	m_comPort.CloseComm();
    Sleep(100);
	
}
/* Dpu.ini
[Set]
nMod=2 //总卡件数
Com=COM4
Baud=38400
TotalMod=2
[Mod1] //第一卡件的配置信息
Function=3
nReg=17
Addr=2
TimeOut=300
[Mod2] //第一卡件的配置信息
Function=3
nReg=17
Addr=3
TimeOut=300
*/

UINT DrvPoll(LPVOID pParam) //发送指令给卡件
{
	unsigned char chCmd[17]={0};//17个寄存器,34个字节
	Mod *pMod=NULL;
	WORD wdCRC=0;
	UINT nCmd=0;
	int i=0;
	while(m_bStart)
	{
		for(i=0;i<m_arMod.size();i++)
		{
			memset(chCmd,0,17);
			pMod=m_arMod[i];
			if(pMod)
			{
				chCmd[0]=pMod->nAddr;
				chCmd[1]=pMod->nFunction; //2,3,4均设置为0
				chCmd[5]=pMod->nReg;
				wdCRC=m_comPort.CRC16(chCmd,6);
				chCmd[6]=wdCRC/256;
				chCmd[7]=wdCRC%256;

			}
			else
				continue;
			m_csMod.Lock();
			m_pMod=pMod;
			m_csMod.Unlock();

			if(m_comPort.IsOpened())
			{
				ResetEvent(m_commEvent);

				m_nRev=0;
				m_comPort.WriteComm(chCmd,8); //发送数据采集命令
				//int resu=WaitForSingleObject(m_commEvent,pMod->nTimeOut);
				if(WAIT_TIMEOUT==WaitForSingleObject(m_commEvent,pMod->nTimeOut))
				{
					pMod->bComm=false;
					m_csMod.Lock();
					m_pMod=NULL;
					m_csMod.Unlock();
				}
				else
				{
					pMod->bComm=true;
				}
			}
			else
			{
				pMod->bComm=false;
				m_csMod.Lock();
				m_pMod=NULL;
				m_csMod.Unlock();
			}
			Sleep(200);
		}//next
		Sleep(50);
	}//while
	SetEvent(m_hPollExit);
	return 0;
}

UINT MonitorCallback(unsigned char *hBuf, int nLen, LPARAM lParam)
{
	static unsigned char buff[1024];
	Mod *pMod=NULL;
	m_csMod.Lock();
	pMod=m_pMod;
	WORD wdCRC=0;
	int i=0;
	int index=0;
	DWORD nowTime=0;
	nowTime=::GetTickCount();
	if(m_nRev>0 && (nowTime-m_lastTime)>500)
	{
		//接收超时,清空缓冲区
		m_nRev=0;
	}
	m_lastTime=nowTime;
	if(pMod) //数据处理
	{
		memcpy(buff+m_nRev,hBuf,nLen);
		m_nRev+=nLen;
		if( m_nRev>=(pMod->nReg*2+5))
		{
			wdCRC=m_comPort.CRC16(buff,pMod->nReg*2+3);
			if(wdCRC/256==buff[pMod->nReg*2+3] && wdCRC%256==buff[pMod->nReg*2+4]) //检查CRC校验
			{
				pMod->SetVal(0,pMod->nReg*2,buff+3);
				SetEvent(m_commEvent);
			}
			m_nRev=0;
		}
	}
	else //数据接受错误则抛弃
		m_nRev=0;
	m_csMod.Unlock();
	return 0;
}

bool OpenComm()
{
	UINT nBaud=0;
	WCHAR sTemp[256],sPort[256];
	m_iniFile.GetKeyString(_T("Set"),_T("Com"),_T("COM4"),sPort);
	m_iniFile.GetKeyString(_T("Set"),_T("Baud"),_T("38400"),sTemp);
	nBaud=_wtoi(sTemp);//atoi
	//打开串口
	if(!m_comPort.OpenComm(sPort,nBaud))
		return false;
	if(!m_comPort.Monitor((LPMONITORPROC)&MonitorCallback, NULL))
	{
		m_comPort.CloseComm();
		return false;
	}
	return true;
}

//加载卡件通讯设置,创建卡件通讯对象
bool LoadModSet()
{
	Mod *pMod=NULL;
	m_arMod.clear();
	int i=0;
	UINT nMod=0,nFunction=0,nReg=0,nAddr=0,nTimeOut=0;
	WCHAR sTemp[256],sMod[256];
	m_iniFile.GetKeyString(_T("Set"),_T("TotalMod"),_T("2"),sTemp);
	nMod=_wtoi(sTemp);
	for( i=0;i<nMod;i++)
	{
		wsprintf(sMod,_T("Mod%d"),i+1);
		m_iniFile.GetKeyString(sMod,_T("Function"),_T("3"),sTemp);
		nFunction=_wtoi(sTemp);

		m_iniFile.GetKeyString(sMod,_T("nReg"),_T("17"),sTemp);
		nReg=_wtoi(sTemp);

		m_iniFile.GetKeyString(sMod,_T("Addr"),_T("1"),sTemp);
		nAddr=_wtoi(sTemp);

		m_iniFile.GetKeyString(sMod,_T("TimeOut"),_T("300"),sTemp);
		nTimeOut=_wtoi(sTemp);

		pMod=new Mod;
		if(pMod)
		{
			pMod->nAddr=nAddr;//获取配置文件中的卡件地址
			pMod->nFunction=nFunction;//获取配置文件中的MODBUS功能码
			pMod->nReg=nReg;//获取配置文件中的请求的寄存器数量
			pMod->nTimeOut=nTimeOut;//获取配置文件中的通讯超时时间
			m_arMod.push_back(pMod);//调用成员函数push_back()给各数组元素m_arMod[i]赋值  
  }                       
		}
		else
			return false;

	}
	return true;
}

void ModiDataBuf2(unsigned char *buf, long nLen)
{
	if(buf==NULL)
		return;
	
	if(nLen%4>0)
		return;

	unsigned char *buff=new unsigned char [nLen];
	memcpy(buff,buf,nLen);
	for(int i=0;i<nLen;i+=4)
	{
		memcpy(buf+i,buff+i+3,1);
		memcpy(buf+i+1,buff+i+2,1);
		memcpy(buf+i+2,buff+i+1,1);
		memcpy(buf+i+3,buff+i,1);

	}
	delete []buff;
}

⌨️ 快捷键说明

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