stm32f429 HAL库 freertos 实现USART1 printf输出 使用DMA发送数据DMA传输完成并发送信号量
以下是使用STM32F429 HAL库和FreeRTOS实现USART1 printf输出并使用DMA发送数据DMA传输完成并发送信号量的步骤:
-
在CubeMX中配置USART1和DMA
- 在Pinout & Configuration中,将USART1的TX引脚配置为GPIO_AF7_USART1,并启用USART1
- 在DMA中,启用DMA2和USART1 TX的DMA通道
-
在main.c中添加以下代码:
#include "stdio.h" #include "FreeRTOS.h" #include "task.h" #include "semphr.h" #include "stm32f4xx_hal.h" UART_HandleTypeDef huart1; DMA_HandleTypeDef hdma_usart1_tx; SemaphoreHandle_t xSemaphore; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_DMA_Init(void); static void MX_USART1_UART_Init(void); int __io_putchar(int ch) { HAL_UART_Transmit_DMA(&huart1, (uint8_t*)&ch, 1); xSemaphoreTake(xSemaphore, portMAX_DELAY); return ch; } void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { xSemaphoreGiveFromISR(xSemaphore, pdFALSE); } int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_DMA_Init(); MX_USART1_UART_Init(); xSemaphore = xSemaphoreCreateBinary(); xSemaphoreGive(xSemaphore); printf("Hello World!\r\n"); while (1) { vTaskDelay(1000); } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 25; RCC_OscInitStruct.PLL.PLLN = 360; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 7; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); /* SysTick_IRQn interrupt configuration */ HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); } static 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; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } } static void MX_DMA_Init(void) { __HAL_RCC_DMA2_CLK_ENABLE(); 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(&huart1, hdmatx, hdma_usart1_tx); HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 5, 0); HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn); } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } void DMA2_Stream7_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_usart1_tx); } void _Error_Handler(char *file, int line) { printf("Error: %s:%d\r\n", file, line); while(1); } -
在Makefile中添加以下代码:
CFLAGS += -DUSE_HAL_DRIVER CFLAGS += -DSTM32F429xx CFLAGS += -DUSE_FULL_ASSERT CFLAGS += -DUSE_STDPERIPH_DRIVER CFLAGS += -DPRINTF_FLOAT_ENABLE CFLAGS += -DPRINTF_ADVANCED_ENABLE CFLAGS += -D__FPU_PRESENT=1 CFLAGS += -DARM_MATH_CM4 CFLAGS += -D__FPU_USED=1 CFLAGS += -I$(HAL)/Inc CFLAGS += -I$(HAL)/../CMSIS/Device/ST/STM32F4xx/Include CFLAGS += -I$(HAL)/../CMSIS/Include CFLAGS += -I$(HAL)/../STM32F4xx_HAL_Driver/Inc CFLAGS += -I$(FREERTOS)/include CFLAGS += -I$(FREERTOS)/portable/GCC/ARM_CM4F CFLAGS += -I$(FREERTOS)/portable/MemMang SRCS += $(HAL)/Src/*.c SRCS += $(HAL)/../STM32F4xx_HAL_Driver/Src/*.c SRCS += $(FREERTOS)/portable/GCC/ARM_CM4F/port.c SRCS += $(FREERTOS)/portable/MemMang/heap_4.c SRCS += $(FREERTOS)/tasks.c SRCS += $(FREERTOS)/list.c SRCS += $(FREERTOS)/queue.c SRCS += $(FREERTOS)/timers.c -
编译并烧录程序,可以看到串口输出“Hello World!”,并且使用DMA发送数据
原文地址: https://www.cveoy.top/t/topic/dnKS 著作权归作者所有。请勿转载和采集!