191 lines
6.0 KiB
C
191 lines
6.0 KiB
C
#include "../main/SystemInclude.h"
|
|
|
|
u8 isOldProtocol;
|
|
|
|
__MB_Buf_TypeDef MBBuf;
|
|
/******************************************************************************/
|
|
u16 ModBusCRC(u8 *Data_Array , u8 DataLength) //获取CRC
|
|
{
|
|
u32 i, j;
|
|
u16 CRCTemp;
|
|
|
|
CRCTemp = 0xffff;
|
|
for(i = 0; i<=DataLength; i++)
|
|
{
|
|
CRCTemp = CRCTemp ^ Data_Array[i];
|
|
for(j=0; j<=7; j++)
|
|
{
|
|
if((CRCTemp & 0x0001)==0x0001)
|
|
{
|
|
CRCTemp >>= 1;
|
|
CRCTemp ^= 0xa001;
|
|
}
|
|
else CRCTemp >>= 1;
|
|
}
|
|
}
|
|
|
|
return CRCTemp;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
void ComputeTxdDataCRC(void)
|
|
{
|
|
tempL.Word[0] = ModBusCRC(MBBuf.RxPointer, MBBuf.TxdLen-2); //计算CRC
|
|
MBBuf.RxPointer[MBBuf.TxdLen] = tempL.Byte[1];
|
|
MBBuf.RxPointer[MBBuf.TxdLen-1] = tempL.Byte[0];
|
|
MBBuf.TxdLen++;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
void ModBusErrorInfo(u8 ErrorCode)
|
|
{
|
|
MBBuf.RxPointer[1] |= 0x80; //返回执行错误
|
|
MBBuf.RxPointer[2] = 1; //字节长度1
|
|
MBBuf.RxPointer[3] = ErrorCode; //返回详细错误代码:功能码错误 本设备不支持此功能
|
|
MBBuf.TxdLen = 5;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
void ModBusReadMultiByte(void)
|
|
{
|
|
if(MBBuf.StartAddr < INT_PARAMETER_PROTOCOL) UserReadDataProtocol();
|
|
else InternalReadParameterProtocol();
|
|
}
|
|
|
|
/******************************************************************************/
|
|
void ModBusWriteMultiByte(void)
|
|
{
|
|
if(MBBuf.StartAddr < INT_PARAMETER_PROTOCOL) UserWriteDataProtocol();
|
|
else InternalWriteParameterProtocol();
|
|
}
|
|
|
|
/******************************************************************************/
|
|
//ModBus数据处理
|
|
void ModBusDataProcessing(void)
|
|
{
|
|
MBBuf.BusError = 0;
|
|
switch(MBBuf.RxPointer[1])
|
|
{
|
|
case READ_HOLDING_REGISTERS: //0x03 读取保持寄存器---------------------------------------------
|
|
MBBuf.StartAddr = ((u16)MBBuf.RxPointer[2] << 8) | (u16)MBBuf.RxPointer[3];
|
|
MBBuf.ByteNumber = ((u16)MBBuf.RxPointer[4] << 8) | (u16)MBBuf.RxPointer[5];
|
|
|
|
if(MBBuf.ByteNumber > ENABLE_REG_MAX) {
|
|
MBBuf.BusError = SLAVE_DEVICE_FAILURE;
|
|
break;
|
|
}
|
|
MBBuf.ByteNumber <<= 1;
|
|
MBBuf.TxdLen = MBBuf.ByteNumber;
|
|
MBBuf.RxPointer[2] = MBBuf.TxdLen;//返回数据的字节数
|
|
MBBuf.TxdLen += 4;
|
|
MBBuf.Index = 3;
|
|
ModBusReadMultiByte();//读操作
|
|
break;
|
|
|
|
case PRESET_SINGLE_REGISTER: //0x06 写预置单寄存器---------------------------------------------
|
|
MBBuf.StartAddr = MBBuf.StartAddr = ((u16)MBBuf.RxPointer[2] << 8) | (u16)MBBuf.RxPointer[3];
|
|
MBBuf.EndAddr = MBBuf.StartAddr + 1;
|
|
MBBuf.TxdLen = 7;
|
|
MBBuf.ByteNumber = 2;
|
|
MBBuf.Index = 4; // 接收到的数据有效起始
|
|
ModBusWriteMultiByte();//写操作
|
|
break;
|
|
|
|
case PRESET_MULTIPLE_REGISTERS : //0x010 写预置多寄存器----------------------------------------
|
|
//if(RxdIndex < 11) return;
|
|
MBBuf.StartAddr = ((u16)MBBuf.RxPointer[2] << 8) | (u16)MBBuf.RxPointer[3];
|
|
MBBuf.ByteNumber = ((u16)MBBuf.RxPointer[4] << 8) | (u16)MBBuf.RxPointer[5];
|
|
if(MBBuf.ByteNumber > ENABLE_REG_MAX) {
|
|
MBBuf.BusError = SLAVE_DEVICE_FAILURE;
|
|
break;
|
|
}
|
|
MBBuf.EndAddr = MBBuf.StartAddr + MBBuf.ByteNumber;
|
|
MBBuf.ByteNumber <<= 1;
|
|
//准备返回数据
|
|
MBBuf.RxPointer[1] = 0x10;
|
|
MBBuf.TxdLen = 7;
|
|
MBBuf.Index = 7;
|
|
ModBusWriteMultiByte();//写操作
|
|
break;
|
|
|
|
case ERROR_TEST : //0x08 错误诊断-------------------------------------------------------------
|
|
if (MBBuf.RxPointer[0] != 0x00) //如果不是广播地址 则回复 否则静默
|
|
break;
|
|
|
|
default: //功能码未识别-----------------------------------------------------------------------
|
|
MBBuf.BusError = ILLEGAL_FUNCTION;
|
|
break;
|
|
}
|
|
|
|
if(MBBuf.BusError != 0) ModBusErrorInfo(MBBuf.BusError);
|
|
//广播地址 静默
|
|
if(MBBuf.RxPointer[0] == 0x00) {
|
|
MBBuf.TxdLen = 0;
|
|
return;
|
|
}
|
|
|
|
if(MBBuf.TxdLen == 0) return;
|
|
ComputeTxdDataCRC();
|
|
memmove( (char *)MBBuf.TxPointer, (char *)MBBuf.RxPointer, MBBuf.TxdLen);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
//检测是否符合Modbus协议帧
|
|
u8 ModBusProtocolDetection(void)
|
|
{
|
|
u16 CRCTempRX, CRCTempCX;
|
|
|
|
MBBuf.TxdLen = 0;
|
|
if(MBBuf.RxdLen < 5) return 0;
|
|
// 判断地址是否错误
|
|
if(MBBuf.RxPointer[0] == localAddress) goto DetecteNext;
|
|
else if(MBBuf.RxPointer[0] == 0) goto DetecteNext;
|
|
else return 0;
|
|
|
|
DetecteNext:
|
|
//tempL.Byte[1] = MBBuf.RxPointer[MBBuf.RxdLen-1];
|
|
//tempL.Byte[0] = MBBuf.RxPointer[MBBuf.RxdLen-2];
|
|
//CRCTempRX = tempL.Word[0];
|
|
CRCTempRX = ((u16)MBBuf.RxPointer[MBBuf.RxdLen-1] << 8) | (u16)MBBuf.RxPointer[MBBuf.RxdLen-2];
|
|
CRCTempCX = ModBusCRC(MBBuf.RxPointer, MBBuf.RxdLen-3); // 计算CRC
|
|
if(CRCTempRX != CRCTempCX) return 0; // CRC错误
|
|
else return 1;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
//Modbus变量指针处理
|
|
u8 ModbusVariablePointerProcess(void)
|
|
{
|
|
if(MBBuf.ByteNumber >= MBBuf.DataByte) MBBuf.ByteNumber -= MBBuf.DataByte;
|
|
else return 1;
|
|
|
|
if(MBBuf.ByteNumber < 2) return 1;
|
|
|
|
MBBuf.DataByte >>= 1;
|
|
MBBuf.StartAddr += MBBuf.DataByte;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
u8 ModbusVariablePointerDec(void)
|
|
{
|
|
if(MBBuf.ByteNumber < MBBuf.DataByte + 2) {
|
|
MBBuf.ByteNumber = 0;
|
|
return 1;
|
|
}
|
|
|
|
MBBuf.ByteNumber -= MBBuf.DataByte;
|
|
MBBuf.DataByte >>= 1;
|
|
MBBuf.StartAddr += MBBuf.DataByte;
|
|
return 0;
|
|
}
|
|
|
|
///******************************************************************************/
|
|
void CopyDataAndJudgeComplete(void)
|
|
{
|
|
u32 I;
|
|
for(I=1; I<= MBBuf.DataByte; I++) MBBuf.RxPointer[MBBuf.Index++] = tempL.Byte[MBBuf.DataByte-I];
|
|
|
|
ModbusVariablePointerDec();
|
|
} |