295 lines
6.4 KiB
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;
|
|
}
|