[STM32 HAL] 控制LED灯闪烁频率

TIM简介

TIM外设,是用来产生定时事件的。在内部构造上 如下图。
TIM系统框架图

但关键部件只有 [输入时钟脉冲]->[计数器CNT]->[捕获比较寄存器]
常用的寄存器

  • Prescaler(PSC)预分频寄存器:对输入到TIM外设时钟频率进行分频,比如该TIM挂在在APB2上,APB2的时钟频率为72MHz,如果设置PSC寄存器值为72-1,那么那么进入TIM外设的内部的时钟频率为1MHz,CNT寄存器也就是对1这1MHz的脉冲进行计数。该寄存器可通过__HAL_TIM_SET_PRESCALER(__HANDLE__, __PRESC__)进行修改
  • Counter(CNT)寄存器: 用来计数当前收到的脉冲数。使用__HAL_TIM_SET_COUNTER(__HANDLE__, __COUNTER__)修改
  • CCR寄存器(capture/compare register):在输入捕获,和输出比较中有不同的作用。以PWM波生成为例,该寄存器可用来设置PWM波的占空比。使用__HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__)来进行设置
  • ARR寄存器(AutoReload Register): 在本例中,当CNT寄存器中的值达到ARR中的值时,自动将CNT值清零。也就是用来限制CNT的计数范围。使用__HAL_TIM_SET_AUTORELOAD(__HANDLE__, __AUTORELOAD__)进行设置。
    从下图可以看出TIM生成PWM的工作过程。TIM最核心的就是CNT和ARR了,CNT不断的计数,计的是进入TIM的脉冲数,也就是经过PSC分频后的时钟脉冲数;CNT一旦到达ARR的值就会归零,再次开始计数。这就是基本TIM的作用了。如果TIM的某个通道还启用PWM功能,那么就会有CCR寄存器被派上用场,时刻监视着CNT值,根据CNT值和CCR值的比较,更改通道的对应引脚的电平状态。
    在这里插入图片描述

STM32CubeMX配置

对于本次例题。我们直接将CCR值设置为ARR的一半,也就是PWM的占空比50%
将LED灯所在引脚的模式设置为TIM。
设置LED灯所在引脚模式为TIM
配置该TIM 通道为PWM波输出方式。只需要启动Activated即可(左侧TIM16图标变成绿色),主要的参数可以在程序中通过上述的代码设置。
在这里插入图片描述

代码编写
double LED_freq=1;//全局变量,用于保存当前LED闪烁频率值
void LED_blink(double freq)
{
	uint16_t freq_arr=10e3/freq;
	__HAL_TIM_SET_PRESCALER(&htim1, 7200 - 1) //将进入TIM的频率设为10KHz
	__HAL_TIM_SET_AUTORELOAD(&htim1,freq_arr);
	__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,freq_arr/2);
	htim1.Instance->EGR=TIM_EGR_UG; //立即使配置生效
}

#define KEY_UP 1
#define KEY_DOWN 2
#define KEY_NONE 0
uint8_t read_button()
{
	if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)==0||HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==0)
	{
		HAL_Delay(20);//延时消抖
		if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==0)
		{
			HAL_Delay(500);
			return KEY_UP;
		}
		if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)==0)
		{
			HAL_Delay(500);
			return KEY_DOWN;
		}
	}
	else
		if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)==1&&HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==1)
			return KEY_NONE;
	return KEY_NONE;
}

主循环

 /* USER CODE BEGIN 2 */
  HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);//启用TIM定时器
  LED_blink(1);
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	switch(read_button())
	{
	case KEY_UP:
		++LED_freq;
		LED_blink(LED_freq);
		printf("Freq=%.2f\r\n",LED_freq);
			break;
	case KEY_DOWN:
		--LED_freq;
		LED_blink(LED_freq);
		printf("Freq=%.2f\r\n",LED_freq);
			break;
		default:
			break;
    }

项目文件下载地址

HAL库(Hardware Abstraction Layer)是STM32控制器系列提供的软件框架的一部分,用于简化硬件操作并提供一种标准接口,使得开发者能够更方便地管理设备资源如GPIO、定时器等。在STM32Key1开发板上,你可以使用HAL库来控制LED进行闪烁。 首先,你需要确保你已经在项目中包含了HAL库和相关的驱动头文件。通常步骤如下: 1. 初始化GPIO:打开STM32Key1的GPIO功能,选择相应的GPIO端口和引脚连接到LED。 ```matlab % 引入相关头文件 #include "stm32f4xx_hal.h" #include "stm32_key1.h" % GPIO初始化 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = LED_PIN; % 替换为实际的LED引脚 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; % 输出推挽模式 GPIO_InitStruct.Pull = GPIO_NOPULL; % 不用拉高或拉低 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); ``` 2. 定义定时器:创建一个定时器,设置周期用于控制LED闪烁频率。 ```matlab TIM_HandleTypeDef htim; TIM_TimeBaseInitTypeDef.TIM_Prescaler; TIM_TimeBaseInitTypeDef.TIM_Period; TIM_Prescaler.Prescaler = (SystemCoreClock / (2 * LED_FLASH_DELAY)) - 1; % 根据要求整延时 TIM_Period.Period = LED_FLASH_PERIOD; // LED闪烁周期 // 初始化定时器 htim.Instance = LED_TIMER; // 替换为实际的定时器实例 htim.Init.Prescaler = TIM_Prescaler; htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = TIM_Period; HAL_TIM_Base_Init(&htim); ``` 3. 设置定时器中断服务程序:配置定时器触发中断并在中断服务函数里切换LED状态。 ```matlab void HAL_TIM_Base_MspCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == LED_TIMER) { HAL_GPIO_TogglePin(LED_PORT, LED_PIN); // LED状态切换 } } // 开启中断 HAL_NVIC_EnableIRQ(LED_TIMER_IRQn); // 配置中断回 __HAL_TIM_BASE_REGISTER_CALLBACK(&htim, HAL_TIM_Base_MspCallback); ``` 4. 启动定时器:启动定时器并进入主循环。 ```matlab HAL_TIM_Base_Start_IT(&htim); while (1) { // 主循环执行其他任务 } ``` 以上只是一个基本的示例,具体细节可能因STM32Key1的具体配置和你的需求而有所不同。记得检查并适配你项目的具体硬件连接以及所使用的具体定时器类型。如果你遇到任何具体的错误或者有特殊的需求,请告诉我,我会进一步帮助你。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值