在项目中遇到MCU(stm32)与上位机工具通过modbus传输数据,MCU中数据是小端存储,modbus数据默认是大端存储。所以在modbus通信时需要处理大小端对齐的问题。
1. MCU发送uint16数据的处理
/*Data是MCU需要发送的数据(小端存储),经过转化后发送给modbus*/
tPrjUInt16 Byte_exchange(tPrjUInt16 Data)
{
tPrjUInt8 Temp_data;
Temp_data= (tPrjUInt8)(Data>>8);
Data = (Data<<8)|Temp_data;
return(Data);
}
2.MCU发送float(32bit)数据的处理
modbus 一个保持寄存器是16bit,接收一个浮点数需要2个寄存器来存储。低地址的寄存器保存float数据的低16位,高地址寄存器保存float的高16bit。
方法一:
tPrjFloat32 Float_byte_exchange(tPrjFloat32 Data)
{
tPrjFloat32 bigEndianValue;
volatile char *littleEndianBytes = ( char *)&Data;
char *bigEndianBytes = ( char *)&bigEndianValue;
bigEndianBytes[0] = *(littleEndianBytes+1);
bigEndianBytes[1] = *(littleEndianBytes);
bigEndianBytes[2] = *(littleEndianBytes+3);
bigEndianBytes[3] = *(littleEndianBytes+2);
return bigEndianValue;
}
方法二:
先定义一个联合体:
/*联合体中数据公用同一段内存地址*/
/*浮点数与IEEE754格式转换*/
typedef union
{
float ul_Temp;
u8 uc_Buf[4];//小数转换成IEEE754格式的数组
u16 us_Buf[2];//用于modbus协议小数转换的数组
}un_DtformConver;
tPrjFloat32 Float_byte_exchange(tPrjFloat32 Data)
{
un_DtformConver unData;
unData.ul_Temp = Data;
tPrjFloat32 bigEndianValue;
unsigned char str[4] = {0};
str[0] = unData.uc_Buf[1];
str[1] = unData.uc_Buf[0];
str[2] = unData.uc_Buf[3];
str[3] = unData.uc_Buf[2];
bigEndianValue = *((float *)str);
return bigEndianValue;
}
或者用两个16bit的寄存器直接存放数据:
unit16 regBuf[num] ;//保持寄存器
void Float_To_U32(float value, u16 regaddr)
{
un_DtformConver Data;
Data.ul_Temp = value;//获取小数值
regBuf[regaddr] = Data.us_Buf[0];//获取低16位
regBuf[regaddr+1] = Data.us_Buf[1];//获取高16位
}
void Float_To_U32(float value, u16 regaddr)
{
un_DtformConver Data;
u16 us_temp = 0;
Data.ul_Temp = value;//获取小数值
regBuf[regaddr] = Data.uc_Buf[0]; //获取最低8位
us_temp = Data.uc_Buf[1];//获取8~15位
regBuf[regaddr] |= us_temp <<8;//低16位保存到保持寄存器中
regBuf[regaddr+1] = Data.uc_Buf[2];//获取16~23位
us_temp = Data.uc_Buf[3];//获取24~31位
regBuf[regaddr+1] |= us_temp <<8;//高16位保存到保持寄存器中
}