浮点数的储存格式与STM32的串口传输

浮点数的储存形式

1. 浮点数的二进制表示

举个例子:4.25
在这个浮点数中:4-整数部分,0.25-小数部分
在这里插入图片描述
整数部分-直接转换成二进制,即4表示为 ( 100 ) 2 (100)_2 (100)2
小数部分-将小数部分乘以2,取小数点前一位作为二进制的高位,对小数点后的部分执行相同的步骤,直到它变成1.0;

0.25 *2=0.50
0.5 *2=1.00
0.25= ( 01 ) 2 (01)_2 (01)2

将整数和小数部分结合到一起:
4.25= ( 100.01 ) 2 (100.01)_2 (100.01)2

2. 浮点数的二进制储存

这里说明单精度浮点数(float)的储存格式:
根据 IEEE 754的标准,将32bin的浮点数划分为:
符号位:1位
指数位:8位
有效数字位:24位(23位显式储存)

符号位决定了数据的符号;
指数位是一个从 0 到 255 的 8 位无符号整数。指数值 127 代表实际零,-127代表0;
有效数字包括二进制小数点右侧的 23 个小数位和值为1的隐式前导位。

其具体储存格式如下:
在这里插入图片描述
 value  = ( − 1 ) sign  × 2 ( E − 127 ) × ( 1 + ∑ i = 1 23 b 23 − i 2 − i ) \text { value }=(-1)^{\text {sign }} \times 2^{(E-127)} \times\left(1+\sum_{i=1}^{23} b_{23-i} 2^{-i}\right)  value =(1)sign ×2(E127)×(1+i=123b23i2i)
其中:
sign ⁡ = b 31 = 0 ( − 1 ) sign ⁡ = ( − 1 ) 0 = + 1 E = b 30 b 29 … b 23 = ∑ i = 0 7 b 23 + i 2 + i = 124 2 ( E − 127 ) = 2 124 − 127 = 2 − 3 1. b 22 b 21 … b 0 = 1 + ∑ i = 1 23 b 23 − i 2 − i = 1 + 1 ⋅ 2 − 2 = 1.25 \begin{aligned} &\operatorname{sign}=b_{31}=0 \\ &(-1)^{\operatorname{sign}}=(-1)^{0}=+1 \\ &E=b_{30} b_{29} \ldots b_{23}=\sum_{i=0}^{7} b_{23+i} 2^{+i}=124\\ &2^{(E-127)}=2^{124-127}=2^{-3}\\ &1 . b_{22} b_{21} \ldots b_{0}=1+\sum_{i=1}^{23} b_{23-i} 2^{-i}=1+1 \cdot 2^{-2}=1.25 \end{aligned} sign=b31=0(1)sign=(1)0=+1E=b30b29b23=i=07b23+i2+i=1242(E127)=2124127=231.b22b21b0=1+i=123b23i2i=1+122=1.25
因此:
 value  = ( + 1 ) × 2 − 3 × 1.25 = + 0.15625 \text { value }=(+1) \times 2^{-3} \times 1.25=+0.15625  value =(+1)×23×1.25=+0.15625
同理双精度浮点数(double)的储存格式:
在这里插入图片描述
计算同理单精度。

3. 储存格式的代码说明

下面通过一段代码加深一下对储存格式的理解:

代码主要是通过指针的形式,将4字节的float格式数据的地址及地址中的数据依次打印出来,便于对二进制储存格式的理解

指针变量指向的类型作用:决定了指针变量 所取空间内存的宽度 决定了指针变量+1跳过的单位跨度

#include <stdio.h>
#include <stdlib.h> 

int main ()
{
   float  var_f=0.15625;
   int  i,num;
   char *char_ptr;
	
   num=sizeof(float);
   printf("float存储大小:%d \n",num);
   char_ptr=(char*)(&var_f);


   for ( i = 0; i < num; i++)
   {
   printf("第%d位的地址:%p\n",i+1,char_ptr+i);
   printf("第%d位的数据:%x\n",i+1,*(char_ptr+i));
   }
   return 0;
}

运行结果为:
在这里插入图片描述
通过IEEE-754 Floating Point Converter进行转换有:
在这里插入图片描述

可以看到16进制表示时:0x3e200000 与我们的输出结果一致!

STM32的串口传输:

  上面我们了解了浮点数的储存格式,那么只要将一个浮点数的4个字节数据分成单个字节进行依次串口传输这样就可以了呀!
发送:

void usart_send_float  (float value)
{
   float v_float ;
   unsigned char * char_p;
   unsigned char i,num;

   v_float   = value;
   char_p = (unsigned char *)(&v_float );
   num = sizeof(float);
   
   for (i=0;i<num ;i++)
  {   
   USART_SendData(USART1, *(char_p+i));
   while( USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
  }
}

接收:

       char pc_rx_buf[4];
       unsigned char i,num;
       float *buff,my_float;
       num = sizeof(float);
	   for (i = 0; i < num; i++)
		 pc_rx_buf[i] = *(char_ptr + i); //接收来自串口的数据
	   buff = (float*)(pc_rx_buf);
	    //从pc_rx_buf[0]开始读取4个字节pc_rx_buf[0]、[1]、[2]、[3]组成一个float
	   my_float = *buff; //得到数值
	   //or my_float = *(float*)char_ptr; 进行强制类型转换,将char_ptr转成一个float指针并将地址中保存的数据传给my_float

验证:

#include <stdio.h>
#include <stdlib.h> 

int main()
{
	float  var_f = 0.15625, my_float;
	int  i, num;
	char *char_ptr;
	float *buff;
	char pc_rx_buf[4];
	num = sizeof(float);
	printf("float存储大小:%d \n", num);
	char_ptr = (char*)(&var_f);
	

	for (i = 0; i < num; i++)
	{
		printf("第%d位的地址:%p\n", i + 1, char_ptr + i);
		printf("第%d位的数据:%x\n", i + 1, *(char_ptr + i));
		pc_rx_buf[i] = *(char_ptr + i);
	}
	buff = (float*)(pc_rx_buf);
	printf("pc_rx_buf的地址:%p\n", &pc_rx_buf);
	my_float = *buff;

	printf("接收的数值为:%f\n", my_float);
	return 0;
}

输出结果为:
在这里插入图片描述
  这样就可实现串口的数据发送与接收,对于整数的传输也是相同道理。

  最近实验验证需要,进行了ROS小车的底盘驱动部分的开发,开发任务要进行上位机与下位机的数据交互,其中底盘的角度数据要上传给主控部分,就涉及到了浮点数的串口传输问题,之前调试中,一直是利用串口发送字符串进行数据交互,但在字符串的解算过程中比较麻烦,需要寻找相应的标志位,对于浮点数更是要进行小数点的位置判断,及数据位的长度计算,十分麻烦,参考网上代码中对整数传输的例子,想到了浮点数的传输也同理,故整理记录!

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Spgroc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值