#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; }