📄 sim.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 + -