#include "proto_modbus_lib.h" #include "stdio.h" #include "string.h" #include "bsp_Uart.h" /************************************************** *名称: modbus_lib_crc16 *功能: modbus crc16校验 *参数: p_data -- 校验数据指针 * len -- 数据长度 *返回: 校验结果(小端序) **************************************************/ u16 modbus_lib_crc16(u8 *p_data, u16 len) { u16 crc16 = 0xffff; u16 i; while(len--) { crc16 = crc16^(*p_data++); for(i=0; i++<8; ) { if(crc16&0x0001) { crc16 = (crc16>>1)^0xa001; } else { crc16>>=1; } } } return crc16; } /************************************ * 函数: Float2u16 * 功能: 提取浮点数的高16或低16位 * 参数: float_data : 要转换的浮点数 h_l : 返回高16位还是低16位 * 返回: 返回对应的高16位还是低16位 * 描述: 无 ******************************************/ u16 float_to_u16(float float_data,unsigned char h_l) { u16 temp = 0XFFFF; if(h_l == U16_DATA_L) { temp = *((u32 *)&float_data) & 0x0000ffff; } else if(h_l == U16_DATA_H) { temp = ((*((u32 *)&float_data)) >> 16) & 0x0000ffff; } return temp; } /****************************************** * 函数: u32TOu16 * 功能: 提取u32的高16或低16位 * 参数: u32_data : 要转换的u32 h_l : 返回高16位还是低16位 * 返回: 返回对应的高16位还是低16位 * 描述: 无 ******************************************/ u16 u32_to_u16(u32 u32_data,unsigned char h_l) { u16 temp = 0XFFFF; if(h_l == U16_DATA_L) { temp = u32_data & 0x0000ffff; } else if(h_l == U16_DATA_H) { temp = (u32_data >> 16) & 0x0000ffff; } return temp; } void u32_to_u8(u32 u32_data,u8 *p_data,u8 endian) { if(BIG_ENDIAN == endian) { for(u8 i = 0;i < 4;i++) { p_data[i] = (u32_data >> (8 * (3 - i))) & 0xff; } } else if(LITTLE_ENDIAN == endian) { for(u8 i = 0;i < 4;i++) { p_data[i] = (u32_data >> (8 * i)) & 0xff; } } } void u16_to_u8(u16 u16_data,u8 *p_data,u8 endian) { if(BIG_ENDIAN == endian) { for(u8 i = 0;i < 2;i++) { p_data[i] = (u16_data >> (8 * (1 - i))) & 0xff; } } else if(LITTLE_ENDIAN == endian) { for(u8 i = 0;i < 2;i++) { p_data[i] = (u16_data >> (8 * i)) & 0xff; } } } float u32_to_float(u32 u32_data,unsigned char h_l) { float temp = 0; temp = *((float *)&u32_data); return temp; } /*将u8_endian端序的p_u8data转换为单片机对应的小端序*/ u32 u8_to_u32(u8 *p_u8data,unsigned char u8_endian) { u32 temp = 0; if(BIG_ENDIAN == u8_endian) { for(u8 i = 0;i < 4;i++) { temp |= p_u8data[i] << ((3 - i) * 8); } } else if(LITTLE_ENDIAN == u8_endian) { for(u8 i = 0;i < 4;i++) { temp |= p_u8data[i] << (i * 8); } } return temp; } /*将u8_endian端序的p_u8data转换为单片机对应的小端序*/ u16 u8_to_u16(u8 *p_u8data,unsigned char u8_endian) { u32 temp = 0; if(BIG_ENDIAN == u8_endian) { for(u8 i = 0;i < 2;i++) { temp |= p_u8data[i] << ((1 - i) * 8); } } else if(LITTLE_ENDIAN == u8_endian) { for(u8 i = 0;i < 2;i++) { temp |= p_u8data[i] << (i * 8); } } return temp; } /*字节端序转换*/ u32 u32_endian_conv(u32 data) { u32 temp = 0; temp = (((data >> 0 ) & 0xff) << 24) | (((data >> 8 ) & 0xff) << 16) | (((data >> 16) & 0xff) << 8 ) | (((data >> 24) & 0xff) << 0 ); return temp; } /*字节端序转换*/ u16 u16_endian_conv(u16 data) { u16 temp = 0; temp = (((data >> 0) & 0xff) << 8) | (((data >> 8) & 0xff) << 0); return temp; } /****************************************** * 函数: ModbusReaddata * 功能: MODBUS读数据 * 参数: Id :MODBUS从机地址 * addr :写数据的起始地址 * Num :写的寄存器数量 * send :串口发送函数 * 返回: 无 * 描述: 无 ******************************************/ void modbus_lib_data_read(u8 id,u16 addr,u16 num,void (*send)(u8 *,u16 )) { u8 tx[8]; u16 crc16; tx[0] = id; tx[1] = 0x41;//0x03; tx[2] = (addr >> 8) & 0xff; tx[3] = addr & 0xff; tx[4] = (num >> 8) & 0xff; tx[5] = num & 0xff; crc16 = modbus_lib_crc16(tx,6); tx[6] = crc16 & 0xff; tx[7] = (crc16 >> 8) & 0xff; send(tx,8); } /****************************************** * 函数: modbus_multiple_data_write * 功能: MODBUS写数据 * 参数: Id :MODBUS从机地址 * addr :写数据的起始地址 * Num :写的寄存器数量 * data :写的数据 * send :串口发送函数 * 返回: 无 * 描述: 无 ******************************************/ void modbus_lib_multiple_data_write(u8 id,u16 addr,u16 Num,u16 *data,void (*send)(u8 *,u16 )) { u8 tx[50]; u16 crc16,i; 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 = modbus_lib_crc16(tx,7 + 2 * i); tx[7 + 2 * i] = crc16 & 0xff; tx[8 + 2 * i] = (crc16 >> 8) & 0xff; send(tx,9 + 2 * i); } void modbus_lib_only_data_write(u8 id,u16 addr,u16 value,void (*send)(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 = modbus_lib_crc16(tx,6); tx[6] = crc16 & 0xff; tx[7] = (crc16 >> 8) & 0xff; send(tx,8); } //01 10 00 02 00 01 02 12 34 CRC //id Func Startaddress RegNumber wdataaddress u8 modbus_lib_analysis(modbus_analysis_data_t *p_modbus, u8 *p_data, u16 len) { u16 crc16; u16 u16_temp; if(NULL == p_modbus) return 0; if(len < 8) return 0; crc16 = modbus_lib_crc16(p_data, len-2); u16_temp = *(p_data+len-1); u16_temp <<= 8; u16_temp |= *(p_data+len-2); if(u16_temp != crc16) return 0; p_modbus->id = *p_data; p_modbus->func = *(p_data+1); p_modbus->start_addr = (*(p_data+2))<<8; p_modbus->start_addr |= *(p_data+3); /*单独写一个寄存器*/ if(0x06 == p_modbus->func) { p_modbus->write_data_addr = p_data+4; } else if(0x10 == p_modbus->func) /*写多个寄存器*/ { p_modbus->reg_number = (*(p_data+4))<<8; p_modbus->reg_number |= *(p_data+5); p_modbus->write_data_addr = p_data+7; } else { p_modbus->reg_number = (*(p_data+4))<<8; p_modbus->reg_number |= *(p_data+5); } return 1; }