完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
前言
在前两章节中已经讲述了串口的通常用法, 【STM32】CubeMX+HAL库之串口 以及串口DMA空闲中断不定长接收与发送, 【STM32】串口DMA空闲中断不定长收发配自定义装包与解包 在本章节我们将介绍DMA双缓冲这一技术。在很多时候数据的发送频率与数据接收使用频率并不一致,数据来的太快,接收者还没来得及对其进行处理,下一帧的数据就到了,并将其覆盖,致使信息的有效性大大减弱。这时我们增加一个缓冲区来存放来不及处理的数据,就能更好地完成任务。双缓冲还有一个重要的应用是在图像部分,可以更好的解决显示图像时的闪烁延迟问题。 所用工具: 开发板:野火挑战者STM32H743IIT6 STM32CubeMX IDE: Keil-MDK 满足怎样的需求 利用DMA传输方式节约CPU资源 利用串口空闲中断来拉起处理函数 提供掉线重启DMA的能力,保证热插拔的稳定性 总述流程 在主函数中调用初始化函数 main.c /* USER CODE BEGIN PFP */ extern void uartInit(UART_HandleTypeDef *huart); /* USER CODE END PFP */ /* USER CODE BEGIN 2 */ uartInit(&huart1); /* USER CODE END 2 */ bsp_uart.c中的定义 uint8_t rx_buf[2][RX_BUFLEN]; //双缓冲Buffer DMA_Stream_TypeDef *DMA_DBuf; 初始化函数实体 此部分初始化两个Buffer,与前部分的区别十分明显。 bsp_uart.c void uartInit(UART_HandleTypeDef *huart) { DMA_DBuf = huart->hdmarx->Instance; //enable the DMA transfer for the receiver request //使能DMA串口接收 SET_BIT(huart->Instance->CR3, USART_CR3_DMAR); //enalbe idle interrupt //使能空闲中断 __HAL_UART_ENABLE_IT(huart, UART_IT_IDLE); //disable DMA //失效DMA __HAL_DMA_DISABLE(huart->hdmarx); while(DMA_DBuf->CR & DMA_SxCR_EN) { __HAL_DMA_DISABLE(huart->hdmarx); } DMA_DBuf->PAR = (uint32_t) & (USART1->RDR); //F4中为DR //memory buffer 1 //内存缓冲区1 DMA_DBuf->M0AR = (uint32_t)(rx_buf[0]); //memory buffer 2 //内存缓冲区2 DMA_DBuf->M1AR = (uint32_t)(rx_buf[1]); //data length //数据长度 huart->RxXferSize = RX_BUFLEN * 2; DMA_DBuf->NDTR = RX_BUFLEN * 2; //enable double memory buffer //使能双缓冲区 SET_BIT(DMA_DBuf->CR, DMA_SxCR_DBM); //enable DMA //使能DMA __HAL_DMA_ENABLE(huart->hdmarx); } 回调函数实体 在处理函数中也分别对两个Buffer进行处理。 bsp_uart.c void BSP_UART_Callback(UART_HandleTypeDef *huart) { DMA_DBuf = huart->hdmarx->Instance; if(huart->Instance == USART1) { if(huart->Instance->ISR & UART_FLAG_RXNE)//接收到数据 F4 为SR { __HAL_UART_CLEAR_PEFLAG(huart); } else if(huart->Instance->ISR & UART_FLAG_IDLE) { static uint16_t this_time_rx_len = 0; __HAL_UART_CLEAR_PEFLAG(huart); //disable DMA //失效DMA __HAL_DMA_DISABLE(huart->hdmarx); //get receive data length, length = set_data_length - remain_length //获取接收数据长度,长度 = 设定长度 - 剩余长度 this_time_rx_len = huart->RxXferSize - DMA_DBuf->NDTR; //reset set_data_lenght //重新设定数据长度 DMA_DBuf->NDTR = 36; if ((DMA_DBuf->CR & DMA_SxCR_CT) == RESET) { //set memory buffer 1 //设定缓冲区1 DMA_DBuf->CR |= DMA_SxCR_CT; //enable DMA //使能DMA __HAL_DMA_ENABLE(huart->hdmarx); if(this_time_rx_len == 18) { //LoadData(0); 此部分写自己的解包程序 } } else { //设定缓冲区2 DMA1_Stream1->CR &= ~(DMA_SxCR_CT); //enable DMA //使能DMA __HAL_DMA_ENABLE(huart->hdmarx); if(this_time_rx_len == 18) { //LoadData(1); 此部分写自己的解包程序 } } } } }``` 5. 在stm32h7xx_it.c中加入自定义回调函数 ```c /* USER CODE BEGIN PFP */ extern void BSP_UART_Callback(UART_HandleTypeDef *huart); /* USER CODE END PFP */ void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ BSP_UART_Callback(&huart1); /* USER CODE END USART1_IRQn 0 */ HAL_UART_IRQHandler(&huart1); /* USER CODE BEGIN USART1_IRQn 1 */ /* USER CODE END USART1_IRQn 1 */ } 双缓冲的使用到这里就结束了,H7与其他芯片略有不同,需要自行找下问题,在代码中基本也都有注释,此部分学的还不够透彻,还望大佬指教更加官方的写法。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1627 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1550 浏览 1 评论
984 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
688 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1601 浏览 2 评论
1869浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
652浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
520浏览 3评论
539浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
508浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-25 02:11 , Processed in 0.938510 second(s), Total 79, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号