STM32CubeIDE——USART中断收发

目录

一、工程配置

二、使用USART中断收发前必知的两个函数的作用

2.1 HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

2.2 HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

三、代码详解

3.1 main()函数

3.2 两个回调函数

四、总结


硬件条件:带有两个usart外设(引脚空闲)的STM32开发板/工控板,用杜邦线把它俩正确的连起来。

实现功能:

  1. stm32的usart1发送信息,发送完成后立即执行“发送完成”回调函数;
  2. stm32的usart2发送信息,发送完成后立即执行“发送完成”回调函数;
  3. stm32的usart1中断接收usart2发送的信息,接收完成后立即执行“接收完成”回调函数;
  4. stm32的usart2中断接收usart1发送的信息,接收完成后立即执行“接收完成”回调函数;

本文默认读者已经有了如下的基本知识和技能:

  • 对stm32的usart或uart有一定的了解,包括波特率、时序信息等;
  • 会在stm32cubeide中图形化配置芯片的调试串口、时钟和代码自动生成。

下面直接开始工程(工程中只讲述与usart有关的地方)。

一、工程配置

本文以STM32F103C8T6芯片为例。

图形化界面中,usart1和usart2的配置如图1-1、图1-2所示。它们的中断优先级配置如图1-3所示。

到此,两个usart的配置全部结束了(代码中不再添加多余的配置代码)。

图1-1
图1-2
图1-3

二、使用USART中断收发前必知的两个函数的作用

2.1 HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

  • 用户在 main() 中轮询调用该函数;
  • 执行中:发送pData指针指向空间的信息+使能“发送寄存器空”中断;
  • 执行结束后:立即进入中断;
    • 在中断里,先自动调用 UART_EndTransmit_IT(UART_HandleTypeDef *huart) 函数(该函数会失能“发送完成”中断。不过无所谓,可以不用在意);
    • 中断里,之后再自动调用 HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) 回调函数(用户自定义其功能);
  • 退出中断,等待下一次信息的发送。

2.2 HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

  • 用户在 main() 和回调函数 HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 中都调用一次该函数;
  • 执行中:指定未来接收到的信息要存入的空间,即pData指针指向的空间就是之后接收到的信息要存入的空间+使能“奇偶校验错误”中断+使能“其它uart错误”中断+使能“接收寄存器非空”中断;(特别注意:该函数是不会接收信息的,只是指定信息要存入的空间
  • 执行结束后:等待接收寄存器非空,然后进入中断;
    • 在中断里,先自动调用 UART_Receive_IT(UART_HandleTypeDef *huart) 函数(该函数会接收信息并存入上一步已经预备好的空间中+失能“奇偶校验错误”中断+失能“其它uart错误”中断+失能“接收寄存器非空”中断);
    • 中断里,之后再自动调用 HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 回调函数(用户自定义其功能,但是用户在该函数中必须自行添加 HAL_UART_Receive_IT() 函数,以指定下一次信息待存入的空间并再次使能对应的中断功能);
  • 退出中断,等待下一次接收寄存器非空。

三、代码详解

3.1 main()函数

/* USER CODE BEGIN PV */
uint8_t RxData1 = 0x00U;    // usart1接收到的信息待存入的空间
uint8_t RxData2 = 0x00U;    // usart2接收到的信息待存入的空间
uint8_t TxData1 = 0x01U;    // usart1待发送的信息
uint8_t TxData2 = 0xFFU;    // usart1待发送的信息
/* USER CODE END PV */

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_USART1_UART_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
  HAL_UART_Receive_IT(&huart1, &RxData1, sizeof(RxData1));    // 指定usart1存储接收信息所用的空间,并使能usart1的相关接收中断
  HAL_UART_Receive_IT(&huart2, &RxData2, sizeof(RxData2));    // 指定usart2存储接收信息所用的空间,并使能usart2的相关接收中断
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  if(HAL_UART_Transmit_IT(&huart1, &TxData1, (uint16_t) sizeof(TxData1)) != HAL_OK)    // usart1发送信息,发完信息立即进入中断,执行用户自定义的回调函数使得TxData1的内容加1
	  {
		  Error_Handler();
	  }
	  if(HAL_UART_Transmit_IT(&huart2, &TxData2, (uint16_t) sizeof(TxData2)) != HAL_OK)    // usart2发送信息,发完信息立即进入中断,执行用户自定义的回调函数使得TxData2的内容减1
	  {
		  Error_Handler();
	  }
  }
  /* USER CODE END 3 */
}

3.2 两个回调函数

/*
 * 该函数是在HAL_UART_Transmit_IT()函数执行完之后立即自动调用的回调函数
 * 
 */
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance == USART1)
	{
        // 产生usart1下一次发送的信息
		if(TxData1 == 0xFFU)
		{
			TxData1 = 0x01U;
		}
		else
		{
			TxData1++;
		}
	}
	if(huart->Instance == USART2)
	{
        // 产生usart2下一次发送的信息
		if(TxData2 == 0x01U)
		{
			TxData2 = 0xFFU;
		}
		else
		{
			TxData2--;
		}
	}
}
/*
 * 该函数是在“接收寄存器非空”中断里自动调用的回调函数
 * 进入该函数前,usart1已经将接收到的信息存储在了RxData1中;usart2已经将接收到的信息存储在了RxData2中
 *             并且,两个usart相关的接收中断是处于失能的状态
 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance == USART1)
	{
		HAL_UART_Receive_IT(&huart1, &RxData1, sizeof(RxData1));    // 指定usart1存储下一次接收信息所用的空间,并再次使能usart1的相关接收中断
		// 用户代码begin

		// 用户代码end
	}
	if(huart->Instance == USART2)
	{
		HAL_UART_Receive_IT(&huart2, &RxData2, sizeof(RxData2));    // 指定usart2存储下一次接收信息所用的空间,并再次使能usart2的相关接收中断
		// 用户代码begin

		// 用户代码end
	}
}

四、总结

stm32的usart配置和使用流程在stm32cubeide软件中是这样的:

  1. ioc文件里图形化使能usart并配置其波特率、工作方式、中断优先级;
  2. 自动生成代码后,在main.c文件下的main()里调用一次 HAL_UART_Receive_IT() 并轮询调用 HAL_UART_Transmit_IT();
  3. 在main.c文件下的main()外用户自定义两个中断回调函数:HAL_UART_TxCpltCallback() 和 HAL_UART_RxCpltCallback();
  4. HAL_UART_RxCpltCallback() 中必须再次调用 HAL_UART_Receive_IT()。

我遇到的错误点总结:

  1. 没有在main()里调用 HAL_UART_Receive_IT(),usart是不会进入中断去接收信息的。——阅读了stm32f1xx_hal_uart.c文件中对uart外设的说明,发现了该问题并解决。
  2. 没有在 HAL_UART_RxCpltCallback() 中再次调用 HAL_UART_Receive_IT(),usart只会响应一次中断去接收信息,之后再来新的信息就不会进入中断去接收了,更不会进入 HAL_UART_RxCpltCallback() 函数里了。——通过软件的单步调试功能和网上海量教程,发现了该问题并解决。

所有与usart相关的函数,它们的功能,传递参数的含义、类型、取值,返回值等;所有与usart相关的结构体,它们的定义,成员变量的含义、类型、取值等,或是其它更多的信息。这些请自行在工程里的这两个文件中进行查阅:

  • 18
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

觅道無涯-千知

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值