学习目标:
整合资源,通过USART1串口完整实现信息的接收和发送
学习内容:
1.事实上可以将USART.h和USART.c存储起来,封装为串口的驱动文件。
这里,我们把它们另存为usart1.h和usart1.c
2.改写main.c文件实现代码的重构
3.通过XCOM V2.2串口调试助手来验证代码运行正确性
学习时间:
2026.1.7
工程创建:
1.在项目工程文件MDK-RAM文件夹下新建Devices/usart1文件夹
新建usart1.c和usart1.h文件,并对其编程。
usart1.c
#include "usart1.h"
#include "stm32l4xx_hal.h"
// Global variable definitions
uint8_t USART_RX_BUF[USART_REC_LEN]; // Receive buffer
uint16_t USART_RX_STA = 0; // Receive status flag
UART_HandleTypeDef huart1; // UART handle
#if 1
#pragma import(__use_no_semihosting)
// Support functions required by the standard library
struct __FILE
{
int handle;
};
FILE __stdout;
/**
* @brief Define _sys_exit() to avoid using semihosting mode
*
* @param x (Unused parameter)
*
* @return void
*/
void _sys_exit(int x)
{
x = x; // Prevent unused parameter warning
}
/**
* @brief Redefine fputc function for printf redirection
*
* @param ch Character to send
* @param f File pointer (unused)
*
* @return The character sent
*/
int fputc(int ch, FILE *f)
{
// Wait until the transmit data register is empty
while((USART1->ISR & 0X40) == 0);
// Write the character to the transmit data register
USART1->TDR = (uint8_t)ch;
return ch;
}
#endif
/**
* @brief USART1 initialization function
*
* @param bound UART baud rate
*
* @return void
*/
void uart1_init(uint32_t bound)
{
// UART initialization settings
huart1.Instance = USART1; // USART1
huart1.Init.BaudRate = bound; // Set baud rate
huart1.Init.WordLength = UART_WORDLENGTH_8B; // 8-bit data format
huart1.Init.StopBits = UART_STOPBITS_1; // One stop bit
huart1.Init.Parity = UART_PARITY_NONE; // No parity
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; // No hardware flow control
huart1.Init.Mode = UART_MODE_TX_RX; // Transmit and receive mode
HAL_UART_Init(&huart1); // HAL_UART_Init() will enable USART1
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); // Enable receive interrupt
HAL_NVIC_EnableIRQ(USART1_IRQn); // Enable USART1 interrupt channel
HAL_NVIC_SetPriority(USART1_IRQn, 3, 3); // Preemption priority 3, subpriority 3
}
/**
* @brief HAL library UART low-level initialization (clock enable, pin configuration, interrupt configuration)
*
* @param huart Pointer to UART handle
*
* @return void
*/
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
// GPIO port settings
GPIO_InitTypeDef GPIO_InitStruct = {0};
if (huart->Instance == USART1) // If it is USART1, perform USART1 MSP initialization
{
__HAL_RCC_GPIOA_CLK_ENABLE(); // Enable GPIOA clock
__HAL_RCC_USART1_CLK_ENABLE(); // Enable USART1 clock
GPIO_InitStruct.Pin = GPIO_PIN_9; // PA9 (TX)
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // Alternate function push-pull output
GPIO_InitStruct.Pull = GPIO_PULLUP; // Pull-up
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // High speed
GPIO_InitStruct.Alternate = GPIO_AF7_USART1; // Alternate function USART1
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // Initialize PA9
GPIO_InitStruct.Pin = GPIO_PIN_10; // PA10 (RX)
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // Initialize PA10
}
}
#if EN_USART1_RX // If reception is enabled
/**
* @brief USART1 interrupt service routine
* @remark The code writes the interrupt control logic directly inside the ISR.
* Note: Using HAL library processing logic, efficiency is not high.
*
* @param void
* @return void
*/
void USART1_IRQHandler(void)
{
uint8_t Res;
if ((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET)) // Receive interrupt (received data must end with 0x0d 0x0a)
{
HAL_UART_Receive(&huart1, &Res, 1, 1000);
if ((USART_RX_STA & 0x8000) == 0) // Reception not completed
{
if (USART_RX_STA & 0x4000) // Already received 0x0d
{
if (Res != 0x0a)
USART_RX_STA = 0; // Receive error, restart
else
USART_RX_STA |= 0x8000; // Reception completed
}
else // Has not received 0x0D yet
{
if (Res == 0x0d)
USART_RX_STA |= 0x4000;
else
{
USART_RX_BUF[USART_RX_STA & 0X3FFF] = Res;
USART_RX_STA++;
}
if (USART_RX_STA > (USART_REC_LEN - 1))
USART_RX_STA = 0; // Receive data error, restart reception
}
}
}
HAL_UART_IRQHandler(&huart1);
}
#endif
usart1.h
#ifndef _USART_H
#define _USART_H
#include "stm32l4xx.h"
#include "stdio.h"
#define USART_REC_LEN 200 // Define maximum received bytes as 200
#define EN_USART1_RX 1 // Enable (1) / Disable (0) USART1 reception
extern uint8_t USART_RX_BUF[USART_REC_LEN]; // Receive buffer, maximum USART_REC_LEN bytes. Last byte is newline character
extern uint16_t USART_RX_STA; // Receive status flag
extern UART_HandleTypeDef huart1; // UART handle
#define RXBUFFERSIZE 1 // Buffer size
extern uint8_t aRXBuffer[RXBUFFERSIZE]; // HAL library USART receive buffer
// If you want to use USART interrupt reception, do not comment the following macro definition
void uart1_init(uint32_t bound);
#endif

2.将保存好的usart1.c和usart1.h文件复制一份至Hardwares文件夹下

3.在项目管理窗口中,添加usart1.c,包含usart1路径。


4.当确定Hardware中已经包含usart1.c文件,需要将系统自动生成的usart文件删除。

5.在main.c对usart1进行初始化
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2026 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>
#include <stdint.h>
#include <stdio.h>
#include "key.h"
#include "Led.h"
#include "Beep.h"
#include "usart1.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
uint8_t KEY_Scan(uint8_t mode);
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
// GPIO????(??????????)
#define KEY0_Pin GPIO_PIN_10
#define KEY0_GPIO_Port GPIOD
#define KEY1_Pin GPIO_PIN_9
#define KEY1_GPIO_Port GPIOD
#define KEY2_Pin GPIO_PIN_8
#define KEY2_GPIO_Port GPIOD
#define WK_UP_Pin GPIO_PIN_13
#define WK_UP_GPIO_Port GPIOC
#define LED_R_Pin GPIO_PIN_7
#define LED_R_GPIO_Port GPIOE
#define LED_G_Pin GPIO_PIN_8
#define LED_G_GPIO_Port GPIOE
#define LED_B_Pin GPIO_PIN_9
#define LED_B_GPIO_Port GPIOE
#define BEEP_Pin GPIO_PIN_2
#define BEEP_GPIO_Port GPIOB
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
// ????????????
extern uint8_t USART_RX_BUF[200];
extern uint16_t USART_RX_STA;
extern UART_HandleTypeDef huart1;
/* 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 */
// ?????
KEY_Init();
BEEP_Init();
LED_Init();
uart1_init(115200); // ?????1,???115200
uint8_t len;
uint32_t times = 0; // ???times??
uint8_t key_value; // ????????
// ??????
printf("\r\n");
printf("===============================================\r\n");
printf(" STM32 IoT Development Board Test Program\r\n");
printf("===============================================\r\n");
printf("Serial Port: COM14 @115200bps\r\n");
printf("Press Enter key to start testing...\r\n");
printf("===============================================\r\n\r\n");
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// ???????LED/???????
key_value = KEY_Scan(1);
switch (key_value){
case 1:// KEY0??
HAL_GPIO_TogglePin(LED_R_GPIO_Port,LED_R_Pin); //????LED??
break;
case 2:// KEY1??
HAL_GPIO_TogglePin(LED_G_GPIO_Port, LED_G_Pin); //????LED??
break;
case 3: // KEY2??
HAL_GPIO_TogglePin(LED_B_GPIO_Port, LED_B_Pin); //????LED??
break;
case 4: // WK_UP??
HAL_GPIO_TogglePin(BEEP_GPIO_Port, BEEP_Pin);//???????
break;
default:
break;
}
// ??10ms,??CPU???
HAL_Delay(10);
// ??LED????
// LED????
HAL_GPIO_TogglePin(LED_R_GPIO_Port,LED_R_Pin);
HAL_Delay(500);
HAL_GPIO_WritePin(LED_G_GPIO_Port,LED_G_Pin,GPIO_PIN_RESET);
HAL_Delay(500);
HAL_GPIO_WritePin(LED_G_GPIO_Port,LED_G_Pin,GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(LED_B_GPIO_Port,LED_B_Pin,GPIO_PIN_RESET);
HAL_Delay(500);
HAL_GPIO_WritePin(LED_B_GPIO_Port,LED_B_Pin,GPIO_PIN_SET);
HAL_Delay(500);
// ?????
HAL_GPIO_WritePin(BEEP_GPIO_Port,BEEP_Pin,GPIO_PIN_SET);//?????
HAL_Delay (500);
HAL_GPIO_WritePin(BEEP_GPIO_Port,BEEP_Pin,GPIO_PIN_RESET);//?????
// ??????????
// ??HAL_UART_Transmit??????
const char *message ="USART1_test\r\n";
HAL_UART_Transmit(&huart1, (uint8_t *)message, strlen(message), HAL_MAX_DELAY);
// ??printf()?????????
printf("Hello, IoT\r\n");
printf("QLU\r\n");
printf("2026Y1M5D Bo Wang\r\n");
// ??printf()??JSON????
float temperature = 25.5; //??
int humidity = 60; //??
printf("{\"temperature\": %.1f, \"humidity\": %d}\n", temperature, humidity);
printf("\r\n");
// ?????????????
uint8_t key = KEY_Scan(0); //????,mode=0???????
switch (key)
{
case WKUP_PRES: //WK_UP????
HAL_GPIO_TogglePin(BEEP_GPIO_Port, BEEP_Pin); // ??:??HAL_GPIO_TogglePin??
printf("WKUP_PRES\r\n");
break;
case KEY2_PRES: //KEY2????,????LED
HAL_GPIO_TogglePin(LED_B_GPIO_Port, LED_B_Pin); // ??:??HAL_GPIO_TogglePin??
printf("KEY2_PRES\r\n");
break;
case KEY1_PRES: //KEY1????,????LED
HAL_GPIO_TogglePin(LED_G_GPIO_Port, LED_G_Pin); // ??:??HAL_GPIO_TogglePin??
printf("KEY1_PRES\r\n");
break;
case KEY0_PRES: //KEY0????,????LED
HAL_GPIO_TogglePin(LED_R_GPIO_Port, LED_R_Pin); // ??:??HAL_GPIO_TogglePin??
printf("KEY0_PRES\r\n");
break;
default:
break;
}
// ????????
if (USART_RX_STA & 0x8000) // ???????(bit15=1),??????
{
len = USART_RX_STA & 0x3fff; // ??????(?14?)
printf("\r\nYour notice is:\r\n"); // ????,???????????
HAL_UART_Transmit(&huart1, (uint8_t *)USART_RX_BUF, len, 1000); // ???????????
// ????:
// &huart1:????,??UART1
// (uint8_t *)USART_RX_BUF:????????
// len:???????
// 1000:????(??:ms)
while (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) != SET); // ??????
// __HAL_UART_GET_FLAG():???????,UART_FLAG_TC ????????
// ??????????,????????
printf("\r\n\r\n"); // ?????,????,????????
USART_RX_STA = 0; // ????????,???????
}
else // ???????
{
times++; // ????1,????LED???????????
if (times % 500 == 0) // ?5??????
{
printf("\r\n<IoT Engineering Practice and Management>Usart_Test\r\n"); // ??????
printf("QLU\r\n\r\n\r\n"); // ??????
}
if (times % 200 == 0) // ?2??????
{
printf("Send data and finish with Enter key.\r\n"); // ??????
}
// ??LED_B????
if (times % 30 == 0) HAL_GPIO_TogglePin(LED_B_GPIO_Port, LED_B_Pin); // ?300ms????LED_B???
// HAL_GPIO_TogglePin:?? LED ????(?/?),???????????
HAL_Delay(10); // ?? 10 ms,?CPU????
}
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
{
Error_Handler();
}
/** 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.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 1;
RCC_OscInitStruct.PLL.PLLN = 20;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
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_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
uint8_t KEY_Scan(uint8_t mode){
// ????????,???????
if (HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == GPIO_PIN_RESET){
HAL_Delay(20);//????
if (HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == GPIO_PIN_RESET){
while (HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin) == GPIO_PIN_RESET);//??????
return 1;//??KEY0??
}
}
//??KEY1?(?????)
if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_RESET){
HAL_Delay(20);//????
if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_RESET){
while (HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == GPIO_PIN_RESET);//??????
return 2;//??KEY1??
}
}
if (HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin) == GPIO_PIN_RESET){
HAL_Delay(20);//????
if (HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == GPIO_PIN_RESET){
while (HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin) == GPIO_PIN_RESET);//??????
return 3;//??KEY2??
}
}
//??WK_UP?(?????)
if (HAL_GPIO_ReadPin(WK_UP_GPIO_Port,WK_UP_Pin) == GPIO_PIN_SET) {
HAL_Delay(20);//????
if (HAL_GPIO_ReadPin(WK_UP_GPIO_Port,WK_UP_Pin) == GPIO_PIN_SET){
while (HAL_GPIO_ReadPin(WK_UP_GPIO_Port,WK_UP_Pin) == GPIO_PIN_SET); //??????
return 4;//??WK_UP??
}
}
return 0;//?????
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
6.编译用下载文件至开发板,接收按键指令后自动发送预存的信息。

562

被折叠的 条评论
为什么被折叠?



