modbus协议通信时浮点数如何发送和接收处理的解决办法

modbus协议通信时浮点数如何发送和接收处理的解决办法

  在本次做项目的时候,发现需要威纶通屏幕与stm32芯片采用modbus通信,很多时候需要处理float小数。最开始一直在纠结大小端的问题,坑了一天,理出了下面的解决办法。
  注意:主机发送给从机的小数是以32位的形式发送的,所以会占用2个保持寄存器。并且本次项目的威纶通屏幕作为主机时,在发送IEEE754格式的小数时,第一个保持寄存器存放的是小数的低16位,第二个保持寄存器存放的是小数的高16位。

小数转换步骤:
1、威纶通屏幕作为主机在发送浮点数时,是以IEEE754格式发送数据,需要用到2个保持寄存器,第一个保持寄存器存放小数的低16位,第二个保持寄存器存放小数的高16位
2、在从机保持寄存器接收到小数后,需要将数据按小端格式放入一个4字节的空间中,即低地址存放低字节,高地址存放高字节
3、获取小数的4个字节空间的首地址,得到小数值


一、如何将保持寄存器中存放的IEEE754格式的小数转换成float类型

一、方法1.0
此方法是采用1个4字节的u8类型的数组,去转换主机发给从机的小数。在stm32中小数存储方式是以小端模式存放:低地址存放低字节,高地址存放高字节。

/*
函数功能:将从机保持寄存器的值转换成对应小数
函数参数: HoldAddr ----从机保持寄存器接收到的小数存放的起始地址*/
float  DataConvertFloat(u16 HoldAddr)
{
    u8 str[4];
    float temp;
	str[0] = (u8 )(usSRegHoldBuf[HoldAddr]&0xff);//得到保持寄存器HoldAddr的低8位,也就是小数的0~7位
	str[1] = (u8 )(usSRegHoldBuf[HoldAddr]>>8);	//得到保持寄存器HoldAddr的高8位,也就是小数的8~15位
	str[2] = (u8 )(usSRegHoldBuf[HoldAddr+1]&0xff);//得到保持寄存器(HoldAddr+1)的低8位,也就是小数的16~23位
	str[3]= (u8 )(usSRegHoldBuf[HoldAddr+1]>>8);//得到保持寄存(HoldAddr+1)的高8位,也就是小数的24`31位
	temp = *((float *)str);//得到小数,	
	return temp;
}

/*此处有用到保持寄存器的数组usSRegHoldBuf,这个我项目由于要多次使用到,我已经把
这个保持寄存器定义为了全局变量*/
#define S_REG_HOLDING_NREGS           500 //保持寄存器数量
USHORT  usSRegHoldBuf[S_REG_HOLDING_NREGS] ;//保持寄存器 

二、方法1.1
定义一个内联类型的变量,此内联类型比较特殊

/*浮点数与IEEE754格式转换*/
typedef union                                        
{
   float ul_Temp;
   u8  uc_Buf[4];//小数转换成IEEE754格式的数组
   u16 us_Buf[2];//用于modbus协议小数转换的数组
}un_DtformConver; 

//此方式和1.0其实差不多,不过这个方式可以运用到的别的小数转换成IEEE754的场合
float DataConvertFloat(u16 HoldAddr)
{
	 un_DtformConver  Data;
	 float temp;
	 Data.uc_Buf[0] = (u8 )(usSRegHoldBuf[HoldAddr]&0xff);//得到保持寄存器HoldAddr的低8位
	 Data.uc_Buf[1] = (u8 )(usSRegHoldBuf[HoldAddr]>>8);//得到保持寄存器HoldAddr的高8位
	 Data.uc_Buf[2] = (u8 )(usSRegHoldBuf[HoldAddr+1]&0xff);//保持寄存器(HoldAddr+1)的低8位
	 Data.uc_Buf[3]= (u8 )(usSRegHoldBuf[HoldAddr+1]>>8);//保持寄存器(HoldAddr+1)的高8位
	 temp = Data.ul_Temp;//得到小数
	 return temp;
}

三、方法1.3

float DataConvertFloat(u16 HoldAddr)
{
	un_DtformConver Data;
	float temp;
	Data.us_Buf[0] = usSRegHoldBuf[HoldAddr];//获取从机接收到的小数的低16位
	Data.us_Buf[1] = usSRegHoldBuf[HoldAddr+1];//获取从机接收到的小数的高16位
	temp = Data.ul_Temp;//得到小数
	return temp;
}

四、方法1.4

float DataConvertFloat(u16 HoldAddr)
{
	float temp;
	temp = *((float *)&usSRegHoldBuf[HoldAddr]);//直接获取地址转换就可以了,因为usSRegHoldBuf[HoldAddr+1]存放的正好是小数的高16位,满足stm32的小端模式
	return temp;
}


二、如何将float类型的小数转换成IEEE754格式放入到从机的保持寄存器中

/*
函数功能:将小数转换成IEEE754数据类型,用于modbus协议传输数据
函数参数:value 小数值    Holdaddr 从机保持寄存器地址
*/
//方式1.0
void Float_To_U32(float value, u16 Holdaddr)
{
	un_DtformConver Data;
	Data.ul_Temp = value;//获取小数值
	usSRegHoldBuf[Holdaddr] = Data.us_Buf[0];//获取低16位
	usSRegHoldBuf[Holdaddr+1] = Data.us_Buf[1];//获取高16位
}

//方式1.1
void Float_To_U32(float value, u16 Holdaddr)
{
	un_DtformConver Data;
	u16 us_temp = 0;
	Data.ul_Temp = value;//获取小数值
	usSRegHoldBuf[Holdaddr] = Data.uc_Buf[0]; //获取最低8位
	us_temp = Data.uc_Buf[1];//获取8~15位
	usSRegHoldBuf[Holdaddr] |= us_temp <<8;//低16位保存到保持寄存器中
	
    usSRegHoldBuf[Holdaddr+1] = Data.uc_Buf[2];//获取16~23位
    us_temp = Data.uc_Buf[3];//获取24~31位
    usSRegHoldBuf[Holdaddr+1] |= us_temp <<8;//高16位保存到保持寄存器中
}
  • 13
    点赞
  • 98
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值