第一次来论坛测评,今天先出第一篇,在STM32F103上,就是星允派开发板实现串口和GPIO的使用。
- 平台:KEIL
- 实现功能:串口操作、GPIO操作。
- 串口通信:PA9(TX)和PA10(RX)
- GPIO操作:按键KEY1接PA2,LED1接PB4
- 功能需求:串口输出星允派!hello,F103!和按下KEY1时,LED1闪烁
1、硬件连接
KEY1:连接到PA2(输入模式,建议上拉或下拉,防止悬空) LED1:连接到PB4(输出模式,推挽输出) 串口:PA9(TX)、PA10(RX)用于调试输出
2、原理图
按键与LED,从原理图了解LED引脚是受PB4控制,从这个原理图就能得出结果,可以清楚的从CUBEMX进行配置PB4为输出模式。

串口连接IO引脚:

3、STM32CubeMX配置
先配置LED为输出,再设置PB4的模式:

STM32CubeMX 工具配置 PB4 引脚,
- 引脚功能:GPIO_Output(通用输出模式)
- 输出电平:High(初始高电平)
- 模式:Output Push Pull(推挽输出)
- 上拉/下拉:No pull(无上下拉电阻)
- 最大输出速度:High(高速模式)
再配置输入模式按键:

串口配置,定义串口引脚:

根据上图显示,关键引脚配置如下:
| 引脚 | 功能配置 | 模式 | 上下拉 | 速度 |
|---|---|---|---|---|
| PA9 | USART1_TX | Alternate Function Push-Pull | No pull-up/pull-down | High |
| PA10 | GPIO_Output | Output Push-Pull | No pull-up/pull-down | High |
4、代码
/* USER CODE BEGIN 1 */
char i; // 定义一个字符型变量i,用于存储按键状态
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* 复位所有外设,初始化Flash接口和系统滴答定时器 */
HAL_Init();
/* USER CODE BEGIN Init */
/* 用户初始化代码区域(当前为空) */
/* USER CODE END Init */
/* 配置系统时钟 */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* 系统初始化代码区域(当前为空) */
/* USER CODE END SysInit */
/* 初始化所有已配置的外设 */
MX_GPIO_Init(); // 初始化GPIO
MX_USART1_UART_Init(); // 初始化USART1串口
/* USER CODE BEGIN 2 */
// 串口发送测试数据
unsigned char Sendbuf[] = "星允派!\r\n"; // 定义要发送的字符串
HAL_UART_Transmit(&huart1, Sendbuf, sizeof(Sendbuf), HAL_MAX_DELAY); // 通过UART1发送数据
HAL_Delay(1000); // 延时1秒
// 使用printf打印测试信息
printf("hello,STM32F103!\r\n"); // 通过串口打印信息
HAL_Delay(1000); // 延时1秒
/* USER CODE END 2 */
/* 无限循环 */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// 检测KEY按键状态(0表示按下,1表示释放)
i = HAL_GPIO_ReadPin(K1_GPIO_Port, K1_Pin); // 读取KEY1按键状态
if (i == 0)
{
// 按键按下时LED1闪烁三次
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); // LED1亮
HAL_Delay(300); // 延时300ms
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET); // LED1灭
HAL_Delay(300); // 延时300ms
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); // LED1亮
}
else
{
// 按键未按下时LED1保持熄灭
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
}
// 检查是否完成串口数据接收
if(rx_done == 1) // 如果接收完成标志置位
{
rx_done = 0; // 清除接收完成标志
// 打印接收到的数据长度和内容
printf("length of rx data: %d!\r\n", rx_cnt); // 打印接收数据长度
for(int i = 0; i < rx_cnt; i++)
printf("%c", rx_buff[i]); // 逐个打印接收到的字符
printf("\r\n"); // 打印换行
rx_cnt = 0; // 重置接收计数器
}
}
/* USER CODE END 3 */
初始化
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
/*Configure GPIO pins : K1_Pin K2_Pin */
GPIO_InitStruct.Pin = K1_Pin|K2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : PA8 */
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : LED2_Pin */
GPIO_InitStruct.Pin = LED2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(LED2_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : LED1_Pin */
GPIO_InitStruct.Pin = LED1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(LED1_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
static void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
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;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/\* USER CODE BEGIN USART1\_Init 2 \*/
// 启用 UART1 的空闲中断(IDLE)和接收寄存器非空中断(RXNE)
// UART\_IT\_IDLE: 空闲中断,当检测到总线空闲时触发
// UART\_IT\_RXNE: 接收数据寄存器非空中断,当接收到数据时触发
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE|UART_IT_RXNE);
/* USER CODE END USART1_Init 2 */
}
//重映射函数
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
5、上面的代码说明:
按键检测(K1/K2)与LED 控制(LED1/LED2) 串口通信(USART1)用于调试信息输出和数据接收 中断驱动的串口数据接收处理
MX_GPIO_Init()初始化所有 GPIO 引脚: 配置 K1/K2 为输入模式(无上下拉) 配置 LED1/LED2 为推挽输出(上拉,高速)
MX_USART1_UART_Init()初始化 USART1: 波特率 115200,8 位数据,无校验 启用空闲中断和接收中断
SystemClock_Config()配置系统时钟(代码未展示,默认使用 HSI/HSE+PLL)
| 中断类型 | 触发条件 | 典型应用 |
|---|---|---|
| UART_IT_RXNE | 接收寄存器非空 | 实时读取单个字节 |
| UART_IT_IDLE | 检测到总线空闲(停止位后) | 判定一帧数据接收完成 |
6、实现效果
串口输出
按键按下时LED闪烁

上面的演示是按键按下,LED闪烁,松开后,就熄灭。
🤒 注释乱码了