本文主要是介绍STM32 | 基于 HAL 库实现 DMA 驱动 GPIO 高速翻转,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
项目中有一款点阵式液晶驱动芯片,需要用 IO 口翻转来实现高速串转并传输,主控芯片为 STM32F103RCT6。如果直接采用库函数进行IO的翻转不仅速度上满足不了要求,还会占用大量时间影响性能,导致时序上的错误。DMA可以在没有控制器的干预下进行数据的传输,因此决定采用DMA方式来驱动IO。本文以 HAL 库实现 DMA 驱动 GPIO 高速翻转为例说明DMA的配置过程,当然也可以改变 dma_buff
数组以实现其他任意时序的输出。
一、STM32CubeMX 配置
选择外部高速时钟。
选择 DMA1
的 Channel 1
,传输方向选择 MEMTOMEM
,使能源地址增加,传输模式这里只能选择为 Normal
,如果需要使用循环模式后续可在代码中修改。PB
口共有16个管脚,数据宽度选择 Word
。
将PB0
管脚配置为输出管脚,后续在代码中将整个 PB
口管脚配置为输出,以便通过示波器或者逻辑分析仪观察输出。
二、代码修改
-
修改 DMA 配置
STM32CubeMX 中
DMA
只能选择Normal
模式,在void MX_DMA_Init(void)
函数中将DMA模式由DMA_NORMAL
更改为DMA_CIRCULAR
模式:/*** Enable DMA controller clock* Configure DMA for memory to memory transfers* hdma_memtomem_dma1_channel1*/ void MX_DMA_Init(void) {/* DMA controller clock enable */__HAL_RCC_DMA1_CLK_ENABLE();/* Configure DMA request hdma_memtomem_dma1_channel1 on DMA1_Channel1 */hdma_memtomem_dma1_channel1.Instance = DMA1_Channel1;hdma_memtomem_dma1_channel1.Init.Direction = DMA_MEMORY_TO_MEMORY;hdma_memtomem_dma1_channel1.Init.PeriphInc = DMA_PINC_ENABLE;hdma_memtomem_dma1_channel1.Init.MemInc = DMA_MINC_DISABLE;hdma_memtomem_dma1_channel1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;hdma_memtomem_dma1_channel1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;hdma_memtomem_dma1_channel1.Init.Mode = DMA_CIRCULAR;hdma_memtomem_dma1_channel1.Init.Priority = DMA_PRIORITY_LOW;if(HAL_DMA_Init(&hdma_memtomem_dma1_channel1) != HAL_OK){Error_Handler();}}
-
修改GPIO定义
在 STM32CubeMX 中仅设置了 PB0 管脚,在 void MX_GPIO_Init(void) 中将 PB 口的十六个管脚都设置为输出,将原有的
LED_Pin
修改为GPIO_PIN_All
即可。/** Configure pins as* Analog* Input* Output* EVENT_OUT* EXTI */ void MX_GPIO_Init(void) {GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOD_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(LED_GPIO_Port, GPIO_PIN_All, GPIO_PIN_RESET);/*Configure GPIO pin : PtPin */GPIO_InitStruct.Pin = GPIO_PIN_All;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);}
-
定义 DMA 缓冲区
/* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ uint16_t dma_buff[8] = {0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA}; /* USER CODE END 0 */
-
启动 DMA 传输
/* USER CODE BEGIN 2 */ HAL_DMA_Start(&hdma_memtomem_dma1_channel1, (uint32_t)(dma_buff), (uint32_t)(&GPIOB->ODR), sizeof(dma_buff)/sizeof(dma_buff[0])); /* USER CODE END 2 */
三、下载验证
通过逻辑分析仪抓取的波形可以看出,IO 的翻转频率为3.57MHz,脉宽为140ns,实验数据与程序中的设置完全吻合。
【注】完整工程以及配置过程可在此处下载。
这篇关于STM32 | 基于 HAL 库实现 DMA 驱动 GPIO 高速翻转的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!