完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
项目上正好用到了这个功能,特此记录下来备忘,方便后人
简单说要注意的几个点
我这里用的是串口3 对应的接收和发送DMA mode用的是Normal,不是Circle 初始化完引脚,时钟,DMA后记得使能对应的串口中断 然后还需要编写一个接收使能的函数,如下 执行这个函数会进入一次IDLE中断,这里需要自行处理这种情况 可以通过标志位的方式屏蔽掉这个不正常的进入,或者清除标志位的方式都可以吧 uint8_t UART_Init(void) { uint8_t res = HAL_OK; MX_DMA_Init(); res = MX_USART1_UART_Init(); if (res == HAL_OK) { UART1_RX_EN(); } res = MX_USART3_UART_Init(); if (res == HAL_OK) { UART3_RX_EN(); } return res; } void UART3_RX_EN(void) { __HAL_UART_ENABLE_IT(&huart3,UART_IT_IDLE); //这里需要补充一句Cache无效化的函数(2020-04-23) HAL_UART_Receive_DMA(&huart3,Uart3.Rx_Buf,UART_DMA_BUF_LEN); } 串口IDLE中断的处理方式 & F7的D-Cache一致性的问题&接收和发送的逻辑控制 上述三个问题接下来一并说了 首先我这里定义了一个结构体的方式管理数据缓存和长度,还有有效数据标志,可能还有更机智的方法,待研究,至少目前这样的方法我觉得用的效果就已经很好了 typedef struct { uint8_t Rx_Buf[UART_DMA_BUF_LEN];//可以定义一个宏定义管理缓冲区的长度 uint8_t Idle_Flag;//可以理解为有效数据接收标志 uint16_t Rx_Len;//收到数据的长度 }ST_DMA_UART; 如下是我的串口空闲中断的处理 STM32 F7系列有Cache,这个加快CPU的执行速度,但是在用到涉及DMA的功能的时候就需要考虑它对代码产生的负面影响!!这个可以具体去搜索STM32 F7 Cache一致性的文章 读一读,这里不过多阐述 我现在的理解就是如果涉及到DMA的操作,最好在函数开始执行之前加上指定内存地址的变量 D Cache无效化的操作 当然这个不是绝对的,但是这个应该是一个调试代码的方向。我加了以后代码的功能正常了,即使调试的时候打断点数据也不会乱掉。。。 这个D Cache还是挺复杂的,值得好好深入研究下 SCB_InvalidateDCache_by_Addr((uint32_t *)Uart3.Rx_Buf,UART_DMA_BUF_LEN);这种处理的逻辑应该是比较常见的 简单来说就是进入有效的IDLE中断后
void UART_Receive_IDLE(UART_HandleTypeDef *huart) { uint32_t temp; if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET)) { __HAL_UART_CLEAR_IDLEFLAG(huart); HAL_UART_DMAStop(huart); temp = huart->hdmarx->Instance->NDTR; if(huart->Instance == huart3.Instance) { if(UART_DMA_BUF_LEN - temp!=0) { Uart3.Rx_Len = UART_DMA_BUF_LEN - temp; Uart3.Idle_Flag=DMA_RECV; } } } } void USART3_IRQHandler(void) { UART_Receive_IDLE(&huart3);// HAL_UART_IRQHandler(&huart3); } 主函数里的接收函数如下 进来处理Cache一致性的问题 接着判断接收是否有效,长度是否有效,在进入对于的处理机制里面,处理完以后,清除掉长度值和标志位 uint8_t UART3_DualCPU_DataRX() { if ((Uart3.Idle_Flag == DMA_RECV) && (Uart3.Rx_Len != 0)) { //执行对应的处理操作 Uart3.Idle_Flag = DMA_NOT_RECV;//自己弄个宏定义反应接收的情况 Uart3.Rx_Len = 0; } } 然后发送函数 进来处理Cache一致性的问题 接着填你要发的数据 然后调用底层发送 底层发送函数一定要填你要发送的长度 我这里的调试时如果不写那一句设定长度的话,数据的长度会不对 void UART3_DualCPU_DataTX() { SCB_InvalidateDCache_by_Addr((uint32_t *)uart3_buf,UART3_BUF_LEN);//要加一句这个,确保数据不会因为Cache的问题乱掉 //处理发送数据的代码 UART3_DMA_TX(uart3_buf, UART3_BUF_LEN); } void UART3_DMA_TX(uint8_t * str,uint16_t len) { __HAL_DMA_SET_COUNTER(&hdma_usart3_tx,len);//这里要设置长度!!! HAL_UART_Transmit_DMA(&huart3, str, len); } 总的来说,这个F7的串口DMA基本上就是这么弄的了 效果很棒,基本上都是发送函数一运行完,接收方就收到了,然后再处理发回来,马上我就能收到,速度很快了 我这个是用在两个CPU对向发送数据上的,觉得很好了 之前也找了很多很多的代码看过 F7的代码实现和F4的还是有很大不同的,特别是Cache的问题,要特别注意 在操作DMA之前,无论发送还是接收,都需要加一句SCB_InvalidateDCache_by_Addr或者SCB_CleanInvalidateDCache_by_Addr,这个具体加哪一个要试一试,我这里加SCB_CleanInvalidateDCache_by_Addr,因为我的串口DMA是单次调用的,不是循环模式,所以重新开启收功能之前都需要调用一遍失能Cache函数,然后收发使用到的缓存都需要32字节对齐,这个是SCB_CleanInvalidateDCache_by_Addr或者SCB_CleanInvalidateDCache_by_Addr要求的,估计以前用了这个没起作用,应该也和这个有关,没有32字节对齐。 补充一些几个关键函数的调用路径和简单的内部实现描述 HAL_UART_Transmit_DMA 1. 全局状态 gState = HAL_UART_STATE_BUSY_TX 2. 调用HAL_DMA_Start_IT 3. DMA状态hdma->State = HAL_DMA_STATE_BUSY; 4. 开启外设DMA __HAL_DMA_ENABLE(hdma); 5. 执行 SET_BIT(huart->Instance->CR3, USART_CR3_DMAT); 数据就被发出去了 UART_EndTransmit_IT 1. 全局状态 huart->gState = HAL_UART_STATE_READY; 2. HAL_UART_TxCpltCallback(huart); UART_EndRxTransfer(huart); 1. 接收状态恢复 huart->RxState = HAL_UART_STATE_READY; 2. 解除中断跳转 huart->RxISR = NULL; HAL_UART_Receive_DMA 1. 判断if (huart->RxState == HAL_UART_STATE_READY),不是READY的话之前退出 2. 接收状态 huart->RxState = HAL_UART_STATE_BUSY_RX; 3. 调用HAL_DMA_Start_IT 4. DMA状态hdma->State = HAL_DMA_STATE_BUSY; 5. 开启外设DMA __HAL_DMA_ENABLE(hdma); HAL_UART_DMAStop 1. 判断是不是有发送请求 如果有,停止发送 2. 判断是不是有接收请求 如果有,停止接收 3. 终止DMA传输 HAL_DMA_Abort 调用 __HAL_DMA_DISABLE(hdma);关闭外设DMA 在调用DMA发送之前一定要做一个判断,判断上一次发送有没有完成,以免出现发送间隔过快,前一次发送没有完成后一次马上又开始导致HAL库函数出现HAL_BUSY的返回值,具体做法可以在调用前判断发送完成标志,或者在HAL库串口发送完成回调函数里面做一个标志位,完成即置位,在发送前判断改标志必须为1才可以进行发送,否则不进行。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1780 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1621 浏览 1 评论
1081 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
728 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1679 浏览 2 评论
1938浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
731浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
570浏览 3评论
596浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
556浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 16:46 , Processed in 1.024088 second(s), Total 78, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号