当前位置:   article > 正文

基于stm32f103c8t6、HAL库定时器控制灯亮灭&&PWM实现呼吸灯_stm32f103c8t6基于hal库实现led呼吸灯程序

stm32f103c8t6基于hal库实现led呼吸灯程序

一.定时器基本知识

定时器分类

1.基本定时器 基本定时器是一个简单的定时器,通常用于生成精确的时间延迟。它具有单个16位计数器,可以通过设置预分频系数实现不同的计数速度。基本定时器通常用于简单的定时任务。 2.通用定时器 通用定时器是一种更为复杂和功能强大的定时器,通常用于更复杂的定时和计数任务。STM32系列微控制器通常配备了多个通用定时器,如TIM1、TIM2等。通用定时器具有多个16位或32位计数器,可以通过设置预分频系数和计数周期来实现不同的计数速度和定时精度。 定时器应用 STM32定时器广泛应用于各种领域,包括工业控制、通信、嵌入式系统等。以下是一些常见的定时器应用场景:

1.定时中断:可以使用定时器生成周期性的中断信号,用于定时任务的触发和处理。 2.计时测量:可以使用定时器进行时间的测量和计算,如测量脉冲宽度、测量信号的频率等。 3.PWM输出:可以使用定时器生成精确的脉宽调制信号,用于控制电机速度、LED亮度等。 4.输入捕获:可以使用定时器进行外部信号的捕获,用于测量外部事件的时间戳。

定时器配置 为了配置和控制STM32定时器,我们可以使用相应的库函数或直接操作寄存器。以下是一些常用的配置参数:

1.预分频系数:用于设置定时器的计数速度,可以根据需要进行调整。 2.计数周期:用于设置定时器的计数周期,决定定时器溢出的时间间隔。 3.工作模式:定时器可以工作在不同的模式下,如定时器模式、计数器模式、PWM模式等。 4.中断使能:可以选择是否使能定时器的中断功能,用于触发中断任务。

二.定时器的应用1

1. 使用STM32F103的 Tim2~Tim5其一定时器的某一个通道pin(与GPIOx管脚复用,见下图),连接一个LED,用定时器计数方式,控制LED以2s的频率周期性地亮-灭 代码:

  1. #include "led.h"
  2. void LED_Config(void)
  3. {
  4. GPIO_InitTypeDef GPIO_InitStruct;
  5. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  6. GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
  7. GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
  8. GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
  9. GPIO_Init(GPIOB, &GPIO_InitStruct);
  10. }
  11. void LED_Toggle(void)
  12. {
  13. GPIOB->ODR ^= GPIO_Pin_0;
  14. }
  15. led.h
  16. #ifndef __LED_H
  17. #define __LED_H
  18. #include "stm32f10x.h"
  19. void LED_Config(void);
  20. void LED_Toggle(void);
  21. #endif
  22. tim_timebase.c
  23. #include "tim_timebase.h"
  24. #include "led.h"
  25. int a = 0;
  26. static void NVIC_Config(void)
  27. {
  28. NVIC_InitTypeDef NVIC_InitStruct;
  29. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  30. NVIC_InitStruct.NVIC_IRQChannel=TIM3_IRQn;
  31. NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
  32. NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
  33. NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
  34. NVIC_Init(&NVIC_InitStruct);
  35. }
  36. void TIM3_Config(void)
  37. {
  38. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
  39. NVIC_Config();
  40. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  41. TIM_TimeBaseInitStruct.TIM_Period=71;
  42. TIM_TimeBaseInitStruct.TIM_Prescaler=1000;//1ms
  43. TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);
  44. TIM_ClearFlag(TIM3, TIM_FLAG_Update);
  45. TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
  46. TIM_Cmd(TIM3, ENABLE);
  47. }
  48. void TIM3_IRQHandler(void)
  49. {
  50. if(TIM_GetITStatus(TIM3, TIM_IT_Update)) a++;
  51. if(a == 1000)
  52. {
  53. LED_Toggle();
  54. a = 0;
  55. }
  56. TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
  57. }

  1. tim_timebase.h
  2. #ifndef __TIM_TIMEBASE_H
  3. #define __TIM_TIMEBASE_H
  4. #include "stm32f10x.h"
  5. void TIM3_Config(void);
  6. #endif
 
  1. main.c
  2. #include "stm32f10x.h"
  3. #include "led.h"
  4. #include "tim_timebase.h"
  5. int main(void)
  6. {
  7. LED_Config();
  8. TIM3_Config();
  9. while(1)
  10. {
  11. }
  12. }

三.PWM的应用

2. 接上,采用定时器PWM模式,让 LED 以呼吸灯方式渐亮渐灭,周期为1~2秒,自己调整到一个满意效果。使用Keil虚拟示波器,观察 PWM输出波形。

代码 PWM.c

  1. #include "stm32f10x.h"                  // Device header
  2. void PWM_Init(void)
  3. {
  4. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  5. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  6. // RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
  7. // GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
  8. // GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
  9. GPIO_InitTypeDef GPIO_InitStructure;
  10. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  11. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIO_Pin_15;
  12. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  13. GPIO_Init(GPIOA, &GPIO_InitStructure);
  14. TIM_InternalClockConfig(TIM2);
  15. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  16. TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  17. TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  18. TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; //ARR
  19. TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1; //PSC
  20. TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
  21. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
  22. TIM_OCInitTypeDef TIM_OCInitStructure;
  23. TIM_OCStructInit(&TIM_OCInitStructure);
  24. TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  25. TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  26. TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  27. TIM_OCInitStructure.TIM_Pulse = 0; //CCR
  28. TIM_OC1Init(TIM2, &TIM_OCInitStructure);
  29. TIM_Cmd(TIM2, ENABLE);
  30. }
  31. void PWM_SetCompare1(uint16_t Compare)
  32. {
  33. TIM_SetCompare1(TIM2, Compare);
  34. }
main.c
  1. #include "stm32f10x.h"                  // Device header
  2. #include "Delay.h"
  3. #include "OLED.h"
  4. #include "PWM.h"
  5. uint8_t i;
  6. int main(void)
  7. {
  8. OLED_Init();
  9. PWM_Init();
  10. while (1)
  11. {
  12. for (i = 0; i <= 100; i++)
  13. {
  14. PWM_SetCompare1(i);
  15. Delay_ms(5);
  16. }
  17. for (i = 0; i <= 100; i++)
  18. {
  19. PWM_SetCompare1(100 - i);
  20. Delay_ms(5);
  21. }
  22. }
  23. }

使用Keil虚拟示波器,观察 PWM输出波形

标为bit显示,用绿色的线表示,得到的波形结果如下图所示:

四.总结

通过本次实验实现了LED以2秒的频率周期性地亮-灭,采用定时器的PWM模式,通过配置定时器的参数和相关寄存器,实现LED了以呼吸灯方式渐亮渐灭 通过Keil虚拟示波器,我们可以观察PWM输出波形,以验证PWM的正确性;在实验前做了充分的准备,仔细阅读了相关的STM32定时器和PWM模式的文档,理解其寄存器的配置方法和中断处理函数的编写并且熟悉了Keil虚拟示波器的使用方法,以便观察波形输出。 本次实验帮助我们更深入地了解STM32的定时器原理和PWM,通过实际操作和观察波形,我们会更好地掌握和理解定时器和PWM的工作原理。在进行呼吸灯效果测试时,发现当PWM周期很大时,呼吸灯效果十分不明显,可以从PWM波原理上看,修改的只是高电平的占比,那么如果周期很大,即使占空比怎么修改,人眼中还是会看出来亮灭的过程,当PWM频率提高时,人眼就无法识别出低电平的间隙,从而看出来是从亮到灭的过程。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/565736
推荐阅读
相关标签
  

闽ICP备14008679号