// ModBus.cpp: implementation of the CModBus class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ModBus.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: LRC------纵向异或校验
//----------------------------------------------------
//参数: const CString& strTxt-------------字符串
//----------------------------------------------------
//功能:纵向异或校验
//----------------------------------------------------
//返回值:
// 校验码(1个 char)
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
unsigned char CModBus::LRC(const unsigned char *pucChar, unsigned int unLen)
{
//在ASCII协议中使用,检测了消息域中除开始的冒号及结束的回车换行号外的内容。
//它仅仅是把每一个需要传输的数据按字节叠加后取反加1即可
unsigned char ucLRC=0;
if(0!=unLen%2)
return 0;
BYTE byLRC = 0;
char pBuf[4];
pBuf [2] = '\0';
int nData = 0;
for(unsigned int i=0; i<unLen; i+=2)
{
//每两个需要发送的ASCII码转化为一个十六进制数
pBuf [0] = pucChar[i];
pBuf [1] = pucChar[i+1];
// pBuf [2] = '\0';
sscanf(pBuf,"%x",& nData);
byLRC += nData;
}
byLRC = ~ byLRC;
byLRC ++;
return byLRC;
}
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: CRC16------循环容余校验
//----------------------------------------------------
//参数: unsigned char *pucChar-------------接收到的字符
//----------------------------------------------------
//功能: 循环容余校验
//----------------------------------------------------
//返回值:
// 校验码
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
unsigned short CModBus::CRC16(const unsigned char *pucChar, unsigned int unLen)
{
unsigned short usItem=0xA001;
unsigned short usCRCReg=0xFFFF;
unsigned char ucChar;
for(unsigned int i=0;i<unLen;i++)
{
ucChar=*(pucChar+i);
usCRCReg^=ucChar;
for(int j=0;j<8;j++)
{
bool bLSB=((usCRCReg & 0x0001)== 0x0001);
usCRCReg=usCRCReg>>1;
if(bLSB)
{
usCRCReg^=usItem;
}
}
}
return usCRCReg;
// unsigned char uchCRCHi=0xFF;
// unsigned char uchCRCLo=0xFF;
// unsigned uIndex;
//
// while(unLen--)
// {
// uIndex=uchCRCLo^*pucChar++; //calculate the CRC
// uchCRCLo=uchCRCHi^auchCRCHi[uIndex];
// uchCRCHi=auchCRCLo[uIndex];
// }
// return(uchCRCHi<<8|uchCRCLo);
}
//Table of CRC Value for high-order byte
//unsigned char CModBus::auchCRCHi[]={
// 1 2 3 4 5 6 7 8 9
// 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01
//};
//Table of CRC value for low-order byte
//unsigned char CModBus::auchCRCLo[]={
// 0x00,0xC0,0xC1,0x01
//};
CModBus::CModBus()
{
m_strPrtName="ModBus";
m_unRLen=500; //将要接收字符长度
m_unNowRLen=0; //已经接收字符长度
m_bFrameMode=MODBUS_RTU; //
}
CModBus::~CModBus()
{
}
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Error------错误提示
//----------------------------------------------------
//参数: int nError-------------错误代码
// int nFunctionCode------功能代码
// int nRegAddr-----------寄存器地址
//----------------------------------------------------
//功能: 错误代码提示
//----------------------------------------------------
//返回值:
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void CModBus::Error(int nError,int nFunctionCode,int nRegAddr)
{
CString strErrTip;
switch(nError)
{
case 0x01:
strErrTip.Format("从机接收到的功能是不允许的。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);
break;
case 0x02:
strErrTip.Format("查询中的数据地址对于从机来说是非法的。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);
break;
case 0x03:
strErrTip.Format("查询中数据域的数值不是从机所允许的。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);
break;
case 0x04:
strErrTip.Format("当从机试图进行所要求的动作时,发生了一个不可恢复的错误。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);
break;
case 0x05:
strErrTip.Format("从机已接受查询,正在进行处理,但需要持续较长的时间。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);
break;
case 0x06:
strErrTip.Format("从机正在处理一个持续时间比较长的指令。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);
break;
case 0x07:
strErrTip.Format("从机不能完成查询中的功能要求。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);
break;
case 0x08:
strErrTip.Format("从机试图阅读扩展存储器,但在存储器中发现奇偶校验错误。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);
break;
default:
strErrTip.Format("不可知的错误。\n\t功能:%d\t寄存器地址:%d",nFunctionCode,nRegAddr);
}
throw(strErrTip);
}
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: ReceiveByte------接收字符
//----------------------------------------------------
//参数: unsigned char& ch-------------接收到的字符
//----------------------------------------------------
//功能: 接收字符处理
//----------------------------------------------------
//返回值:
// 0------正在接收记录
// 1------字符接收完毕
// 2------要求重发送一次
// 3------校验错误,要求重发一次
// 4------没有数据处理
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
int CModBus::ReceiveByte(unsigned char& ch)
{
if (NULL==m_pComData)
return 4; //数据为空
//--------------------------------------------------
m_ucRData[m_unNowRLen++]=ch;
if(MODBUS_RTU==m_bFrameMode)
return ReceiveByte_RTU(ch);
else //ASCII
{
return ReceiveByte_ASCII(ch);
}
}
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Transform------转换成十进制、十六进制、二进制
//----------------------------------------------------
//参数: unsigned char &pChar-------------数据数组
// unsigned int unLen---------------数据长度
// unsigned int unType--------------将要转换的类型1:整形;2:十六进制;3:二进制位
//----------------------------------------------------
//功能: 对发送数据进行译码
//----------------------------------------------------
//返回值:
// NULL
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//DEL CString CModBus::Transform(const unsigned char* pChar, unsigned int unLen, unsigned int unType)
//DEL {
//DEL CString strTxt;
//DEL switch(unType)
//DEL {
//DEL case 1:
//DEL {
//DEL strTxt.Empty ();
//DEL for(unsigned int nIndex=0;nIndex<unLen;nIndex++)
//DEL strTxt+=(char*)pChar[nIndex];
//DEL break;
//DEL }
//DEL case 2:
//DEL {
//DEL strTxt.Empty ();
//DEL for(unsigned int nIndex=0;nIndex<unLen;nIndex++)
//DEL strTxt+=(char*)pChar[nIndex];
//DEL int nNum=atoi(strTxt);
//DEL strTxt.Format ("%x",nNum);
//DEL strTxt.MakeUpper ();
//DEL if(strTxt.GetLength ()==1)
//DEL {
//DEL strTxt.Insert (0,"0");
//DEL }
//DEL
//DEL break;
//DEL }
//DEL case 3:
//DEL {
//DEL for(unsigned int i=0;i<unLen;i++)
//DEL {
//DEL unsigned char ch=*(pChar+i);
//DEL for(unsigned int j=0;j<8;j++)
//DEL {
//DEL bool bBit=((ch>>i & 0x0001)== 0x0001);
//DEL if(bBit)
//DEL strTxt+="1";
//DEL else
//DEL strTxt+="0";
//DEL }
//DEL }
//DEL break;
//DEL }
//DEL }
//DEL
//DEL return strTxt;
//DEL }
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//名称: Decoding------译码
//----------------------------------
- 1
- 2
- 3
- 4
- 5
- 6
前往页