STM32串口,发送数据有几率错误的一个原因,需要避免DMA指向临时变量地址

/// @brief 串口发送一条格式化数据
void send_OneWeld_list_to_uart(uint16_t id)
{
  uint8_t char_data_uart[ONE_WEld_LIST_BYTE +2];

  char_data_uart[0] = 'M';//MCU 的数据
  char_data_uart[1] = 'I';//list
  memcpy(&char_data_uart[2], &OneWeld_Data_new, sizeof(OneWeld_Data_TypeDef));
  Send_Data_toLCD(char_data_uart, sizeof(char_data_uart),100);
}

/// @brief 通过DMA发送数据到LCD
/// @param pData 数据指针
/// @param Size 数据长度
/// @param timeout 超时时间
#pragma location = ".ccmram"
void Send_Data_toLCD(const uint8_t *pData, uint16_t Size,uint32_t timeout)
{
  uint32_t tickstart; tickstart = HAL_GetTick();

  while (huart1.gState != HAL_UART_STATE_READY)   //等待发送完成
  {
    if (((HAL_GetTick() - tickstart) > timeout) || (timeout == 0U))
      return;
    Refresh_ModbusData_and_IWDG();
  }

  HAL_UART_Transmit_DMA(&huart1, pData, Size); 
}

代码如上图,调用send_OneWeld_list_to_uart函数发送数据到LCD时,有几率出错!

原因是因为串口使用DMA发送,而给DMA的发送数据地址是一个临时变量,

在退出发送函数后,临时变量的地址被释放用于存储其他数据,

而串口发送速度是比较慢的(相较于CPU),这导致发送的数据有几率被修改。

解决方法:

  • 将临时变量char_data_uart变量改为全局变量或静态变量,避免内存被释放。
  • 或在send_OneWeld_list_to_uart函数内等待DMA发送完成后再进行后续的操作,避免退出函数后内存被释放!
  • 修改Send_Data_toLCD函数,根据数据量拷贝数据到静态或全局变量,DMA指向拷贝后的变量

教训:一定要注意DMA的问题,之前还遇到过调试断点导出数据总是出错,运行时则没问题的情况,是因为DMA等大部分外设都不会因为CPU核心的停止而停止工作,调试断点时,CPU停止了,但是DMA并没有停止,导致导出的内存数据是错的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值