Files
CHJ/user/Protocol/MODBUS.c
2026-03-20 21:19:53 +08:00

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();
}