301 lines
6.7 KiB
C
301 lines
6.7 KiB
C
#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;
|
|
}
|