[STM32F4] 用 memcpy 函数将浮点数转换为字节表示形式

[复制链接]
59|5
地瓜patch 发表于 2026-1-22 11:28 来自手机 | 显示全部楼层 |阅读模式
本帖最后由 地瓜patch 于 2026-1-22 11:32 编辑


我将浮点数转换为字节表示形式,通过 CAN 总线的 HAL_CAN_AddMessage () 函数发送;接收数据时,再将字节数据转换回对应的浮点数。
第一个浮点数的转换和回传都能正常完成,可以将其转为字节形式发送,通过 HAL_CAN_GetMessage () 接收后也能成功转回浮点数。
但处理第二个浮点数时出现问题,接收端接收不到第二个浮点数的数据。
假设浮点变量如下:
float voltage = 7.3789;
float temperature = 21.98290;
第一个 memcpy () 函数调用完全正常。
以下是完整代码:

uint32_t TxMailbox[3];    //create a variable Mailbox to transmit data
uint8_t TxData[8];    // buffer for transmit data
uint8_t RxData[8];    // buffer for recieving data
uint8_t count = 0;

float receivedVoltage;
float receivedTemperatuer;


void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
   HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData); // data will be recieved from CAN_RX_FIFO0, the header will be stored in RxHeader, data will be saved in RxData

   memcpy(&receivedVoltage, &RxData, sizeof(receivedVoltage));
   memcpy(&receivedTemperatuer, &RxData + sizeof(receivedVoltage), sizeof(receivedTemperatuer));

}

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
char uart_buf[50];
int uart_buf_len;
    uint16_t timer_val;


  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_CAN2_Init();
  MX_TIM6_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
  HAL_CAN_Start(&hcan2);   // start the can here
  HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO0_MSG_PENDING);    //activate the notification of recieving data

  TxHeader.DLC = 8;  // this specifies the length of the data that will be send //8
  TxHeader.ExtId = 0;  // since we use standard protocol we set it to zero
  TxHeader.IDE = CAN_ID_STD; // the IDE is the standard ID
  TxHeader.RTR = CAN_RTR_DATA;  // we send data not frame
  TxHeader.StdId = 0x102;  // this is the identifire, must check why 0x103
  TxHeader.TransmitGlobalTime = DISABLE;


// HAL_CAN_AddTxMessage(&hcan2, &TxHeader, (uint8_t*)TxData, &TxMailbox);

  //uint8_t dev_address1 = 0x16;
  uint8_t dev_address = 0x6C;

  void SendFloatsOverCAN( float voltageVal, float temperatureVal){
  memcpy(&TxData, &voltageVal, sizeof(voltageVal));
  memcpy(&TxData + sizeof(voltageVal), &temperatureVal, sizeof(temperatureVal));

  HAL_CAN_AddTxMessage(&hcan2, &TxHeader, TxData, TxMailbox);
  }
while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */

  main_function(dev_address);
  SendFloatsOverCAN(voltage, temperature);   // voltage and temperature are the floating points varaibles
  HAL_Delay(500);

  }

RxData 和 TxData 中存储的是相同的数据
6720169719a191e002.png
磨砂 发表于 2026-3-14 10:32 | 显示全部楼层
memcpy是C/C++标准库中用于内存块复制的核心函数,以字节为单位高效复制数据,适用于各种数据类型的内存拷贝场景
晓伍 发表于 2026-3-14 13:27 | 显示全部楼层
以字节为单位复制,不关心数据类型,适用于任意数据类型
八层楼 发表于 2026-3-14 15:56 | 显示全部楼层
底层由编译器和硬件优化,通常会利用SIMD指令或硬件加速,效率远高于手动循环复制,尤其在复制大块内存时优势显著,适合对性能敏感的场景
观海 发表于 2026-3-14 18:09 | 显示全部楼层
memcpy假设源和目标内存区域不重叠,若存在重叠,行为未定义,可能导致数据损坏
guanjiaer 发表于 2026-3-14 20:27 | 显示全部楼层
参数为[size=0.875]void*指针,允许复制任意类型的数据,但需开发者自行保证数据类型的兼容性和内存对齐,否则可能导致未定义行为
heimaojingzhang 发表于 2026-3-15 08:02 | 显示全部楼层
必须确保[size=0.875]dest指向的内存空间大小不小于[size=0.875]n字节,否则会导致缓冲区溢出,引发程序崩溃或安全漏洞
keaibukelian 发表于 2026-3-15 10:19 | 显示全部楼层
推荐使用[size=0.875]sizeof()计算复制字节数,避免硬编码,增强代码安全性
paotangsan 发表于 2026-3-15 12:36 | 显示全部楼层
虽然[size=0.875]memcpy可用于复制字符串,但并非最佳选择,因为[size=0.875]memcpy不会自动处理字符串终止符[size=0.875]\0,需要手动指定复制字节数
renzheshengui 发表于 2026-3-15 15:08 | 显示全部楼层
memcpy不会检查[size=0.875]src[size=0.875]dest是否为[size=0.875]NULL,传递空指针会直接导致未定义行为,因此在调用前需手动校验指针有效性
wowu 发表于 2026-3-15 17:31 | 显示全部楼层
在动态分配的内存中,复制数据,确保数据的迁移和备份,常用于动态内存管理场景
yzdel7 发表于 2026-3-14 20:05 来自手机 | 显示全部楼层
标准的编译器float格式的数据是4个字节,你可以定义个union,就不用那么麻烦拷贝来拷贝去了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:出一块TI-PLABS-AMP-EVM

2965

主题

17918

帖子

31

粉丝
快速回复 在线客服 返回列表 返回顶部
0