此例程详细介绍了如何使用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阳极接3V3电源,因此当PC13输出低电平时LED点亮,PC13输出高电平时LED熄灭。
【第一步】: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像单片机发送指令控制其他东西。有兴趣的读者可自行去探索更多的高级玩法,也可以和小编交流哦。对此工程有疑问的也可以评论和小编一起探讨。