完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
STM32高端MCU(F4、F7等)支持DMA双缓冲,低端MCU(F1)不支持DMA双缓冲,不过有替代方案可实现类型效果。
一、MCU支持DMAA双缓冲的 、MCU不支持DMA双缓冲,但可通过DMA传输半完成中断替代,以下代码已在F103上验证。 1.先通过STM32CubeMX生成串口初始化代码 串口接收DMA一定要选择方式模式,并且能够使串口接收中断 2.使能中断循环,故障中断中中断接收数据 3.在DAM接收半、完成中断中取出接收数据 usart.c: /* Includes ------------------------------------------------------------------*/ #include “usart.h” /* USER CODE BEGIN 0 */ #define DE_UART_DMA_BUF_LEN 128 extern void at_uart_recv_data(uint8_t *pdata, uint16_t len); static volatile uint8_t RecvDMABuf[DE_UART_DMA_BUF_LEN]; static volatile uint8_t RecvLastIdx = 0; /* USER CODE END 0 */ UART_HandleTypeDef huart1; DMA_HandleTypeDef hdma_usart1_tx; DMA_HandleTypeDef hdma_usart1_rx; /* USART1 init function */ void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } } void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(uartHandle-》Instance==USART1) { /* USER CODE BEGIN USART1_MspInit 0 */ /* USER CODE END USART1_MspInit 0 */ /* USART1 clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART1 GPIO Configuration PA9 ------》 USART1_TX PA10 ------》 USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART1 DMA Init */ /* USART1_TX Init */ hdma_usart1_tx.Instance = DMA1_Channel4; 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; if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx); /* USART1_RX Init */ hdma_usart1_rx.Instance = DMA1_Channel5; 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_CIRCULAR; hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW; if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx); /* USART1 interrupt Init */ HAL_NVIC_SetPriority(USART1_IRQn, 5, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); /* USER CODE BEGIN USART1_MspInit 1 */ /*Enable the IDLE Interrupt*/ __HAL_UART_ENABLE_IT(uartHandle,UART_IT_IDLE); __HAL_UART_CLEAR_IDLEFLAG(uartHandle); /* USER CODE END USART1_MspInit 1 */ } } void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) { if(uartHandle-》Instance==USART1) { /* USER CODE BEGIN USART1_MspDeInit 0 */ /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); /**USART1 GPIO Configuration PA9 ------》 USART1_TX PA10 ------》 USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); /* USART1 DMA DeInit */ HAL_DMA_DeInit(uartHandle-》hdmatx); HAL_DMA_DeInit(uartHandle-》hdmarx); /* USART1 interrupt Deinit */ HAL_NVIC_DisableIRQ(USART1_IRQn); /* USER CODE BEGIN USART1_MspDeInit 1 */ /* USER CODE END USART1_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ /** * @brief Rx Half Transfer completed callbacks. * @param huart Pointer to a UART_HandleTypeDef structure that contains * the configuration information for the specified UART module. * @retval None */ void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) { if(huart-》Instance == huart1.Instance) { //DebugPrintf(“HAL_UART_RxHalfCpltCallbackn”); uint32_t TotalLen = DE_UART_DMA_BUF_LEN - __HAL_DMA_GET_COUNTER(huart-》hdmarx); if(TotalLen 》 RecvLastIdx) { uint32_t RecvLen = TotalLen - RecvLastIdx; at_uart_recv_data((uint8_t *)&RecvDMABuf[RecvLastIdx],RecvLen); RecvLastIdx = TotalLen; } } } /** * @brief Rx Transfer completed callbacks. * @param huart Pointer to a UART_HandleTypeDef structure that contains * the configuration information for the specified UART module. * @retval None */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart-》Instance == huart1.Instance) { //DebugPrintf(“HAL_UART_RxCpltCallbackn”); uint32_t TotalLen = DE_UART_DMA_BUF_LEN; if(TotalLen 》 RecvLastIdx) { uint32_t RecvLen = TotalLen - RecvLastIdx; at_uart_recv_data((uint8_t *)&RecvDMABuf[RecvLastIdx],RecvLen); RecvLastIdx = 0; } } } /** * @brief Rx IDLE callback * @param huart: UART handle. * @note This example shows a simple way to report end of DMA Tx transfer, and * you can add your own implementation. * @retval None */ static void UART_IDLE_CallBack(UART_HandleTypeDef *huart) { if(huart-》Instance == huart1.Instance) { //DebugPrintf(“UART_IDLE_CallBackn”); uint32_t TotalLen = DE_UART_DMA_BUF_LEN - __HAL_DMA_GET_COUNTER(huart-》hdmarx); //DebugPrintf(“TotalLen:%dn”,TotalLen); if(TotalLen 》 RecvLastIdx) { uint32_t RecvLen = TotalLen - RecvLastIdx; at_uart_recv_data((uint8_t *)&RecvDMABuf[RecvLastIdx],RecvLen); RecvLastIdx = TotalLen; } } } /** * @brief UART_Idle_IRQHandler * @param huart Pointer to a UART_HandleTypeDef structure that contains * the configuration information for the specified UART module. * @retval HAL status */ void UART_Idle_IRQHandler(UART_HandleTypeDef *huart) { if(__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET) { __HAL_UART_CLEAR_IDLEFLAG(huart); __HAL_UART_FLUSH_DRREGISTER(huart); UART_IDLE_CallBack(huart); } } void UART1_StartReceiveDMA(void) { HAL_UART_Receive_DMA(&huart1,(uint8_t *)RecvDMABuf,sizeof(RecvDMABuf)); } |
|
|
|
stm32f1xx_it.c
/* Includes ------------------------------------------------------------------*/ #include “main.h” #include “stm32f1xx_it.h” /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN TD */ /* USER CODE END TD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ extern void UART_Idle_IRQHandler(UART_HandleTypeDef *huart); /* USER CODE END 0 */ /* External variables --------------------------------------------------------*/ extern DMA_HandleTypeDef hdma_usart1_tx; extern DMA_HandleTypeDef hdma_usart1_rx; extern UART_HandleTypeDef huart1; extern TIM_HandleTypeDef htim2; /* USER CODE BEGIN EV */ /* USER CODE END EV */ /******************************************************************************/ /* Cortex-M3 Processor Interruption and Exception Handlers */ /******************************************************************************/ /** * @brief This function handles Non maskable interrupt. */ void NMI_Handler(void) { /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ /* USER CODE END NonMaskableInt_IRQn 0 */ /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ /* USER CODE END NonMaskableInt_IRQn 1 */ } /** * @brief This function handles Hard fault interrupt. */ void HardFault_Handler(void) { /* USER CODE BEGIN HardFault_IRQn 0 */ /* USER CODE END HardFault_IRQn 0 */ while (1) { /* USER CODE BEGIN W1_HardFault_IRQn 0 */ /* USER CODE END W1_HardFault_IRQn 0 */ } } /** * @brief This function handles Memory management fault. */ void MemManage_Handler(void) { /* USER CODE BEGIN MemoryManagement_IRQn 0 */ /* USER CODE END MemoryManagement_IRQn 0 */ while (1) { /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */ /* USER CODE END W1_MemoryManagement_IRQn 0 */ } } /** * @brief This function handles Prefetch fault, memory access fault. */ void BusFault_Handler(void) { /* USER CODE BEGIN BusFault_IRQn 0 */ /* USER CODE END BusFault_IRQn 0 */ while (1) { /* USER CODE BEGIN W1_BusFault_IRQn 0 */ /* USER CODE END W1_BusFault_IRQn 0 */ } } /** * @brief This function handles Undefined instruction or illegal state. */ void UsageFault_Handler(void) { /* USER CODE BEGIN UsageFault_IRQn 0 */ /* USER CODE END UsageFault_IRQn 0 */ while (1) { /* USER CODE BEGIN W1_UsageFault_IRQn 0 */ /* USER CODE END W1_UsageFault_IRQn 0 */ } } /** * @brief This function handles Debug monitor. */ void DebugMon_Handler(void) { /* USER CODE BEGIN DebugMonitor_IRQn 0 */ /* USER CODE END DebugMonitor_IRQn 0 */ /* USER CODE BEGIN DebugMonitor_IRQn 1 */ /* USER CODE END DebugMonitor_IRQn 1 */ } /******************************************************************************/ /* STM32F1xx Peripheral Interrupt Handlers */ /* Add here the Interrupt Handlers for the used peripherals. */ /* For the available peripheral interrupt handler names, */ /* please refer to the startup file (startup_stm32f1xx.s)。 */ /******************************************************************************/ /** * @brief This function handles DMA1 channel4 global interrupt. */ void DMA1_Channel4_IRQHandler(void) { /* USER CODE BEGIN DMA1_Channel4_IRQn 0 */ /* USER CODE END DMA1_Channel4_IRQn 0 */ HAL_DMA_IRQHandler(&hdma_usart1_tx); /* USER CODE BEGIN DMA1_Channel4_IRQn 1 */ /* USER CODE END DMA1_Channel4_IRQn 1 */ } /** * @brief This function handles DMA1 channel5 global interrupt. */ void DMA1_Channel5_IRQHandler(void) { /* USER CODE BEGIN DMA1_Channel5_IRQn 0 */ /* USER CODE END DMA1_Channel5_IRQn 0 */ HAL_DMA_IRQHandler(&hdma_usart1_rx); /* USER CODE BEGIN DMA1_Channel5_IRQn 1 */ /* USER CODE END DMA1_Channel5_IRQn 1 */ } /** * @brief This function handles TIM2 global interrupt. */ void TIM2_IRQHandler(void) { /* USER CODE BEGIN TIM2_IRQn 0 */ /* USER CODE END TIM2_IRQn 0 */ HAL_TIM_IRQHandler(&htim2); /* USER CODE BEGIN TIM2_IRQn 1 */ /* USER CODE END TIM2_IRQn 1 */ } /** * @brief This function handles USART1 global interrupt. */ void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ /* USER CODE END USART1_IRQn 0 */ HAL_UART_IRQHandler(&huart1); /* USER CODE BEGIN USART1_IRQn 1 */ UART_Idle_IRQHandler(&huart1); /* USER CODE END USART1_IRQn 1 */ } /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ 1、此时DMA状态类似一个FIFI,RecvLastIdx说明当前可以读取数据的查看位置。 2、在DMA不能解决中断和DMA解决继续中断后的中断方法中断中重复取接收数据,通过判断TotalLen RecvLastIdx可。 3、应该也适用于F4、F7等高端MCU。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1771 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1619 浏览 1 评论
1070 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
724 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1673 浏览 2 评论
1935浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
728浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
567浏览 3评论
593浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
551浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 11:29 , Processed in 0.949191 second(s), Total 78, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号