Modbus通信时数据接收和发布的处理

在项目中遇到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位保存到保持寄存器中
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值