STM32HAL库定时器中断以及呼吸灯实验

1.定时器延时2s实验

一、CubeMX生成项目文件。

        在使用HAL库时,如何使用定时器定时是我们需要掌握的,下面的实验演示了定时器如何定时2s。

        首先打开CubeMX,创建一个自己芯片的项目。

        找到SYS,修改Debug为Serial Wire。

        

        转到RCC,修改High Speed Clock。

         

        本次实验打算用PA0做管脚闪烁灯,所以这里初始化了GPIOA_PIN_0。

   

     

        点击TIM2,修改Clock Source,将Prescaler和Counter Period修改为4999和6399,这两个值会决定中断时间,公式为:

  Tout= ((arr+1)*(psc+1))/Tclk 

这里psc取4999,arr取6399,Tclk在下面会设置为16Mhz,所以Tout=(5000*6400)/16 us=2 s.

        

        修改clk。

 

        

         最后修改项目名称,IDE等,点击GENERATE CODE生成对应的项目。

二、编写代码

        在main函数while循环前,加一句HAL_TIM_Base_Start_IT(&htim2);,初始化定时器中断函数

HAL_TIM_Base_Start_IT(&htim2);

        在生成的项目中找到main函数,加入定时器中断函数,由于是中断函数,所以我们不需要写在while主循环里,写在主函数外面就行,这里选择写在USER CODE 4中。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    static unsigned char ledState = 0;
    if (htim == (&htim2))
    {
        if (ledState == 0)
            HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET);
        else
            HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET);
        ledState = !ledState;
    }
}

 关于keil5的烧录可以看我的上篇博客:STM32新手入门篇之HAL库点灯-CSDN博客

效果图:

2.使用PWM波生成呼吸灯

 PWM波点灯可以达到一个缓慢熄灭和缓慢点亮的效果,效果图如下

 打开CubeMX,我们可以在上面定时器中断的项目上修改项目设置。

        按照上面定时器的方式修改RCC和SYS,在TIM2修改Clock Source、Channel1,下方修改PSC和Counter Period,修改这两个值可以改变呼吸灯的频率,具体搜索PWM波原理,这里选择的是199和499,你可以尝试调低PSC为99会有不一样的效果,然后将auto-reload preload修改为Enable,在NVIC Setting勾上ENABLE。

        然后按照之前的方式调节时钟和项目设置 。

生成项目后我们打开keil5,编写代码。

int main(void)
{

  /* USER CODE BEGIN 1 */
		uint16_t pwmVal=0;   //PWM占空比  
   // uint8_t dir=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_TIM2_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
		while (pwmVal< 500)
	  {
		  pwmVal++;
		  __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, pwmVal);    //修改比较值,修改占空比
//		  TIM3->CCR1 = pwmVal;   
		  HAL_Delay(1);
	  }
	  while (pwmVal)
	  {
		  pwmVal--;
		  __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, pwmVal);    //修改比较值,修改占空比
//		  TIM3->CCR1 = pwmVal;    
		  HAL_Delay(1);
	  }
	  HAL_Delay(200);

    /* USER CODE BEGIN 3 */
  /* USER CODE END 3 */
}}

        代码编写完毕,我们在对应引脚连上LED即可查看效果,在CubeMX右侧可以看到TIM2对应的引脚为PA15。

最后我们在keil示波器上查看一下PWM波形,具体方法查看STM32新手入门篇之HAL库点灯-CSDN博客

可以看到波形类似与渐变的一个效果,所以表现出呼吸灯。 

  • 14
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
呼吸灯的实现需要使用PWM(脉冲宽度调制)技术,通过改变PWM占空比来调整LED亮度。以下是使用STM32 HAL库实现呼吸灯的步骤: 1. 初始化定时器和PWM输出通道 ```c TIM_HandleTypeDef htim; TIM_OC_InitTypeDef sConfigOC; // 初始化定时器 htim.Instance = TIMx; htim.Init.Prescaler = 0; htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = period - 1; // PWM周期 htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(&htim); // 配置PWM输出通道 sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; // 初始占空比为0 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_x); ``` 2. 开始呼吸灯循环 ```c uint16_t duty_cycle = 0; // 占空比 uint16_t step = 10; // 占空比每次增加/减少的步长 while (1) { // 呼吸灯向上渐亮 for (duty_cycle = 0; duty_cycle <= period; duty_cycle += step) { sConfigOC.Pulse = duty_cycle; HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_x); HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_x); HAL_Delay(10); } // 呼吸灯向下渐暗 for (duty_cycle = period; duty_cycle >= 0; duty_cycle -= step) { sConfigOC.Pulse = duty_cycle; HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_x); HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_x); HAL_Delay(10); } } ``` 通过修改`step`的值可以调整呼吸灯的渐变速度,即亮度变化的平滑程度。注意要在`while`循环中调用`HAL_TIM_PWM_ConfigChannel`和`HAL_TIM_PWM_Start`函数来更新PWM输出通道的占空比和启动PWM输出。 完整的代码示例:(以STM32F407为例,使用PA0引脚控制LED) ```c #include "main.h" #include "stm32f4xx_hal.h" #define TIMx TIM2 TIM_HandleTypeDef htim; TIM_OC_InitTypeDef sConfigOC; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_TIM_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM_Init(); uint16_t period = 1000; // PWM周期 // 初始化定时器 htim.Instance = TIMx; htim.Init.Prescaler = 0; htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = period - 1; // PWM周期 htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(&htim); // 配置PWM输出通道 sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; // 初始占空比为0 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_1); uint16_t duty_cycle = 0; // 占空比 uint16_t step = 10; // 占空比每次增加/减少的步长 while (1) { // 呼吸灯向上渐亮 for (duty_cycle = 0; duty_cycle <= period; duty_cycle += step) { sConfigOC.Pulse = duty_cycle; HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_1); HAL_Delay(10); } // 呼吸灯向下渐暗 for (duty_cycle = period; duty_cycle >= 0; duty_cycle -= step) { sConfigOC.Pulse = duty_cycle; HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_1); HAL_Delay(10); } } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /** 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 = 25; RCC_OscInitStruct.PLL.PLLN = 336; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 7; 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_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } } static void MX_TIM_Init(void) { TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; htim.Instance = TIMx; htim.Init.Prescaler = 0; htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = 1000 - 1; htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; if (HAL_TIM_PWM_Init(&htim) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim, &sMasterConfig) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; if (HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); GPIO_InitStruct.Pin = GPIO_PIN_0; 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); } void Error_Handler(void) { __disable_irq(); while (1) {} } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值