STM32串口传输浮点数

这篇具有很好参考价值的文章主要介绍了STM32串口传输浮点数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

USART 传输浮点数

1. 字节序

现代的计算机系统一般采用 字节(Octet, 8 bit Byte)作为逻辑寻址单位,当物理单位的长度大于 1 个字节时,就要区分字节顺序(Byte Order, or Endianness)。

字节序,即字节在电脑中存放时的序列与输入(输出)时的序列是先到的在前还是后到的在前。字节序也用于描述多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序,常见的字节序有 大端模式(Big Endian)小端模式(Little Endian) 两种,还有一种不太常见的 中端模式(Middle-Endian)

大端模式: 高字节数据存储在低地址,低字节数据存储在高地址。

小端模式: 高字节数据存储在高地址,低字节数据存储在低地址。

中端模式: 比如以 4 个字节为例,比如以 3-4-1-2 或 2-1-4-3 这样的顺序存储的就是中端模式,这种存储顺序偶尔会在一些小型机体系中的十进制数的压缩格式中出现,但是 ARM 架构平台一般不使用这种模式,这里不做讲解。

1.1 大端模式

假设一个长度为 5 byte 数据 0x0102030405,大端模式下字节序为

Low Address ----------> High Address
+----------------------------------+
| 0x01 | 0x02 | 0x03 | 0x04 | 0x05 |
+----------------------------------+

其中高字节(左边的位)0x01 处于低地址(High-byte first)。

1.2 小端模式

假设一个长度为 5 byte 数据 0x0102030405,小端模式下字节序为

Low Address ----------> High Address
+----------------------------------+
| 0x05 | 0x04 | 0x03 | 0x02 | 0x01 |
+----------------------------------+

其中低字节(右边的位)0x05 处于低地址(Low-byte first)。

1.3 检测字节序

在各种计算机体系结构中对于字节,字等的存储机制有所不同,因而引发了计算机通信领域中一个很重要的问题,即通信双方交流的信息单元(比特、字节、字、双字等等)应该以什么样的顺序进行传送。如果不达成一致的规则,通信双方将无法进行正确的编/译码从而导致通信失败。

所以在通信之前我们需要事先确定通信双方的字节序,如果双方的字节序不同则需要协商字节序比如以小端模式为准,此时如果发送方为大端模式则要将数据转换为小端模式进行发送。检测平台上字节序有以下两种方法。

方法一:

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

/**
 * union 共用体所有成员公用一个空间,
 * 空间为共用体中的最大类型
 */

typedef union {
    unsigned short data;
    unsigned char buf[2];
} Data;

int main()
{
    Data Hello = {0};
    Hello.data = 0x0102;

    if (
        (Hello.buf[0] == 0x01) &&
        (Hello.buf[1] == 0x02)
    ) {
        printf("Big Endian\n");
    }

    if (
        (Hello.buf[0] == 0x02) &&
        (Hello.buf[1] == 0x01)
    ) {
        printf("Little Endian\n");
    }

    return 0;
}

方法二:

const int endian = 0x01;
#define is_bigendian()    ((*(char *)&endian) == 0)
#define is_littlendbian() ((*(char *)&endian) == 1)

2. 传输浮点

我们知道单片机串口发送一帧的数据量为 1 个字节(8 位),这意味着串口发送的一帧数据能够表达(发送)的数值范围为 -128~127,或 0~255。

其实无论是串口还是并口都是一样的,对于 8 位并口发送一帧的数据量也为 1 个字节(8 位)能够表示的数值范围也为 -128~127,或 0~255。16 位并口发送一帧的数据量为 2 个字节(16 位)能够表示的数值范围为 -32768~32767,或 0~65535 超过该范围也无能为力。

所以无论使用什么接口或传输方式一帧数据能表达的数值范围都是有限的,所以为了能够传输更广的数值范围我们需要将数值规则拆分以分次传输。

2.1 分次传输

事实上串口传输数值无论传输的是浮点(4/8 byte)还是整型(2/4/8 byte)类型数值,只要数值范围超过 1 个字节(8 位)串口都无法直接完整传输。

所以我们需要将数值按照一定的规则进行拆分,比如将浮点数值从高到低位拆分为 4 个字节(byte1~byte 4)来分 4 次传输,第 1 帧传输第 1 个字节,第 2 帧传输第 2 字节以此类推(这也是前面讲解字节序的意义)。这很类似使用串口发送字符串,因为字符串就是由多个字节组成的,然后每帧发送一个字符(1 个字节)。

usart_send_data("Hello, World!");

可以定义结合一些协议,在协议中告诉接收端接收的数值由 4 个字节组成,要求接收端按照 4 个字节来还原原始数值。结合协议可以让传输程序更灵活,可以发送和接收解码任意字节长度的数值。

2.2 程序实例

前面了解了传输浮点数值的原理,接下来了解一下浮点数值如何按字节拆分。浮点数值按字节的拆分方法有两种,分别为利用指针和联合体的方式进行实现,不过联合体(Union)需要依赖特定编程语言(例如 C 语言)的特性进行实现。

2.2.1 指针形式

我们可以定义一个 char 类型的指针,我们知道 char 类型指针可以逐字节遍历内存中数据,按照该原理我们可以将 char 型指针指向占用 8 个字节空间 double 类型的浮点数据(注意此过程需要强制转换),此时就可以利用指针来逐字节遍历或读取 double 类型包含的 8 个字节数据内容了,如下。

#include <stdio.h>

double send_value = 0.0;
unsigned char * send = NULL;

double recv_value = 0.0;
unsigned char recv[8];

int main()
{
    send_value = 3.14159;
    send = (unsigned char *)&send_value;

    printf("send:%lf\n", send_value);

    // Send and receive data
    for (unsigned char i = 0; i < 8; i++) {
        printf("byte%d:%x\n", i, *send);
        recv[i] = *send;
        send++;
    }

    recv_value = *((double *)&recv[0]);
    printf("recv:%lf\n", recv_value);

   return 0;
}

2.2.2 联合形式

对于 C 语言来说可以利用 Union(联合体),由于联合中的所有元素会共用同一段内存。定义一个联合体,联合体内有一个 double 类型数据和一个 8 个字节大小的 char 类型数组。因为 double 类型数值需要占用 8 个字节,所以 double 数值占用的空间和长度为 8 的 char 类型数组占用的空间是相同的。

有意思的是联合体会将 double 类型的数值拆解为 8 个字节并按照当前平台的字节序排列放置到长度为 8 的数组中(共用内存机制),这样我们可以省略前面指针方式的一个数据强制转换问题,直接使用联合体的数组进行发送即可,如下。文章来源地址https://www.toymoban.com/news/detail-435574.html

#include <stdio.h>

#define MAX_LENTH 8

union send {
    char byte[MAX_LENTH];
    double value;
};

union recv {
    char byte[MAX_LENTH];
    double value;
};

int main()
{
    send send_value;
    recv recv_value;

    send_value.value = 3.14159;
    recv_value.value = 6.28318;

    printf("send:%lf\n", send_value.value);
    printf("recv:%lf\n", recv_value.value);

    // Send and receive byte
    for (unsigned char i = 0; i < MAX_LENTH; i++) {
        printf("Send byte:%d\n", i);

        recv_value.byte[i] = send_value.byte[i];

        printf("Recv byte:%d\n", i);
    }

    printf("recv:%lf\n", recv_value.value);

    return 0;
}

到了这里,关于STM32串口传输浮点数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32单片机(九)USART串口----第三节:USART串口实战练习(串口发送)

    ❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋

    2024年02月10日
    浏览(37)
  • STM32单片机(九)USART串口----第四节:USART串口实战练习(串口发送+接收)

    ❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋

    2024年02月10日
    浏览(38)
  • 【STM32】STM32学习笔记-USART串口协议(25)

    按数据传送的方式,通讯可分为串行通讯与并行通讯,串行通讯是指设备之间通过少量数据信号线(一般是8根以下), 地线以及控制信号线,按数据位形式一位一位地传输数据的通讯方式。而并行通讯一般是指使用8、16、32及64根或更多的数据线进行传输的通讯方式, 它们的通

    2024年01月19日
    浏览(40)
  • 「STM32入门」USART串口通信

    通信的目的:将一个设备的数据传送到另一个设备,扩展硬件系统 通信协议:制定通信的规则,通信双方按照协议规则进行数据收发 本文将介绍USART  概念解释 TX、RX分别是Transmit和Receive的缩写,代表发送、接受数据 全双工的含义是发送线路和接受线路互不影响,可以同时进

    2024年02月06日
    浏览(39)
  • 【STM32】STM32学习笔记-USART串口数据包(28)

    串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,因此大部分电子设备都支持该通讯方式, 电子工程师在调试设备时也经常使用该通讯方式输出调试信息。 在计算机科学里,大部分复杂的问题都可以通过分层来简化。如芯片被分为内核层和

    2024年01月18日
    浏览(35)
  • stm32学习笔记-9 USART串口

    注:笔记主要参考B站 江科大自化协 教学视频“STM32入门教程-2023持续更新中”。 注:工程及代码文件放在了本人的Github仓库。 从本节开始,将逐一学习STM32的通信接口。首先介绍以下stm32都集成了什么通信外设。 为了控制或读取外挂模块,stm32需要与外挂模块进行通信,来扩

    2024年02月14日
    浏览(37)
  • 串口屏(USART HMI)与STM32

    目录 一、前期准备 二、串口屏上位机 三、STM32软件编程 1.STM32单片机 2.HMI USART串口屏 本人使用使用的是陶晶驰的串口屏。型号为TJC4832T135_011 3.USB转TTL串口模块电源板(CP2102芯片)(CH340也可以) 官网资料:USART HMI 资料中心 可拖动左侧工具箱进行界面设计,常用文本、按钮、

    2024年02月05日
    浏览(41)
  • STM32入门学习之USART串口通信:

    1.串口通信简介:通用异步收发传输器UART(Universal Asynchronous Receiver/Transmitter)是负责处理数据总线和串口之间的串/并通信的设备。UART通信规定了数据帧的格式:起始位、数据位、校验位、停止位等。UART异步通信只需要通信双方设置好数据帧的格式和波特率即可完成通信。因为

    2024年02月16日
    浏览(41)
  • STM32CubeMX实现USART串口通信

    硬件:stm32f103c8t6核心板 软件:STM32CubeMX 6.6.1 keil5 mdk 这里就不再详细介绍了,详细请参考上一篇博客: https://blog.csdn.net/qq_55894922/article/details/127232999?spm=1001.2014.3001.5501 若点击 Manage embedded software packages 后,出现失败,则需要随便点击其它任一选项,进行下载一些文件,比如点

    2023年04月17日
    浏览(47)
  • STM-32:USART串口协议、串口外设—数据发送/数据发送+接收

    通信的目的:将一个设备的数据传送到另一个设备,扩展硬件系统。比如STM32芯片里面集成了很多功能模块,如定时器计数、PWM输出、AD采集等等,这些都是芯片内部的电路,它们的配置寄存器、数据寄存器都在芯片里面,操作简单,直接读写就行。但是有些功能STM32内部没有

    2024年02月04日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包