STM32 LL库串口收发

基于STM32F103RC操作
程序混用HAL和LL库

CubeMX配置

配置时钟

配置时钟1
配置时钟2

串口参数

  • 波特率:115200
  • 长度:8bit
  • 无校验
  • 1停止位
    串口参数配置

设置DMA

  • TX:默认内存到外设,以Byte传输,使用DMA2通道5(根据需求可按手册重映射)
  • RX:默认外设到内存,需将模式改为循环模式(当收到后续数据可以更新),以Byte传输,使用DMA2通道3(根据需求可按手册重映射)
  • 启用串口中断
    TX DMA配置

RX DMA配置

启用串口中断

项目生成

  • 将串口更换为LL库
  • 设置项目
    串口设置为LL库
    设置项目
    设置项目

编码

采用两级缓冲,同时一级缓冲(DMA直接建立通讯的内存数据)须定义为全局变量。

定义(main.h)

/* USER CODE BEGIN ET */
#define UART_TX_LEN			10
#define UART_RX_LEN			10
typedef struct
{
	/* L1 buffer */
	uint8_t txBuf[UART_TX_LEN];
	uint8_t rxBuf[UART_RX_LEN];
	
	_Bool rx_flag;
	uint8_t rx_len;
	
	/* L2 buffer */
	uint8_t txBuf2[UART_TX_LEN];
	uint8_t rxBuf2[UART_RX_LEN];
	
}UART_Struct_t;
extern UART_Struct_t UART_Struct;
/* USER CODE END ET */

/* USER CODE BEGIN EFP */
void UART_SendBuf(uint16_t len);
/* USER CODE END EFP */

DMA空闲中断接收(stm32f1xx_it.c)

/* USER CODE BEGIN Includes */
#include <string.h>
/* USER CODE END Includes */

/**
  * @brie
  * f This function handles UART4 global interrupt.
  */
void UART4_IRQHandler(void)
{
  /* USER CODE BEGIN UART4_IRQn 0 */
	if (LL_USART_IsActiveFlag_IDLE(UART4))
	{
		LL_DMA_DisableChannel(DMA2, LL_DMA_CHANNEL_3);
		uint16_t len = UART_RX_LEN - LL_DMA_GetDataLength(DMA2, LL_DMA_CHANNEL_3) - 1;
		if (len <= 0) len = UART_RX_LEN - 1;
		UART_Struct.rx_len = len;
		memcpy(UART_Struct.rxBuf2, UART_Struct.rxBuf, len);
		LL_DMA_SetDataLength(DMA2, LL_DMA_CHANNEL_3, len);
		UART_Struct.rx_flag = 1;
		LL_DMA_EnableChannel(DMA2, LL_DMA_CHANNEL_3);
		
		LL_USART_ClearFlag_IDLE(UART4);
	}
	
  /* USER CODE END UART4_IRQn 0 */
  /* USER CODE BEGIN UART4_IRQn 1 */

  /* USER CODE END UART4_IRQn 1 */
}

DMA发送(main.c)

/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdio.h>
/* USER CODE END Includes */

/* USER CODE BEGIN PV */
UART_Struct_t UART_Struct;
/* USER CODE END PV */

/* USER CODE BEGIN 0 */
void UART_DMA_Init(void)
{
	/* RX DMA Config */
	LL_DMA_SetMemoryAddress(DMA2, LL_DMA_CHANNEL_3, (uint32_t)UART_Struct.rxBuf);
	LL_DMA_SetPeriphAddress(DMA2, LL_DMA_CHANNEL_3, (uint32_t)(&UART4->DR));
	LL_DMA_SetDataLength(DMA2, LL_DMA_CHANNEL_3, UART_RX_LEN);
	LL_DMA_EnableChannel(DMA2, LL_DMA_CHANNEL_3);
	
	/* TX DMA Config */
	LL_DMA_SetMemoryAddress(DMA2, LL_DMA_CHANNEL_5, (uint32_t)UART_Struct.txBuf);
	LL_DMA_SetPeriphAddress(DMA2, LL_DMA_CHANNEL_5, (uint32_t)(&UART4->DR));
	LL_DMA_SetDataLength(DMA2, LL_DMA_CHANNEL_5, UART_TX_LEN);
	
	/* UART Enable */
	LL_USART_EnableIT_IDLE(UART4);
	LL_USART_EnableDMAReq_RX(UART4);
	LL_USART_EnableDMAReq_TX(UART4);
}

void UART_SendBuf(uint16_t len)
{
	while(!LL_USART_IsActiveFlag_TC(UART4));
	LL_DMA_ClearFlag_TC5(DMA2);
	LL_DMA_DisableChannel(DMA2, LL_DMA_CHANNEL_5);
	memcpy(UART_Struct.txBuf, UART_Struct.txBuf2, len);
	LL_DMA_SetDataLength(DMA2, LL_DMA_CHANNEL_5, len);
	LL_DMA_EnableChannel(DMA2, LL_DMA_CHANNEL_5);
}
/* USER CODE END 0 */
/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_UART4_Init();
  /* USER CODE BEGIN 2 */
	UART_DMA_Init();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
		if (UART_Struct.rx_flag)
		{
			UART_Struct.rx_flag = 0;
			UART_Struct.txBuf2[0] = 1;
			UART_Struct.txBuf2[1] = 2;
		}
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

阻塞式发送(main.c)

int fputc(int ch, FILE *f)
{
	while(!LL_USART_IsActiveFlag_TC(UART4));
	LL_USART_TransmitData8(UART4, (uint8_t)ch);
}
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 在使用STM32LL进行串口接收中断时,首先需要对串口进行初始化设置。可以使用`LL_USART_Init()`函数对串口进行初始化,设置波特率、数据位、停止位、校验位等参数。 接下来,需要使能串口接收中断。可以使用`LL_USART_EnableIT_RXNE()`函数来使能接收中断。该函数会将接收寄存器非空中断打开,当接收寄存器中有数据时,中断标志位将被置位,触发中断。 在串口接收中断的处理函数中,可以使用`LL_USART_ReceiveData8()`函数来读取接收寄存器中的数据。该函数会返回接收到的8位数据。可以将读取到的数据保存到缓冲区中以便后续处理。 在处理完接收到的数据后,需要清除接收中断标志位,以便下一次接收中断触发。可以使用`LL_USART_ClearFlag_RXNE()`函数清除接收中断标志位。 在主程序中,可以调用`LL_USART_IsActiveFlag_ORE()`函数来检测是否发生了接收溢出错误。如果接收溢出错误发生,则需要调用`LL_USART_ClearFlag_ORE()`函数清除溢出错误标志位。 需要注意的是,在使用STM32LL进行串口接收中断时,需要根据具体的硬件和需求进行相关的配置和判断。可以查阅STM32相关的参考手册和官方文档来获取更详细的信息和使用示例。 ### 回答2: stm32ll提供了用于串口接收中断的函数。在使用串口接收中断功能时,需要先初始化串口并设置中断优先级。以下是一个简单的示例代码: 1. 首先,需要在代码中引入必要的头文件: #include "stm32l4xx_ll_usart.h" #include "stm32l4xx_ll_gpio.h" #include "stm32l4xx_ll_rcc.h" #include "stm32l4xx_ll_utils.h" 2. 然后,在初始化函数中对串口进行配置: void USART_Config(void) { // 使能串口时钟 LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1); // 配置串口引脚 LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; RCC->AHB2ENR |= RCC_AHB2ENR_GPIOCEN; GPIO_InitStruct.Pin = LL_GPIO_PIN_5 | LL_GPIO_PIN_6; 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; LL_GPIO_Init(GPIOC, &GPIO_InitStruct); // 配置串口参数 LL_USART_InitTypeDef USART_InitStruct = {0}; USART_InitStruct.BaudRate = 115200; USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B; USART_InitStruct.StopBits = LL_USART_STOPBITS_1; USART_InitStruct.Parity = LL_USART_PARITY_NONE; USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX; USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; LL_USART_Init(USART1, &USART_InitStruct); // 使能串口接收中断 LL_USART_EnableIT_RXNE(USART1); // 配置串口中断优先级 NVIC_SetPriority(USART1_IRQn, 0); NVIC_EnableIRQ(USART1_IRQn); // 使能串口 LL_USART_Enable(USART1); } 3. 最后,实现串口接收中断函数USART1_IRQHandler来处理接收到的数据: void USART1_IRQHandler(void) { if(LL_USART_IsActiveFlag_RXNE(USART1) && LL_USART_IsEnabledIT_RXNE(USART1)) { // 从串口缓冲区中读取接收到的数据 uint8_t receivedData = LL_USART_ReceiveData8(USART1); // 在这里进行接收到数据的处理 // ... // 清除接收中断标志位 LL_USART_ClearFlag_RXNE(USART1); } } 通过上述步骤,我们就可以实现基于stm32ll串口接收中断功能。在中断函数中,我们可以处理接收到的数据,并及时清除接收中断标志位,保证下一次中断可以正常触发。 ### 回答3: STM32LL是针对低功耗微控制器的一套函数,可以方便地使用其提供的功能进行开发。而串口是常用的数据通信方式之一,通过串口接收中断可以实现在数据接收时触发中断处理函数,提高系统的实时性和效率。 使用STM32LL进行串口接收中断的步骤如下: 1. 初始化串口:首先需要通过LL_USART_Init函数对串口进行初始化,设置波特率、数据位、校验位等参数,并使能串口。 2. 配置中断:使用LL_USART_EnableIT_RXNE函数使能串口接收中断(RXNE中断),然后通过LL_USART_ClearFlag_IDLE函数清除空闲线路检测标志位。 3. 编写中断处理函数:在串口接收中断触发时,会进入中断处理函数。用户需要在中断处理函数中编写实际的数据接收和处理逻辑。可以使用LL_USART_ReceiveData8或LL_USART_ReceiveData9函数读取接收到的数据,并进行后续的处理操作。 4. 中断优先级和使能:根据实际需求,可以使用LL_NVIC_SetPriority和LL_NVIC_EnableIRQ函数设置中断优先级,并使能NVIC中断。 5. 进入主循环:在主循环中,可以进行其他的任务处理或休眠等操作,当串口接收到数据时,会触发中断,执行中断处理函数。 需要注意的是,在串口接收中断处理函数中,为了避免数据丢失或溢出,应尽可能及时读取接收到的数据,并进行相应处理。此外,应尽量减少中断处理函数的执行时间,避免影响系统的实时性和效率。 总之,使用STM32LL进行串口接收中断的步骤包括初始化串口、配置中断、编写中断处理函数、设置中断优先级和使能,并在主循环中处理其他任务。通过串口接收中断,可以实现实时接收和处理数据的功能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值