stm32_H750VB_cubemx_HAL----三----UART_DMA学习记录(2)

本文介绍了STM32使用DMA进行串口通信时,定长与不定长数组接收的区别,以及在实际操作中遇到的Hard Fault错误。作者通过实验和代码分析,解释了数据错位问题的原因,并分享了如何避免因函数指针为NULL导致的Hard Fault。同时,提到了初始化过程中的注意事项,强调了检查和预防此类错误的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一次hard_fault

不知道为什么它让我进入hard_fault
在这里插入图片描述
,换成remote_deal(buf,0)就好?(收到的数据依然不完整,是放错数组了?)

为什么没有进来??
在这里插入图片描述

看起来好像没进来,但是赋值成功了,成功了为什么还会进hard_fault??
在这里插入图片描述

,懂了:
经过step one line后发现其实第一次触发中断时还未执行board_init();
这时这个函数指针确实是NULL!!!进去后程序跑到0x000000了还跑个der~,所以就成了hard_fault
难怪教科书上经常见到这类判断语句:if(xxx!=NULL){ }
(并且不单步运行时等了半分钟都半天不给我进去赋值,不知道为什么)

在这里插入图片描述
改进:先完成函数指针赋值,再开启中断,例如:
先调用regeister();在调用init(); 瞬间就赋值完成了:
在这里插入图片描述
,一会就把这个阴间初始化函数改得阳间一些。

强烈推荐亲身体验一下函数指针指向NULL引发的hard_fault,不体会一次真的理解不了为什么教科书写那么多if(xxx!=NULL),血的教训。QvQ

但其实不是很懂hardfault到底是什么
在这里插入图片描述

到底什么是定长数组接收,什么是不定长数组接收啊?

0
在这里插入图片描述
1
在这里插入图片描述
2
在这里插入图片描述
3
在这里插入图片描述
4
在这里插入图片描述
5
在这里插入图片描述
在这里插入图片描述

我自己的理解:

定长数据接收/发送:
仅仅只开启 “DMA的接收和发送完成中断” ----(准确定义应该是,啊我猜是,buffer中的每一字节都填入/发出后,某个Counter寄存器从预设的rec_len/ tra_len递减到0时,出发完成中断)

然后假设buffer_size定的和一帧数据长度相等,且发送端(上位机)在接收端初始化完成前一直在发送的话,刚开启接受的那一瞬间可能接收到任意位置的数据,产生错位。
不定长数据接收发送:

在这里插入图片描述

自己尝试体验一下定长接收中断是什么样的(单步执行),设一个100字节数组,每次进中断时都查看一下re_length,并查看数据是否会错位什么的。

定长数组代码编写参考:

(三)stm32之串口通信DMA传输完成中断
在这里插入图片描述

代码编写经历:

没嫖到HAL库的代码,不信邪自己分析着写了一下,DMA函数寻找是照着UART中断处理的名字找的:
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
uint32_t tmp_flag = 0;
uint32_t temp;
tmp_flag =__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE); //获取IDLE标志位
if((tmp_flag != RESET))//idle标志被置位
{
__HAL_UART_CLEAR_IDLEFLAG(&huart2);//清除标志位
//temp = huart1.Instance->SR; //清除状态寄存器SR,读取SR寄存器可以实现清除SR寄存器的功能
//temp = huart1.Instance->DR; //读取数据寄存器中的数据
//这两句和上面那句等效
HAL_UART_DMAStop(&huart2); //
temp = __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);// 获取DMA中未传输的数据个数
//temp = hdma_usart1_rx.Instance->NDTR;//读取NDTR寄存器 获取DMA中未传输的数据个数,
//这句和上面那句等效
rx_len = BUFFER_SIZE - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数
recv_end_flag = 1; // 接受完成标志位置1
}

/* USER CODE END USART2_IRQn 0 /
HAL_UART_IRQHandler(&huart2);
/
USER CODE BEGIN USART2_IRQn 1 */

/* USER CODE END USART2_IRQn 1 */
}
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
依据上几个图片分析写得代码且经实验正确(我设置了100字节的缓冲数组,每次只发送50字节,经断点观察,确实是发送两次,发送100个字节过去后才触发接收完成中断):

代码:

cubemx自动开启DMA中断,不用改什么;
it.c:

void DMA1_Stream4_IRQHandler(void)//usart3_rec
{
  /* USER CODE BEGIN DMA1_Stream4_IRQn 0 */
 if(__HAL_DMA_GET_FLAG(&hdma_usart3_rx,DMA_FLAG_TCIF0_4))
    {
			  HAL_UART_Transmit_DMA(&huart3, (uint8_t *)test_3,sizeof(test_3));	

        __HAL_DMA_CLEAR_FLAG(&hdma_usart3_rx,DMA_FLAG_TCIF0_4); //清除全部中断标志
    }
  /* USER CODE END DMA1_Stream4_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_usart3_rx);
  /* USER CODE BEGIN DMA1_Stream4_IRQn 1 */

  /* USER CODE END DMA1_Stream4_IRQn 1 */
}

实验截图

疑惑:

每次数据错位都是错到9012345…太巧合了?还是别的原因?【】
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

什么叫“定长数组的数据错位问题”?

见上一条的实验截图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值