#include<stdlib.h> // 使用 atof()函数 需要包含此头文件
#include<stdio.h>
int main()
{
double d;
char str[] = "123.456";
d=atof(str);
printf("string=%s,double=%lf\n",str,d);
return 0;
}
比如数据buf[]="12.3",则ret = atof(buf).可一获取小数值,或者使用sscanf这个函数来解析也行
两种思路,供参考。
1. 原始字节
按原始字节数据发送,这也是我个人比较倾向的方式。首先,位、字节和字节流本身没有任何意义,如果按约定的方式去解析,才能有具体的含义。
用什么约定方式呢?使用符合IEEE 754的浮点数标准,每个浮点数为4个字节,按标准解析就可以了。
其实这个标准,包括STM32在内的很多微控制器,都是支持的,内部的表达方式都是一致的,而且效率很快。
技巧就是定义好一个联合体,这一步很关键:
union ByteDouble
{
float x;
struct SB
{
uint8_t b3;
uint8_t b2;
uint8_t b1;
uint8_t b0;
}bb;
}bd;
复制代码
然后在USART的串口中断中,用4个uint8_t获取这四个字节,最后用float表示出来。
//获取数据中断处理函数
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)//Got Data
{
USART1_RX_BUFFER[USART1_RX_CNT++]=USART_ReceiveData(USART1);
}
else if(USART_GetITStatus(USART1,USART_IT_IDLE)!=RESET)
{
//Clear USART_IT_RXNE Flag
USART1->DR;
//Clear USART_IT_IDLE Flag
USART1->SR;
//Process Receive DATA Here
////////////////////////////////////////////////
//Example:
//printf("%s\r\n",USART1_RX_BUFFER);
bd.bb.b0=USART1_RX_BUFFER[0];
bd.bb.b1=USART1_RX_BUFFER[1];
bd.bb.b2=USART1_RX_BUFFER[2];
bd.bb.b3=USART1_RX_BUFFER[3];
printf("%f\r\n",bd.x);
////////////////////////////////////////////////
//Finally Clear Buffer
memset(USART1_RX_BUFFER,0x00,USART1_RX_CNT);
USART1_RX_CNT=0;
}
}
复制代码
测试如下:
![](https://img.haomeiwen.com/i10614199/cf74c87df446a09e.jpg)
1.jpg(31.18 KB, 下载次数: 5)
浮点数表示
2018-5-12 13:43 上传
这个是浮点数的表示形式,123.456按IEEE754的规范,表示成十六进制就是42 F6 E9 79。
然后使用串口程序发送给STM32:
![](https://img.haomeiwen.com/i10614199/4fdf8810b121889d.jpg)
2018-05-12_134634.jpg(61.71 KB, 下载次数: 8)
串口发送
2018-5-12 13:45 上传
两个注意的地方:
a. 浮点数是近似表示,所以你看STM32解析的是123.456001,而不是精确的123.456,这并不违反IEEE 754标准,尤其是涉及到最后一个bit的四舍五入方法,在IEEE 754 中并没有明确规定。
b. 字节顺序和对齐。你所有的工作只是定义好联合体,然后填充好联合体,STM32会自动替你完成转换。不过需要注意的是,一些上位机采用的是大端对齐的方式, 发送的字节顺序会相反。
2. 字符串方式
如果是字符串或者其他方式发送,那就可以自定义一套转换机制,甚至你的上位机在发送2/5的分数,或者40%这样的字符串,都可以解析为0.4的浮点数,这种方式的灵活度非常高,但是对编程要求更复杂,而且相对而言,比较占用MCU的CPU时间和Flash。
原网址:
http://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=615818
网友评论