【STM32】HAL库 CubeMX例程三---串口中断通信(2)(附工程源码)

由于调试过程中发现Proteus 8有些许bug,串口中断采用STM32F103RCT6开发板进行讲解

前期准备:

  1. STM32CubeMX
  2. STM32F103RCT6开发板
  3. IDE Keil(MDK-ARM)

STM32CubeMX部分

1. 配置时钟

在这里插入图片描述

选择STM32F103RCTx系列芯片,配置时钟的同时会自动配置IO口引脚
在这里插入图片描述
将HCLK设置为最大频率72MHz

2.配置USART

在这里插入图片描述
选择:
USART1串口1
Baud Rate(波特率):115200 Bits/s
Work Length(传输数据长度): 8 Bit
Parity(奇偶校验位) : 无
STOP Bits(停止位) :1
Data Direction(数据方向) : 发送和接收都使能

设置完之后就会自动配置USART1_RXUSART1_TX两个引脚

接着在NVIC Settings一栏设置使能全局中断
在这里插入图片描述

3.配置IO口

将PC4,PC5,PB0,PB1设置为:
高电平
Output模式
既不上拉也不下拉
响应速度高

3. 工程生成

在这里插入图片描述

在这里插入图片描述
工程管理依旧是这几个选项,然后GENERATE CODE,STM32CubeMX部分完成。

Keil部分

· HAL_UART_Transmit();串口发送数据,使用超时管理机制 
· HAL_UART_Receive();串口接收数据,使用超时管理机制
· HAL_UART_Transmit_IT();串口中断模式发送  
· HAL_UART_Receive_IT();串口中断模式接收
· HAL_UART_Transmit_DMA();串口DMA模式发送
· HAL_UART_Transmit_DMA();串口DMA模式接收
· HAL_UART_IRQHandler(UART_HandleTypeDef *huart);  //串口中断处理函数
· HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);  //串口发送中断回调函数
· HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);  //串口发送一半中断回调函数(用的较少)
· HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);  //串口接收中断回调函数
· HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);//串口接收一半回调函数(用的较少)
· HAL_UART_ErrorCallback();串口接收错误函数

讲两个常用的函数

  • HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)//串口中断接收数据
    UART_HandleTypeDef * huart:串口号
    uint8_t * pData:存放数据的数组
    uint16_t Size:接收的数据长度
    设置数据存放位置,接收数据长度,然后使能串口接收中断。接收到数据时,会触发串口中断,再然后,串口中断函数处理,直到接收到指定长度数据,而后关闭中断,进入中断接收回调函数,不再触发接收中断。(只触发一次中断)

例:HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);

  • HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); //中断回调函数
    中断进行完之后,并不会直接退出,而是会进入中断回调函数中,我们在其中写入代码即可

例:void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
用户自定义的代码
}

1. 重定义Printf函数

先在main.c添加

/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */

然后在stm32f1xx_hal.c中添加
在这里插入图片描述

#include "stm32f1xx_hal.h"
#include <stdio.h>
extern UART_HandleTypeDef huart1;   //声明串口

接着重写fgetc和fputc函数
在这里插入图片描述

/**
  * 函数功能: 重定向c库函数printf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}
 
/**
  * 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
  return ch;
}

然后在while里就可使用Printf函数了
在这里插入图片描述

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		printf("²âÊÔ\r\n");
		HAL_Delay(1000);
  }

编译下载时需要选择相对应的下载器,勾选以下
在这里插入图片描述

打开串口助手,设置
波特率:115200
停止位:1
数据位:8
奇偶校验:无
在这里插入图片描述
可以看到Printf能正常使用

2. 重写中断回调函数

在usart.c文件中添加如下代码

/* USER CODE BEGIN 0 */
#include "stdio.h"
#include "string.h"

#define RXBUFFERSIZE  256     //最大接收字节数

char RxBuffer[RXBUFFERSIZE];  //接收数据
uint8_t aRxBuffer;			      //接收中断缓冲
uint8_t Uart1_Rx_Cnt = 0;     //接收缓冲计数
/* USER CODE END 0 */
/* USER CODE BEGIN 1 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(huart);
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_UART_TxCpltCallback could be implemented in the user file
   */
 
	if(Uart1_Rx_Cnt >= 255)  //溢出判断
	{
		Uart1_Rx_Cnt = 0;
		memset(RxBuffer,0x00,sizeof(RxBuffer));
		HAL_UART_Transmit(&huart1, (uint8_t *)"数据溢出", 10,0xFFFF); 	
	}
	else
	{
		RxBuffer[Uart1_Rx_Cnt++] = aRxBuffer;   //
		RxBuffer[Uart1_Rx_Cnt++] = aRxBuffer;   //
	
		if(aRxBuffer == '1')//当发送1时,翻转电平
		{
			HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1);
		}
		else if(aRxBuffer == '2')//当发送2时,翻转电平
		{
			HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);
		}
		else if(aRxBuffer == '3')//当发送3时,翻转电平
		{
			HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_5);
		}
		else if(aRxBuffer == '4')//当发送4时,翻转电平
		{
			HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_4);
		}
		
		
		if((RxBuffer[Uart1_Rx_Cnt-1] == 0x0A)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
		{
			HAL_UART_Transmit(&huart1, (uint8_t *)&RxBuffer, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
      	    while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);//检测UART发送结束
			Uart1_Rx_Cnt = 0;
			memset(RxBuffer,0x00,sizeof(RxBuffer)); //清空数组
		}
	}
	
	HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);   //因为接收中断使用了一次即关闭,所以在最后加入这行代码即可实现无限使用
}
/* USER CODE END 1 */

接着去main.c中加入 extern uint8_t aRxBuffer;

/* USER CODE BEGIN Includes */
#include "stdio.h"
extern uint8_t aRxBuffer;	//声明变量
/* USER CODE END Includes */

接着开启接收中断
在这里插入图片描述

HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);

开启一次后进入中断回调函数,因为在中断回调函数中添加了此函数,即可一直等待发送数据以此进入中断

在这里插入图片描述
可以看到发送的数据被正常返回

接下来发送1 2 3 4看看灯是否能正常亮灭

链接:本期内容Keil工程
提取码:z276
在这里插入图片描述

版权声明:本文为CSDN博主「Q大帅」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Qxiaofei_/article/details/119029425

由于调试过程中发现Proteus 8有些许bug,串口中断采用STM32F103RCT6开发板进行讲解

前期准备:

  1. STM32CubeMX
  2. STM32F103RCT6开发板
  3. IDE Keil(MDK-ARM)

STM32CubeMX部分

1. 配置时钟

在这里插入图片描述

选择STM32F103RCTx系列芯片,配置时钟的同时会自动配置IO口引脚
在这里插入图片描述
将HCLK设置为最大频率72MHz

2.配置USART

在这里插入图片描述
选择:
USART1串口1
Baud Rate(波特率):115200 Bits/s
Work Length(传输数据长度): 8 Bit
Parity(奇偶校验位) : 无
STOP Bits(停止位) :1
Data Direction(数据方向) : 发送和接收都使能

设置完之后就会自动配置USART1_RXUSART1_TX两个引脚

接着在NVIC Settings一栏设置使能全局中断
在这里插入图片描述

3.配置IO口

将PC4,PC5,PB0,PB1设置为:
高电平
Output模式
既不上拉也不下拉
响应速度高

3. 工程生成

在这里插入图片描述

在这里插入图片描述
工程管理依旧是这几个选项,然后GENERATE CODE,STM32CubeMX部分完成。

Keil部分

· HAL_UART_Transmit();串口发送数据,使用超时管理机制 
· HAL_UART_Receive();串口接收数据,使用超时管理机制
· HAL_UART_Transmit_IT();串口中断模式发送  
· HAL_UART_Receive_IT();串口中断模式接收
· HAL_UART_Transmit_DMA();串口DMA模式发送
· HAL_UART_Transmit_DMA();串口DMA模式接收
· HAL_UART_IRQHandler(UART_HandleTypeDef *huart);  //串口中断处理函数
· HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);  //串口发送中断回调函数
· HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);  //串口发送一半中断回调函数(用的较少)
· HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);  //串口接收中断回调函数
· HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);//串口接收一半回调函数(用的较少)
· HAL_UART_ErrorCallback();串口接收错误函数

讲两个常用的函数

  • HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)//串口中断接收数据
    UART_HandleTypeDef * huart:串口号
    uint8_t * pData:存放数据的数组
    uint16_t Size:接收的数据长度
    设置数据存放位置,接收数据长度,然后使能串口接收中断。接收到数据时,会触发串口中断,再然后,串口中断函数处理,直到接收到指定长度数据,而后关闭中断,进入中断接收回调函数,不再触发接收中断。(只触发一次中断)

例:HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);

  • HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); //中断回调函数
    中断进行完之后,并不会直接退出,而是会进入中断回调函数中,我们在其中写入代码即可

例:void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
用户自定义的代码
}

1. 重定义Printf函数

先在main.c添加

/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */

然后在stm32f1xx_hal.c中添加
在这里插入图片描述

#include "stm32f1xx_hal.h"
#include <stdio.h>
extern UART_HandleTypeDef huart1;   //声明串口

接着重写fgetc和fputc函数
在这里插入图片描述

/**
  * 函数功能: 重定向c库函数printf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}
 
/**
  * 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
  return ch;
}

然后在while里就可使用Printf函数了
在这里插入图片描述

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		printf("²âÊÔ\r\n");
		HAL_Delay(1000);
  }

编译下载时需要选择相对应的下载器,勾选以下
在这里插入图片描述

打开串口助手,设置
波特率:115200
停止位:1
数据位:8
奇偶校验:无
在这里插入图片描述
可以看到Printf能正常使用

2. 重写中断回调函数

在usart.c文件中添加如下代码

/* USER CODE BEGIN 0 */
#include "stdio.h"
#include "string.h"

#define RXBUFFERSIZE  256     //最大接收字节数

char RxBuffer[RXBUFFERSIZE];  //接收数据
uint8_t aRxBuffer;			      //接收中断缓冲
uint8_t Uart1_Rx_Cnt = 0;     //接收缓冲计数
/* USER CODE END 0 */
/* USER CODE BEGIN 1 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(huart);
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_UART_TxCpltCallback could be implemented in the user file
   */
 
	if(Uart1_Rx_Cnt >= 255)  //溢出判断
	{
		Uart1_Rx_Cnt = 0;
		memset(RxBuffer,0x00,sizeof(RxBuffer));
		HAL_UART_Transmit(&huart1, (uint8_t *)"数据溢出", 10,0xFFFF); 	
	}
	else
	{
		RxBuffer[Uart1_Rx_Cnt++] = aRxBuffer;   //
		RxBuffer[Uart1_Rx_Cnt++] = aRxBuffer;   //
	
		if(aRxBuffer == '1')//当发送1时,翻转电平
		{
			HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1);
		}
		else if(aRxBuffer == '2')//当发送2时,翻转电平
		{
			HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);
		}
		else if(aRxBuffer == '3')//当发送3时,翻转电平
		{
			HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_5);
		}
		else if(aRxBuffer == '4')//当发送4时,翻转电平
		{
			HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_4);
		}
		
		
		if((RxBuffer[Uart1_Rx_Cnt-1] == 0x0A)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
		{
			HAL_UART_Transmit(&huart1, (uint8_t *)&RxBuffer, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
      	    while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);//检测UART发送结束
			Uart1_Rx_Cnt = 0;
			memset(RxBuffer,0x00,sizeof(RxBuffer)); //清空数组
		}
	}
	
	HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);   //因为接收中断使用了一次即关闭,所以在最后加入这行代码即可实现无限使用
}
/* USER CODE END 1 */

接着去main.c中加入 extern uint8_t aRxBuffer;

/* USER CODE BEGIN Includes */
#include "stdio.h"
extern uint8_t aRxBuffer;	//声明变量
/* USER CODE END Includes */

接着开启接收中断
在这里插入图片描述

HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);

开启一次后进入中断回调函数,因为在中断回调函数中添加了此函数,即可一直等待发送数据以此进入中断

在这里插入图片描述
可以看到发送的数据被正常返回

接下来发送1 2 3 4看看灯是否能正常亮灭

链接:本期内容Keil工程
提取码:z276
在这里插入图片描述

版权声明:本文为CSDN博主「Q大帅」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Qxiaofei_/article/details/119029425

生成海报
点赞 0

Q大帅

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

74HC138译码器的原理和使用

前言 译码器就是将每个输入的二进制代码译成对应的输出高低电平信号,和编码器互为逆过程。 百度百科 74HC138是一款高速CMOS器件,74HC138引脚兼容低功耗肖特基TTL(LSTTL&#xf

ESP32-GY_30光照强度传感器

GY_30光照强度传感器介绍 GY-30光强传感器特点及使用介绍 一、连接引脚 GY_30光照强度传感器使用I2C传输数据 。 5根引脚,名称与功能如下; vcc 为外接供电电源输入端 GND 地线 SCL I2C通信模式时钟