如何使用数据包收发float型数据以及大小端问题

目录

一、浮点型数据接收

(一)数据包接收

1)逻辑结构

2)代码部分(以下全部放在serial.c中)

(二)对浮点型数据的处理(这里以接收三轴浮点数为例)

二、float型数据的发送

三、使用stm32遇到的大小端问题


一、浮点型数据接收

(一)数据包接收

1)逻辑结构

2)代码部分(以下全部放在serial.c中)

1、先定义如下变量:

uint8_t recvData;   //接收数据缓存
uint8_t recvFlag;   //标志位

uint8_t recvPacket[128] = {0};  //存放接收的数据

2、main中调用一次开启接收中断

void USART_IT_Enable()
{
    HAL_UART_Receive_IT(&huart1, &recvData, 1);
}

3、编写回调函数

/* 中断回调函数 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    static uint8_t recvState = 0;  //状态标志位
    static uint8_t i = 0;         //存放数据的数组的下标

    //状态机
    if (0 == recvState)
    {
        if (recvData == 0xFF)
        {
            recvState = 1;
            i = 0;
        }
    }
    else if (1 == recvState)
    {
        recvPacket[i] = recvData;
        i++;

        if (i >= DATALENGTH)  //指定接收数据的长度
        {
            recvState = 2;
        }
    } 
    else if (2 == recvState)
    {
        if (recvData == 0xFE)
        {
            //到这里已经接收完成,添加对recvPacket的操作
            i = 0;
            recvState = 0;
            recvFlag = 1;    //表示接收完成
        }

    }

    HAL_UART_Receive_IT(&huart1, (uint8_t *)&recvData, 1);   //再开启接收中断
}

(二)对浮点型数据的处理(这里以接收三轴浮点数为例)

//先定义一个全局变量
float aim_x = 0, aim_y = 0, aim_z = 0;

//数据解析函数
static void Analysis_Data(uint8_t re_data[],float *x,float *y,float *z)
{
    *x = Aplice_Float(re_data,0);  //解析xyz数据
    *y = Aplice_Float(re_data,1);
    *z = Aplice_Float(re_data,2);
}

//字符拼接函数
static float Aplice_Float(uint8_t Tobe_Spliced[],int k)
{
    uint8_t byteStream[sizeof(float)] = {0};

    int added = 4*k; //用于拆分数据
    // 逐字节接收字节流
    for (int i = added; i < sizeof(float)+added; i++) {
        byteStream[i - added] = Tobe_Spliced[i];
    }

    float data;
    //memcpy(&data, byteStream, sizeof(float));//转换成float型
    data = *(float*)byteStream;

    return data;
}

//返回三轴数据
void Get_xyz(float *x, float *y, float *z)
{
    *x = aim_x;
    *y = aim_y;
    *z = aim_z;
}

二、float型数据的发送

//串口发送函数
void bsp_USART_SendData(float floatData)
{
    HAL_UART_Transmit(&huart1,(uint8_t*)0xA5,1,0xfffff);//头部标识
    // 将 float 数据的地址强制转换为字节流的地址
    uint8_t* byteStream = (uint8_t*)&floatData;

    // 通过 USART 逐字节发送字节流
    for (int i = 0; i < sizeof(float); i++) {
        HAL_UART_Transmit(&huart1,&byteStream[i],1,0xffff);
    }
}

通过以上代码自收发,实验测试如下:

三、使用stm32遇到的大小端问题

在stm32芯片中使用小端存储数据,即高位数据存储在高地址,这就导致发送端发送的是3F 99 99 99,单片机接收到的四个字节也依次是3F 99 99 99,但是将其直接转换为浮点数,它是将99 99 99 3F转换为浮点数,其结果是-1.5881724819422105e-23,所以,在数据解析时要进行字节转换。

float  SwapFloat(float value) //Float大小端转换
{
    union{
        float f;
        unsigned char b[4];
    }source, dest;
    source.f = value;
    dest.b[0] = source.b[3];
    dest.b[1] = source.b[2];
    dest.b[2] = source.b[1];
    dest.b[3] = source.b[0];
    return dest.f;
}

double SwapDouble(double value) //Double大小端转换
{
    union{
        double d;
        unsigned char b[8];
    }source, dest;
    source.d = value;
    dest.b[0] = source.b[7];
    dest.b[1] = source.b[6];
    dest.b[2] = source.b[5];
    dest.b[3] = source.b[4];
    dest.b[4] = source.b[3];
    dest.b[5] = source.b[2];
    dest.b[6] = source.b[1];
    dest.b[7] = source.b[0];
    return dest.d;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值