Files
secs2-bootloader/usr/protocol/proto_Modbus.c

295 lines
6.4 KiB
C

#include "proto_Modbus.h"
#include "stdio.h"
#include "string.h"
#include "bsp_Uart.h"
u16 ModbusCrc16(u8 *pData, u16 Len)
{
u16 CRC_16 = 0xffff;
u16 i;
while(Len--)
{
CRC_16 = CRC_16^(*pData++);
for(i=0; i++<8; )
{
if(CRC_16&0x0001)
{
CRC_16 = (CRC_16>>1)^0xa001;
}
else
{
CRC_16>>=1;
}
}
}
return CRC_16;
}
/******************************************
* 函数: Float2u16
* 功能: 提取浮点数的高16或低16位
* 参数: FloatData : 要转换的浮点数
HorL : 返回高16位还是低16位
* 返回: 返回对应的高16位还是低16位
* 描述: 无
******************************************/
u16 FloatTOu16(float FloatData,u8 HorL)
{
u16 Temp = 0XFFFF;
if(HorL == U16_DATA_L)
{
Temp = *((u32 *)&FloatData) & 0x0000ffff;
}
else if(HorL == U16_DATA_H)
{
Temp = ((*((u32 *)&FloatData)) >> 16) & 0x0000ffff;
}
return Temp;
}
/******************************************
* 函数: u32TOu16
* 功能: 提取u32的高16或低16位
* 参数: u32Data : 要转换的u32
HorL : 返回高16位还是低16位
* 返回: 返回对应的高16位还是低16位
* 描述: 无
******************************************/
u16 u32TOu16(u32 u32Data,u8 HorL)
{
u16 Temp = 0XFFFF;
if(HorL == U16_DATA_L)
{
Temp = u32Data & 0x0000ffff;
}
else if(HorL == U16_DATA_H)
{
Temp = (u32Data >> 16) & 0x0000ffff;
}
return Temp;
}
void u32TOu8(u32 u32Data,u8 *pData,u8 Endian)
{
if(BIG_ENDIAN == Endian)
{
for(u8 i = 0;i < 4;i++)
{
pData[i] = (u32Data >> (8 * (3 - i))) & 0xff;
}
}
else if(LITTLE_ENDIAN == Endian)
{
for(u8 i = 0;i < 4;i++)
{
pData[i] = (u32Data >> (8 * i)) & 0xff;
}
}
}
void u16TOu8(u16 u16Data,u8 *pData,u8 Endian)
{
if(BIG_ENDIAN == Endian)
{
for(u8 i = 0;i < 2;i++)
{
pData[i] = (u16Data >> (8 * (1 - i))) & 0xff;
}
}
else if(LITTLE_ENDIAN == Endian)
{
for(u8 i = 0;i < 2;i++)
{
pData[i] = (u16Data >> (8 * i)) & 0xff;
}
}
}
float u32TOFloat(u32 u32Data,u8 HorL)
{
float Temp = 0;
Temp = *((float *)&u32Data);
return Temp;
}
/*将u8Endian端序的p_u8Data转换为单片机对应的小端序*/
u32 u8TOu32(u8 *p_u8Data,u8 u8Endian)
{
u32 Temp = 0;
if(BIG_ENDIAN == u8Endian)
{
for(u8 i = 0;i < 4;i++)
{
Temp |= p_u8Data[i] << ((3 - i) * 8);
}
}
else if(LITTLE_ENDIAN == u8Endian)
{
for(u8 i = 0;i < 4;i++)
{
Temp |= p_u8Data[i] << (i * 8);
}
}
return Temp;
}
/*将u8Endian端序的p_u8Data转换为单片机对应的小端序*/
u16 u8TOu16(u8 *p_u8Data,u8 u8Endian)
{
u32 Temp = 0;
if(BIG_ENDIAN == u8Endian)
{
for(u8 i = 0;i < 2;i++)
{
Temp |= p_u8Data[i] << ((1 - i) * 8);
}
}
else if(LITTLE_ENDIAN == u8Endian)
{
for(u8 i = 0;i < 2;i++)
{
Temp |= p_u8Data[i] << (i * 8);
}
}
return Temp;
}
/*字节端序转换*/
u32 u32_EndianConv(u32 Data)
{
u32 TempData = 0;
TempData = (((Data >> 0 ) & 0xff) << 24)
| (((Data >> 8 ) & 0xff) << 16)
| (((Data >> 16) & 0xff) << 8 )
| (((Data >> 24) & 0xff) << 0 );
return TempData;
}
/*字节端序转换*/
u16 u16_EndianConv(u16 Data)
{
u16 TempData = 0;
TempData = (((Data >> 0) & 0xff) << 8)
| (((Data >> 8) & 0xff) << 0);
return TempData;
}
/******************************************
* 函数: ModbusReadData
* 功能: MODBUS读数据
* 参数: Id :MODBUS从机地址
* Addr :写数据的起始地址
* Num :写的寄存器数量
* UsartSendBuffer :串口发送函数
* 返回: 无
* 描述: 无
******************************************/
void ModbusReadData(u8 Id,u16 Addr,u16 Num,void (*UsartSendBuffer)(u8 *,u16 ))
{
u8 Tx[8];
u16 CRC16;
Tx[0] = Id;
Tx[1] = 0x03;
Tx[2] = (Addr >> 8) & 0xff;
Tx[3] = Addr & 0xff;
Tx[4] = (Num >> 8) & 0xff;
Tx[5] = Num & 0xff;
CRC16 = ModbusCrc16(Tx,6);
Tx[6] = CRC16 & 0xff;
Tx[7] = (CRC16 >> 8) & 0xff;
UsartSendBuffer(Tx,8);
}
/******************************************
* 函数: ModbusWriteMultipleData
* 功能: MODBUS写数据
* 参数: Id :MODBUS从机地址
* Addr :写数据的起始地址
* Num :写的寄存器数量
* Data :写的数据
* UsartSendBuffer :串口发送函数
* 返回: 无
* 描述: 无
******************************************/
void ModbusWriteMultipleData(u8 ID,u16 Addr,u16 Num,u16 *Data,void (*UsartSendBuffer)(u8 *,u16 ))
{
u8 Tx[50],i;
u16 CRC16;
Tx[0] = ID;
Tx[1] = 0x10;
Tx[2] = (Addr >> 8) & 0xff;
Tx[3] = Addr & 0xff;
Tx[4] = (Num >> 8) & 0xff;
Tx[5] = Num & 0xff;
Tx[6] = Num * 2;
for(i = 0;i < Tx[6]/2;i++)
{
Tx[7 + 2 * i] = (Data[i] >> 8) & 0xff;
Tx[8 + 2 * i] = Data[i] & 0xff;
}
CRC16 = ModbusCrc16(Tx,7 + 2 * i);
Tx[7 + 2 * i] = CRC16 & 0xff;
Tx[8 + 2 * i] = (CRC16 >> 8) & 0xff;
UsartSendBuffer(Tx,9 + 2 * i);
}
void ModbusyWriteOnlData(u8 ID,u16 Addr,u16 Value,void (*UsartSendBuffer)(u8 *,u16 ))
{
u8 Tx[8];
u16 CRC16;
Tx[0] = ID;
Tx[1] = 0x06;
Tx[2] = (Addr >> 8) & 0xff;
Tx[3] = Addr & 0xff;
Tx[4] = (Value >> 8) & 0xff;
Tx[5] = Value & 0xff;
CRC16 = ModbusCrc16(Tx,6);
Tx[6] = CRC16 & 0xff;
Tx[7] = (CRC16 >> 8) & 0xff;
UsartSendBuffer(Tx,8);
}
//01 10 00 02 00 01 02 12 34 CRC
//ID Func StartAddress RegNumber wDataAddress
u8 ModbusAnalysis(ModbusAnalysisData_t *pModbus, u8 *pData, u16 len)
{
u16 CRC_16;
u16 TempU16;
if(NULL == pModbus) return 0;
if(len < 8) return 0;
CRC_16 = ModbusCrc16(pData, len-2);
TempU16 = *(pData+len-1);
TempU16 <<= 8;
TempU16 |= *(pData+len-2);
if(TempU16 != CRC_16) return 0;
pModbus->ID = *pData;
pModbus->Func = *(pData+1);
pModbus->StartAddress = (*(pData+2))<<8;
pModbus->StartAddress |= *(pData+3);
/*单独写一个寄存器*/
if(0x06 == pModbus->Func)
{
pModbus->wDataAddress = pData+4;
}
else if(0x10 == pModbus->Func) /*写多个寄存器*/
{
pModbus->RegNumber = (*(pData+4))<<8;
pModbus->RegNumber |= *(pData+5);
pModbus->wDataAddress = pData+7;
}
else
{
pModbus->RegNumber = (*(pData+4))<<8;
pModbus->RegNumber |= *(pData+5);
}
return 1;
}