文章目录众手捉之(众所周知),在单片机应用时对float的需求比较大,但它又不(不容易)让你用float,所以本文档的目的是:
希望在flash中存储float,int,乃至结构体类型的数据涉及双机乃至多机通信时,能够不受数据类型的限制(想传啥数传啥数)
float的表示和存储方式应用
float的表示和存储方式表示方式
一般情况下,float类型的数据占据的内存为4比特,32位,并且有其独特的表示方式(科学计数法),但是计算机眼中的科学计数法是这样的:
(
±
)
1.
a
×
2
b
(1)
(pm)1.a times 2^b tag{1}
(±)1.a×2b(1)
例如:
1010
⇒
+
1.01
×
2
3
0101
⇒
+
1.01
×
2
2
10101
⇒
+
1.0101
×
2
4
0.0101
⇒
+
1.01
×
2
−
2
begin{aligned} 1010 &Rightarrow +1.01 times 2^3 \ 0101 &Rightarrow +1.01 times 2^2 \ 10101 &Rightarrow +1.0101 times 2^4 \ 0.0101 &Rightarrow +1.01 times 2^{-2} \ end{aligned}
10100101101010.0101⇒+1.01×23⇒+1.01×22⇒+1.0101×24⇒+1.01×2−2
存储方式1
如上式(1)所示,float类型的数据需要分三部分存储,分别是正负号, a a a 和 b b b,所以32位的空间被划分为三部分:
- 符号位(1位):最高位存储符号指数位(8位):左数第二位到第九位存储指数,但是需要把指数偏移127,所以这八位存储的数值为b+127尾数位(23位):最后二十三位存储尾数,如果尾数为0.01则计算机会把它自动补齐为0.010_0000_0000_0000_0000_0000,并把小数点后的23位存储在尾数位中
举例
10
⇒
1010
⇒
1.01
×
2
3
⇒
0
_
10000010
_
01000000000000000000000
10 Rightarrow 1010 Rightarrow 1.01 times 2^3 Rightarrow 0_10000010_01000000000000000000000
10⇒1010⇒1.01×23⇒0_10000010_01000000000000000000000验证一下:
int main(void)
{
float data = 10;
int data_bit = *(int *)&data; //把float的32位数据存储在int中
std::string str = "";
for (int i = 31; i>=0; i--)
{
//把这32位数据存储在string类型中,方便打印
if (data_bit & 1 << i) str+="1";
else str+="0";
}
std::cout << str; //打印
return 0;
}
输出结果:
01000001001000000000000000000000
甚至我们还可以“创造”一个浮点数(以713为例):
713
⇒
1011001001
⇒
1.011001001
×
2
9
⇒
0
_
10001000
_
01100100100000000000000
⇒
0
x
44324000
713 Rightarrow 1011001001 Rightarrow 1.011001001 times 2^{9} \ Rightarrow 0_10001000_01100100100000000000000 \ Rightarrow 0x44324000
713⇒1011001001⇒1.011001001×29⇒0_10001000_01100100100000000000000⇒0x44324000
验证一下:
int main(void)
{
int data = 0x44324000;
float data_f = *(float *)(&data);
std::cout << data_f;
return 0;
}
输出结果:
713
成功!!!
往flash中存float:
第一种写法
float data; //你的float型参数 void *data_void = (void*)(&data); //把地址赋值给一个数组 uint32_t flash_data; memcpy(&flash_data, data_void, sizeof(uint32_t)); flash_program(flash_data); //写flash的函数另一种写法
float data; //你的float型参数 uint32_t flash_data = *(uint32_t*)(&data); flash_program(flash_data); //写flash的函数读取数据
uint32_t flash_data; //从flash读出的数据 float data = *(float*)(&flash_data);
uart通信发送接收float类型的数据
发送端:
float data; //要发送的数据 uint8_t *p_data = (uint8_t*)(&data); //p_data指向最低的八位 uart_putchar(UART, p_data); p_data++; //把float拆成四个uint8_t发送 uart_putchar(UART, p_data); p_data++; //同一行可以出现俩分号 uart_putchar(UART, p_data); p_data++; uart_putchar(UART, p_data); //连发四次即可接收端:
\推荐在uart接收中断函数中接收
void UART_IRQHandler(void)
{
UART->ICR |= UART_ICR_RXICLR; //清除接收中断标志
float receive_data_f; //你需要接收的参数
static uint8_t receive_data[4]; //定义四个uint8_t参数
static uint8_t count = 0;
uart_getchar(UART, &receive_data[count]);
if (count < 3) count++;
else
{
count = 0;
//将拆开发送的4个uint8_t组合在一起
uint32_t receive_data_bit = 0;
//注意强转(uint32_t)不能少,不然uint8_t位数不够,不能左移8位以上
receive_data_bit += (uint32_t)(receive_data[0] << 8*0);
receive_data_bit += (uint32_t)(receive_data[1] << 8*1);
receive_data_bit += (uint32_t)(receive_data[2] << 8*2);
receive_data_bit += (uint32_t)(receive_data[3] << 8*3);
receive_data_f = *(float *)(&receive_data_bit);
}
}
类似的,float, double, int, 结构体都可以用以上这些方式进行读写传输。
https://blog.csdn.net/albertsh/article/details/92385277 ↩︎



