STM32H743 USART1 LL 库
程序员文章站
2024-02-22 12:07:46
...
空闲中断+DMA接收数据
使用LL库配置,可与HAL库一起使用,0级优化编译文件大小如下:
1.工程目录
2.代码配置
usart1.h
主要定义接收缓存,发送缓存,处理缓存大小
#ifndef _USART1_H
#define _USART1_H
#include "stm32h7xx.h"
#define USART1_TX_BUFFER_SIZE (1 * 1024)
#define USART1_RX_BUFFER_SIZE (1 * 1024)
#define USART1_RX_HANDLE_SIZE (1 * 1024)
extern uint8_t USART1_TX_BUFFER[USART1_TX_BUFFER_SIZE];
extern uint8_t USART1_RX_BUFFER[USART1_RX_BUFFER_SIZE];
extern uint8_t USART1_RX_HANDLE[USART1_RX_HANDLE_SIZE];
extern uint32_t USART_RX_CNT; //接收的字节数
void IAP_USART1_Init(void);
void DMA_START(DMA_TypeDef *DMAx, uint32_t Stream, uint32_t *SRC_ADDR, uint32_t *DES_ADDR, uint32_t Data_Len, uint32_t Direction);
#endif
usart1.c
DMA1的USART1 TX RX都配置好了,但是一般不需要,所以虽然配置了但未使用
#include "usart1.h"
#include "string.h"
#include "stm32h7xx_ll_utils.h"
#include "stm32h7xx_ll_dma.h"
#include "stm32h7xx_ll_usart.h"
#include "stm32h7xx_ll_gpio.h"
uint8_t USART1_TX_BUFFER[USART1_TX_BUFFER_SIZE] = {0};
uint8_t USART1_RX_BUFFER[USART1_RX_BUFFER_SIZE] = {0};
uint8_t USART1_RX_HANDLE[USART1_RX_HANDLE_SIZE] = {0};
uint32_t USART_RX_CNT = 0; //接收的字节数
/**
* @brief 配置USART1串口.
*/
void USART1_UART_Init(void)
{
LL_USART_InitTypeDef USART_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
//开启外设 USART1 时钟
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);
//开启 GPIOA 时钟
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOA);
//USART1 GPIO Configuration
//PA9 ------> USART1_TX
//PA10 ------> USART1_RX
GPIO_InitStruct.Pin = LL_GPIO_PIN_9|LL_GPIO_PIN_10;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
//初始化 PA9 PA10
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1; //时钟不分频
USART_InitStruct.BaudRate = 512000; //波特率512000
USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B; //数据宽度8位
USART_InitStruct.StopBits = LL_USART_STOPBITS_1; //一个停止位
USART_InitStruct.Parity = LL_USART_PARITY_NONE; //无奇偶校验
USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX; //开启TX RX
USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; //无硬件流控制
USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16; //16倍过采样
//初始化 USART1
LL_USART_Init(USART1, &USART_InitStruct);
LL_USART_SetTXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_8);//1/8 FIFO
LL_USART_SetRXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_8);
//LL_USART_EnableFIFO(USART1);
LL_USART_DisableFIFO(USART1); //不使用 FIFO
LL_USART_ConfigAsyncMode(USART1); //异步模式
//使能 USART1
LL_USART_Enable(USART1);
LL_USART_ClearFlag_TC(USART1);
/* USART1 interrupt Init */
NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));//优先级分组4,抢占优先级0,响应优先级0
//LL_USART_EnableIT_TC(USART1); //开启发送完成中断
//LL_USART_EnableIT_RXNE_RXFNE(USART1); //开启接收中断
LL_USART_EnableIT_IDLE(USART1); //开启空闲中断
NVIC_EnableIRQ(USART1_IRQn);
/* Polling USART1 initialisation */
while((!(LL_USART_IsActiveFlag_TEACK(USART1))) || (!(LL_USART_IsActiveFlag_REACK(USART1))))
{
}
}
/**
* @brief 配置USART1 DMA.
*/
void USART1_DMA_Init(void)
{
LL_DMA_InitTypeDef DMA_Init_Struct;
//开启DMA1时钟
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
//DMA1 STREAM_0 ------- USART1_TX
//DMA1 STREAM_1 ------- USART1_RX
/* //USART1 TX DMA配置
DMA_Init_Struct.PeriphRequest = LL_DMAMUX1_REQ_USART1_TX; //USART1 TX请求
DMA_Init_Struct.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;//传输方向:内存到外设
DMA_Init_Struct.PeriphOrM2MSrcAddress = (uint32_t)&USART1->TDR; //外设地址
DMA_Init_Struct.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE; //外设数据对齐宽度:字节
DMA_Init_Struct.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; //外设地址不自增
DMA_Init_Struct.MemoryOrM2MDstAddress = (uint32_t) USART1_TX_BUFFER; //内存地址
DMA_Init_Struct.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE; //内存数据对齐宽度:字节
DMA_Init_Struct.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; //内存地址自增
DMA_Init_Struct.NbData = USART1_TX_BUFFER_SIZE; //传输数据数量
DMA_Init_Struct.Mode = LL_DMA_MODE_NORMAL; //普通模式
DMA_Init_Struct.Priority = LL_DMA_PRIORITY_HIGH; //优先级高
DMA_Init_Struct.FIFOMode = LL_DMA_FIFOMODE_DISABLE; //关闭FIFO
DMA_Init_Struct.FIFOThreshold = LL_DMA_FIFOTHRESHOLD_FULL;
DMA_Init_Struct.MemBurst = LL_DMA_MBURST_SINGLE; //内存单次突发传输
DMA_Init_Struct.PeriphBurst = LL_DMA_PBURST_SINGLE; //外设单次突发传输
LL_DMA_Init(DMA1, LL_DMA_STREAM_0, &DMA_Init_Struct);
LL_DMA_ClearFlag_TC0(DMA1);
//LL_DMA_EnableIT_TC(DMA1, LL_DMA_STREAM_0);
LL_DMA_DisableStream(DMA1, LL_DMA_STREAM_0);
*/
//USART1 RX DMA配置
DMA_Init_Struct.PeriphRequest = LL_DMAMUX1_REQ_USART1_RX; //USART1 RX请求
DMA_Init_Struct.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;//传输方向:外设到内存
DMA_Init_Struct.PeriphOrM2MSrcAddress = (uint32_t)&USART1->RDR; //外设地址
DMA_Init_Struct.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE; //外设数据对齐宽度:字节
DMA_Init_Struct.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; //外设地址不自增
DMA_Init_Struct.MemoryOrM2MDstAddress = (uint32_t) USART1_RX_BUFFER; //内存地址
DMA_Init_Struct.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE; //内存数据对齐宽度:字节
DMA_Init_Struct.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; //内存地址自增
DMA_Init_Struct.NbData = USART1_RX_BUFFER_SIZE; //传输数据数量
DMA_Init_Struct.Mode = LL_DMA_MODE_NORMAL; //普通模式
DMA_Init_Struct.Priority = LL_DMA_PRIORITY_HIGH; //优先级高
DMA_Init_Struct.FIFOMode = LL_DMA_FIFOMODE_DISABLE; //关闭FIFO
DMA_Init_Struct.FIFOThreshold = LL_DMA_FIFOTHRESHOLD_FULL;
DMA_Init_Struct.MemBurst = LL_DMA_MBURST_SINGLE; //内存单次突发传输
DMA_Init_Struct.PeriphBurst = LL_DMA_PBURST_SINGLE; //外设单次突发传输
LL_DMA_Init(DMA1, LL_DMA_STREAM_1, &DMA_Init_Struct);
LL_DMA_ClearFlag_TC1(DMA1);
LL_DMA_EnableIT_TC(DMA1, LL_DMA_STREAM_1);
LL_DMA_DisableStream(DMA1, LL_DMA_STREAM_1);
/* DMA interrupt init */
/* DMA1_Stream0_IRQn interrupt configuration */
// NVIC_SetPriority(DMA1_Stream0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
// NVIC_EnableIRQ(DMA1_Stream0_IRQn);
/* DMA1_Stream1_IRQn interrupt configuration */
NVIC_SetPriority(DMA1_Stream1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(DMA1_Stream1_IRQn);
}
/**
* @brief 配置 USART1 功能.
*/
void IAP_USART1_Init(void)
{
USART1_UART_Init();
USART1_DMA_Init();
//使能DMA请求
//LL_USART_EnableDMAReq_TX(USART1);
LL_USART_EnableDMAReq_RX(USART1);
}
/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
uint32_t RX_DATA_LEN = 0;
// if(LL_USART_IsActiveFlag_TC(USART1) != RESET)//发送完成中断
// {
// LL_USART_ClearFlag_TC(USART1);
// }
// if(LL_USART_IsActiveFlag_RXNE_RXFNE(USART1) != RESET)//接收中断
// {
// USART1_RX_BUFFER[0] = (uint8_t)USART1->RDR;
//
// }
if(LL_USART_IsActiveFlag_IDLE(USART1) != RESET)//空闲中断
{
LL_DMA_DisableStream(DMA1, LL_DMA_STREAM_1);//关闭DMA
LL_USART_ClearFlag_IDLE(USART1);
LL_DMA_ClearFlag_TC1(DMA1);
//计算DMA传输字节数, 最大字节数 USART1_RX_BUFFER_SIZE
RX_DATA_LEN = USART1_RX_BUFFER_SIZE - LL_DMA_GetDataLength(DMA1, LL_DMA_STREAM_1);
//如果缓存未满
if((USART_RX_CNT + RX_DATA_LEN) < USART1_RX_HANDLE_SIZE)
{
//复制数据到处理缓存
memcpy(USART1_RX_HANDLE, USART1_RX_BUFFER, RX_DATA_LEN);
USART_RX_CNT = RX_DATA_LEN;
}
//再次开启DMA接收
DMA_START(DMA1, LL_DMA_STREAM_1, (uint32_t *)&USART1->RDR , (uint32_t *)USART1_RX_BUFFER, USART1_RX_BUFFER_SIZE, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
}
}
void DMA_START(DMA_TypeDef *DMAx, uint32_t Stream, uint32_t *SRC_ADDR, uint32_t *DES_ADDR, uint32_t Data_Len, uint32_t Direction)
{
//LL_DMA_DisableStream(DMAx, Stream);
//DMAx->LIFCR = 0x00000F40U;
LL_DMA_ConfigAddresses(DMAx, Stream, (uint32_t)SRC_ADDR, (uint32_t)DES_ADDR, Direction);
LL_DMA_SetDataLength(DMAx, Stream, Data_Len);
LL_DMA_EnableStream(DMAx, Stream);
//LL_DMA_EnableBufferableTransfer(DMAx, Stream);
}
/**
* @brief This function handles DMA1 stream0 global interrupt.
*/
void DMA1_Stream0_IRQHandler(void)
{
if(LL_DMA_IsActiveFlag_TC0(DMA1) != RESET)//DMA1_Stream0 传输完成中断,USART1_TX
{
LL_DMA_DisableStream(DMA1, LL_DMA_STREAM_0);//关闭DMA
LL_DMA_ClearFlag_TC0(DMA1);
}
}
/**
* @brief This function handles DMA1 stream1 global interrupt.
*/
void DMA1_Stream1_IRQHandler(void)
{
if(LL_DMA_IsActiveFlag_TC1(DMA1) != RESET)//DMA1_Stream1 传输完成中断, USART1_RX
{
LL_DMA_DisableStream(DMA1, LL_DMA_STREAM_1);//关闭DMA
LL_DMA_ClearFlag_TC1(DMA1);
}
}
main.h
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32h7xx_ll_dma.h"
#include "stm32h7xx_ll_rcc.h"
#include "stm32h7xx_ll_crs.h"
#include "stm32h7xx_ll_bus.h"
#include "stm32h7xx_ll_system.h"
#include "stm32h7xx_ll_exti.h"
#include "stm32h7xx_ll_cortex.h"
#include "stm32h7xx_ll_utils.h"
#include "stm32h7xx_ll_pwr.h"
#include "stm32h7xx_ll_usart.h"
#include "stm32h7xx.h"
#include "stm32h7xx_ll_gpio.h"
#if defined(USE_FULL_ASSERT)
#include "stm32_assert.h"
#endif /* USE_FULL_ASSERT */
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void SystemClock_Config(void);
void Error_Handler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
#ifndef NVIC_PRIORITYGROUP_0
#define NVIC_PRIORITYGROUP_0 ((uint32_t)0x00000007) /*!< 0 bit for pre-emption priority,
4 bits for subpriority */
#define NVIC_PRIORITYGROUP_1 ((uint32_t)0x00000006) /*!< 1 bit for pre-emption priority,
3 bits for subpriority */
#define NVIC_PRIORITYGROUP_2 ((uint32_t)0x00000005) /*!< 2 bits for pre-emption priority,
2 bits for subpriority */
#define NVIC_PRIORITYGROUP_3 ((uint32_t)0x00000004) /*!< 3 bits for pre-emption priority,
1 bit for subpriority */
#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003) /*!< 4 bits for pre-emption priority,
0 bit for subpriority */
#endif
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
main.c
不断查询是否接收到数据,如果接收到数据,发送接收的数据
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart1.h"
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
LL_APB4_GRP1_EnableClock(LL_APB4_GRP1_PERIPH_SYSCFG);
NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);//组4:4位抢占优先级,0位响应优先级
SystemClock_Config();
IAP_USART1_Init();
while (1)
{
if(USART_RX_CNT)//接收到数据
{
for(uint32_t count = 0; count < USART_RX_CNT; count ++)
{
//等待发送寄存器为空
while(LL_USART_IsActiveFlag_TXE_TXFNF(USART1) == RESET);
//填入数据
LL_USART_TransmitData8(USART1, USART1_RX_HANDLE[count]);
}
//清空接收数据数
USART_RX_CNT = 0;
}
else
{
//LL_mDelay(100);
}
}
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
LL_FLASH_SetLatency(LL_FLASH_LATENCY_2);
if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_2)
{
Error_Handler();
}
LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY);
LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
LL_RCC_HSI_Enable();
/* Wait till HSI is ready */
while(LL_RCC_HSI_IsReady() != 1)
{
}
LL_RCC_HSI_SetCalibTrimming(32);
LL_RCC_HSI_SetDivider(LL_RCC_HSI_DIV1);
LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSI);
LL_RCC_PLL1P_Enable();
LL_RCC_PLL1_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_2_4);
LL_RCC_PLL1_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
LL_RCC_PLL1_SetM(32);
LL_RCC_PLL1_SetN(400);
LL_RCC_PLL1_SetP(2);
LL_RCC_PLL1_SetQ(2);
LL_RCC_PLL1_SetR(2);
LL_RCC_PLL1_Enable();
/* Wait till PLL is ready */
while(LL_RCC_PLL1_IsReady() != 1)
{
};
/* Intermediate AHB prescaler 2 when target frequency clock is higher than 80 MHz */
LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2);
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1);
LL_RCC_SetSysPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2);
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2);
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_2);
LL_RCC_SetAPB3Prescaler(LL_RCC_APB3_DIV_2);
LL_RCC_SetAPB4Prescaler(LL_RCC_APB4_DIV_2);
LL_Init1msTick(400000000);
LL_SetSystemCoreClock(400000000);
LL_RCC_SetUSARTClockSource(LL_RCC_USART16_CLKSOURCE_PCLK2);
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
3.运行结果
4.参考链接
链接: STM32之串口DMA接收不定长数据.