完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
1.使用STM32CubeMX配置的串口引脚设置和dma的设置会生成在usart.c。
1)如果DMA接收想采用循环缓冲区的方式,可以直接将RX-DMA设置成Circle方式,然后数据就会硬件上自动实现环形缓冲区的功能,省了不少时间。 2)DMA在采用Normal模式的时候,当一次任务完成后,DMA->DMA_BufferSize自动清零,并且DMA自动停止。如果想再次设置DMA的BufferSize的话,必须要进行如下操作: step1:DMA_CMD(DMAx_Channely,DISABLE); step2: 设置DMA_BufferLen step3:DMA_CMD(DMAx_Channely,ENABLE) 3)DMA采用Circle模式的时候,在发送或者接受完成之后,仍然保存着BufferSize,并且DMA还处于使能状态,一直连续工作,直到用户停止DMA else if(uartHandle->Instance==USART1) { /* USER CODE BEGIN USART1_MspInit 0 */ /* USER CODE END USART1_MspInit 0 */ /* USART1 clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); /**USART1 GPIO Configuration PA9 ------> USART1_TX PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART1 DMA Init */ /* USART1_RX Init */ hdma_usart1_rx.Instance = DMA2_Stream2; hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4; hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart1_rx.Init.Mode = DMA_NORMAL; //这里设成DMA_CIRCULAR和DMA_NORMAL好像没有对双缓冲造成影响 hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW; hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx); /* USART1_TX Init */ hdma_usart1_tx.Instance = DMA2_Stream7; hdma_usart1_tx.Init.Channel = DMA_CHANNEL_4; hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart1_tx.Init.Mode = DMA_NORMAL; hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW; hdma_usart1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } __HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx); /* USART1 interrupt Init */ HAL_NVIC_SetPriority(USART1_IRQn, 5, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); /* USER CODE BEGIN USART1_MspInit 1 */ /* USER CODE END USART1_MspInit 1 */ } 2.下面是关于DMA双缓冲机制的配置,特别说明一下,我先__HAL_DMA_DISABLE(hdma); 再配置后面的参数。DMA才正常接收数据了。 static HAL_StatusTypeDef DMAEx_MultiBufferStart_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t SecondMemAddress, uint32_t DataLength) { HAL_StatusTypeDef status = HAL_OK; /* Memory-to-memory transfer not supported in double buffering mode */ if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY) { hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED; return HAL_ERROR; } /* Set the UART DMA transfer complete callback */ /* Current memory buffer used is Memory 1 callback */ hdma->XferCpltCallback = dma_m0_rxcplt_callback; //第一个缓冲区填满后会调用这个函数 /* Current memory buffer used is Memory 0 callback */ hdma->XferM1CpltCallback = dma_m1_rxcplt_callback; 第二个缓冲区填满后会调用这个函数 /* Check callback functions */ if ((NULL == hdma->XferCpltCallback) || (NULL == hdma->XferM1CpltCallback)) { hdma->ErrorCode = HAL_DMA_ERROR_PARAM; return HAL_ERROR; } /* Process locked */ __HAL_LOCK(hdma); /* Enable the peripheral */ __HAL_DMA_DISABLE(hdma); //先要禁止DMA后面的设置才会生效 //if(HAL_DMA_STATE_READY == hdma->State) //{ /* Change DMA peripheral state */ hdma->State = HAL_DMA_STATE_BUSY; /* Initialize the error code */ hdma->ErrorCode = HAL_DMA_ERROR_NONE; /* Enable the Double buffer mode */ hdma->Instance->CR |= (uint32_t)DMA_SxCR_DBM; /* Configure DMA Stream destination address */ hdma->Instance->M1AR = SecondMemAddress; /* Configure DMA Stream data length */ hdma->Instance->NDTR = DataLength; /* Configure the source, destination address */ if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH) { hdma->Instance->PAR = DstAddress; hdma->Instance->M0AR = SrcAddress; } else { hdma->Instance->PAR = SrcAddress; hdma->Instance->M0AR = DstAddress; } /* Clear TC flags */ __HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); /* Enable TC interrupts*/ hdma->Instance->CR |= DMA_IT_TC; /* Enable the peripheral */ __HAL_DMA_ENABLE(hdma); /* Change the DMA state */ hdma->State = HAL_DMA_STATE_READY; //} //else //{ // /* Return error status */ // status = HAL_BUSY; //} /* Process unlocked */ __HAL_UNLOCK(hdma); return status; } void debug_uart_init(void) { //open uart idle it __HAL_UART_CLEAR_IDLEFLAG(&DEBUG_HUART); __HAL_UART_ENABLE_IT(&DEBUG_HUART, UART_IT_IDLE);//设置了空闲中断。进入空闲中断就可以考虑处理数据了。如果数据量大就放到专门的任务里处理。 // Enable the DMA transfer for the receiver request SET_BIT(DEBUG_HUART.Instance->CR3, USART_CR3_DMAR); DMAEx_MultiBufferStart_IT(DEBUG_HUART.hdmarx, (uint32_t)&DEBUG_HUART.Instance->DR, (uint32_t)debug_dma_rxbuff[0], (uint32_t)debug_dma_rxbuff[1], UART_RX_DMA_SIZE); } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1632 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1559 浏览 1 评论
985 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
688 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1605 浏览 2 评论
1869浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
652浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
521浏览 3评论
539浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
508浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-25 06:12 , Processed in 0.753170 second(s), Total 79, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号