一、LED原理图

二、KEY原理图

三、实验现象
通过按键控制LED闪烁频率。当按下PA0按钮时,会在两种定时器周期模式间切换:快速模式和慢速模式,同时PA1、PA2、PA3三个LED会以当前设定的频率同步闪烁。每次按下按钮,LED的闪烁速度会在快慢两种模式之间切换。
四、示例代码
1. GPIO初始化
/**
* @brief GPIO初始化函数
*/
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0}; // GPIO配置结构体
// 使能GPIO端口时钟
__HAL_RCC_GPIOC_CLK_ENABLE(); // 使能GPIOC时钟
__HAL_RCC_GPIOD_CLK_ENABLE(); // 使能GPIOD时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟
// 设置GPIO初始输出电平
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_SET); // PA1,PA2,PA3初始化为高电平
// 配置PA0为输入引脚(按键)
GPIO_InitStruct.Pin = GPIO_PIN_0; // 引脚0
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // 输入模式
GPIO_InitStruct.Pull = GPIO_NOPULL; // 无上拉下拉
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 初始化PA0
// 配置PA1,PA2,PA3为输出引脚(LED)
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3; // 引脚1,2,3
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出模式
GPIO_InitStruct.Pull = GPIO_NOPULL; // 无上拉下拉
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // 低速输出
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 初始化PA1,PA2,PA3
}
2. TIM初始化
/**
* @brief TIM1定时器初始化函数
*/
void MX_TIM1_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0}; // 时钟源配置结构体
TIM_MasterConfigTypeDef sMasterConfig = {0}; // 主模式配置结构体
// 定时器基础配置
htim1.Instance = TIM1; // 定时器实例TIM1(高级定时器)
htim1.Init.Prescaler = 7200-1; // 预分频值7199(7200分频)
htim1.Init.CounterMode = TIM_COUNTERMODE_UP; // 向上计数模式
htim1.Init.Period = 1000-1; // 自动重装载值999
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 时钟分频(不分频)
htim1.Init.RepetitionCounter = 0; // 重复计数器值(高级定时器特有)
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; // 使能自动重装载预装载
// 初始化定时器基础配置
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
Error_Handler(); // 错误处理
}
// 配置时钟源为内部时钟
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
{
Error_Handler(); // 错误处理
}
// 配置主模式
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; // 主模式触发输出复位
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; // 禁用主从模式
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler(); // 错误处理
}
}
3. 主函数
uint16_t aaa[2] = {100-1, 1000-1}; // 定时器周期数组:快速模式99,慢速模式999
uint8_t mode = 0; // 模式标志:0-快速,1-慢速
// 系统时钟配置函数声明
void SystemClock_Config(void);
/**
* @brief 应用程序主函数
* @retval int
*/
int main(void)
{
// HAL库初始化
HAL_Init();
// 系统时钟配置
SystemClock_Config();
// 初始化所有配置的外设
MX_GPIO_Init(); // GPIO初始化
MX_TIM2_Init(); // TIM2定时器初始化
// 启动TIM2定时器中断
HAL_TIM_Base_Start_IT(&htim2);
// 主循环
while (1)
{
// 检测PA0按键是否按下
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET)
{
mode = !mode; // 切换模式(0↔1)
// 停止定时器中断
HAL_TIM_Base_Stop_IT(&htim2);
// 设置新的自动重装载值
__HAL_TIM_SET_AUTORELOAD(&htim2, aaa[mode]);
// 重置计数器为0
__HAL_TIM_SET_COUNTER(&htim2, 0);
// 重新启动定时器中断
HAL_TIM_Base_Start_IT(&htim2);
// 等待按键释放(简单消抖)
while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET);
}
}
}
4. 中断回调函数
/**
* @brief 定时器周期到达回调函数
* @param htim: 定时器句柄指针
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2) // 判断是否为TIM2触发
{
// 翻转PA1、PA2、PA3引脚电平(LED闪烁)
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
}
}