欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

STM32H743 USART1 LL 库

程序员文章站 2024-02-22 12:07:46
...

空闲中断+DMA接收数据

使用LL库配置,可与HAL库一起使用,0级优化编译文件大小如下:
STM32H743 USART1 LL 库

1.工程目录

STM32H743 USART1 LL 库

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>&copy; 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>&copy; 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.运行结果

STM32H743 USART1 LL 库

4.参考链接

链接: STM32之串口DMA接收不定长数据.