【STM32HAL库】STM32CubeMX+STM32CubeMXIDE系列教程(三)——USART串口通信

前言

此例程详细介绍了如何使用STM32CubeMX配置STM32单片机的USART串口,使用STM32CubeMXIDE进行软件编程。
【实现的功能】
1.实现单片机与PC串口调试助手进行信息收发;
2.实现串口调试助手向单片机发送指令控制单片机LED的亮灭。

工具

【库】HAL库
【软件】STM32CubeMX+STM32CubeMXIDE
【开发板】STM32F103C8T6开发板
【硬件资源】LED2、USART1;USB转TTL模块

硬件介绍

硬件连接

【说明】由于小编使用的板子是小系统板,没有板载USB转TTL,需要使用外部USB转TTL连接板子串口IO和PC的USB,才能进行串口助手调试。

//IO连接
USART   USB-TTL
 PA9<--->RXD
 PA10<-->TXD
//LED_IO
 PC13

【板载LED电路】
板载LED电路
注意LED阳极接3V3电源,因此当PC13输出低电平时LED点亮,PC13输出高电平时LED熄灭。

程序设计

STM32CubeMX配置

【第一步】:DeBug和系统时钟配置
DeBug配置
在这里插入图片描述
在这里插入图片描述
【第二步】:LED_IO配置
在这里插入图片描述
【第三步】:USART配置
在这里插入图片描述
【第四步】:工程生成设置
在这里插入图片描述
在这里插入图片描述
以上所有配置完成后点击右上角的GENERATE CODE生成配置好的工程文件,打开工程文件进入IDE进行程序设计。

程序设计

函数介绍

********************本例程主要用到的函数********************
//GPIO写函数,给GPIO写0或1(GPIO失能/使能)
void HAL_GPIO_WritePin( GPIO_TypeDef *  GPIOx,  
  						uint16_t  GPIO_Pin,  
  						GPIO_PinState  PinState  
 					  ) 
//UART数据接收函数
HAL_StatusTypeDef HAL_UART_Receive( UART_HandleTypeDef *  huart,  
  									uint8_t *  pData,  
  									uint16_t  Size,  
 									uint32_t  Timeout  
 								  ) 
//UART数据发送函数
HAL_StatusTypeDef HAL_UART_Transmit( UART_HandleTypeDef *  huart,  
  									 uint8_t *  pData,  
  									 uint16_t  Size,  
  									 uint32_t  Timeout  
 								   ) 
//UART接收中断回调函数
void HAL_UART_RxCpltCallback( UART_HandleTypeDef *  huart ) 
//UART中断服务函数
void HAL_UART_IRQHandler( UART_HandleTypeDef *  huart ) 
//内存初始化函数,常用于数组清零或初始化
void * memset(void *, int, size_t);
//以上函数参数不再做详细解释说明,具体可自行查阅HAL库手册和C语言库函数知识了解函数的具体功能和参数类型,这里小编给出一个STM32F1xxxHAL库官方手册以供读者使用。
链接:https://download.csdn.net/download/weixin_43803230/75395590

【HAL库官方手册下载链接】
STM32F1xxxHAL库官方手册

工程代码

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "string.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define Rx_Buffer_Size 256	//最大接收字节数
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
char Rx_Buffer[Rx_Buffer_Size];	//接收数据存储区
uint8_t aRxBuffer;				//接收数据中间存储区
uint8_t Uart1_Rx_Cnt = 0;		//接受数据长度
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* 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_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);
  /* USER CODE END 2 */

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

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */
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_RxCpltCallback could be implemented in the user file
   */
  if(Uart1_Rx_Cnt >= 255)
  {
	  Uart1_Rx_Cnt = 0;
	  memset(Rx_Buffer,0x00,sizeof(Rx_Buffer));
	  HAL_UART_Transmit(&huart1, (uint8_t *)"数据溢出", 10, 0xFFFF);
  }
  else
  {
	  Rx_Buffer[Uart1_Rx_Cnt++] = aRxBuffer;
	  if((Rx_Buffer[Uart1_Rx_Cnt-1] == 0x0A)&&(Rx_Buffer[Uart1_Rx_Cnt-2] == 0x0D))
	  {
		  if(Rx_Buffer[0] == 'y')	//当串口接收到字符' y '时,LED点亮
		  {
			  HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
			  HAL_UART_Transmit(&huart1, (uint8_t *)&"LED_ON ", 7, 0xFFFF);
		  }
		  if(Rx_Buffer[0] == 'n')	//当串口接收到字符' n '时,LED熄灭
		  {
			  HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
			  HAL_UART_Transmit(&huart1,(uint8_t *)&"LED_OFF ", 8, 0xFFFF);
		  }
		  HAL_UART_Transmit(&huart1, (uint8_t *)&Rx_Buffer, Uart1_Rx_Cnt,0xFFFF);
	      while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);
	      Uart1_Rx_Cnt = 0;
	      memset(Rx_Buffer,0x00,sizeof(Rx_Buffer)); //清空数组
	  }
  }

  HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);   //再开启接收中断
}
/* USER CODE END 4 */

【重点】重要的代码是

//重点关注UART接收中断回调函数中的内容
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	********************
}
//其中这一段是串口调试助手向单片机发送指令控制LED亮灭的程序
/*如果去掉这一段代码,剩下的代码则是仅实现串口调试助手和单片机
进行数据收发的功能,串口调试助手向单片机发送什么,单片机就会将
接收到的数据发送给串口调试助手,并在串口调试助手上显示发的数据。
*/
if(Rx_Buffer[0] == 'y')	//当串口接收到字符' y '时,LED点亮
{
	HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
	HAL_UART_Transmit(&huart1, (uint8_t *)&"LED_ON ", 7, 0xFFFF);
}
if(Rx_Buffer[0] == 'n')	//当串口接收到字符' n '时,LED熄灭
{
	HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
	HAL_UART_Transmit(&huart1,(uint8_t *)&"LED_OFF ", 8, 0xFFFF);
}

例程实现效果

在这里插入图片描述
其中,当发‘ n ’时,单片机上的LED2会熄灭,当发‘ y ’时,单片机上的LED2会点亮。

完整工程文件

完整工程文件

结语

这次的UART也是一个简单的小例程,通过UART控制单片机的LED,知识UART控制单片机IO一个小方面,不过这个小例程的扩展性很大,可以将其扩展至控制继电器、控制PWM从而控制电机转速实现电机调速系统等等,除了使用串口调试助手,也可以根据特定的应用场合自行编写上位机,实现PC通过UART像单片机发送指令控制其他东西。有兴趣的读者可自行去探索更多的高级玩法,也可以和小编交流哦。对此工程有疑问的也可以评论和小编一起探讨。

如果觉得这篇文章对你有帮助的话就顺手点赞收藏关注一小编叭,您的认可时小编更新的最大动力,谢谢支持(^ _ ^)!!!

  • 1
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是使用STM32HAL库进行串口通信的示例代码: ```c // 引用头文件 #include "stm32f4xx_hal.h" // 定义串口句柄 UART_HandleTypeDef huart1; // 串口接收缓冲区 uint8_t rxBuffer = "yupeng"; // 串口接收完成中断回调函数 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart == &huart1) { // 对接收到的数据进行处理 HAL_UART_Receive_IT(&huart1, rxBuffer, 5); // 再次开启一次中断 } } int main(void) { // 初始化HAL库 HAL_Init(); // 初始化串口 __HAL_RCC_USART1_CLK_ENABLE(); huart1.Instance = USART1; huart1.Init.BaudRate = 9600; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; HAL_UART_Init(&huart1); // 开启串口接收中断 HAL_UART_Receive_IT(&huart1, rxBuffer, 5); while (1) { // 发送数据 HAL_UART_Transmit_IT(&huart1, txBuffer, 5); // 延时等待发送完成 HAL_Delay(1000); } } ``` 这段代码中,我们首先引用了STM32HAL库的头文件,并定义了一个串口句柄`huart1`,以及接收和发送的缓冲区。在`main`函数中,我们首先初始化HAL库和串口,并开启串口接收中断。然后,在主循环中,我们使用`HAL_UART_Transmit_IT`函数将数据发送出去,并使用`HAL_Delay`函数进行延时,等待发送完成。同时,当串口接收到数据时,会触发中断回调函数`HAL_UART_RxCpltCallback`,我们在这个函数中对接收到的数据进行处理,并再次开启一次中断。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

乔乔同学

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

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

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

打赏作者

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

抵扣说明:

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

余额充值