[STM32H7] STM32 TIM定时器输出比较

[复制链接]
1043|9
 楼主| qn7a12 发表于 2021-10-25 22:02 | 显示全部楼层 |阅读模式
STM32 TIM定时器输出比较
使用Timer进行周期定时

在STM32的某些应用中,用户有周期性执行某些程序的要求,使用定时器可以产生固定的时间周期,满足 这样的需求。

STM32相关特征:
STM32高级定时器TIM1、TIM8,通用定时器TIM2、TIM3、TIM4、TIM5;
定时器最大时钟72MHz,配合预分频,提供灵活的时钟周期;
每个TIM有4个独立捕获/比较通道,DMA/中断功能;
通道工作在输出比较定时模式,一个TIM至多可以提供4个不同的定时周期。


 楼主| qn7a12 发表于 2021-10-25 22:03 | 显示全部楼层
原理
TIM某输出/捕获通道工作在输出比较定时模式
计数器计数至比较值时产生中断,在中断中刷新捕获比较寄存器,这样在相同时间间隔后可产生下一次中断


TIM2时钟设置为36MHz,预分频设置为2,使用输出比较-翻转模式(Output Compare Toggle Mode)。

TIM2计数器时钟可表达为:TIM2 counter clock = TIMxCLK / (Prescaler +1) = 12 MHz

设置TIM2_CCR1寄存器值为32768,则CC1更新频率为TIM2计数器时钟频率除以CCR1寄存器值,为366.2 Hz。因此,TIM2通道1可产生一个频率为183.1 Hz的周期信号。

同理,根据寄存器TIM2_CCR2 、TIM2_CCR3和 TIM2_CCR4的值,TIM2通道2可产生一个频率为366.3 Hz的周期信号;TIM2通道3可产生一个频率为732.4 Hz的周期信号;TIM2通道4可产生一个频率为1464.8 Hz的周期信号。
 楼主| qn7a12 发表于 2021-10-25 22:04 | 显示全部楼层
可以通过示波器观察各路输出。

172796176b961698a5.png
 楼主| qn7a12 发表于 2021-10-25 22:05 | 显示全部楼层
本帖最后由 qn7a12 于 2021-10-25 22:13 编辑


  1. #include "stm32f10x_lib.h"





  2. TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  3. TIM_OCInitTypeDef  TIM_OCInitStructure;
  4. vu16 CCR1_Val = 32768;
  5. vu16 CCR2_Val = 16384;
  6. vu16 CCR3_Val = 8192;
  7. vu16 CCR4_Val = 4096;
  8. ErrorStatus HSEStartUpStatus;


  9. void RCC_Configuration(void);
  10. void GPIO_Configuration(void);
  11. void NVIC_Configuration(void);
  12.    


  13. int main(void)
  14. {
  15. #ifdef DEBUG
  16.   debug();
  17. #endif


  18.   RCC_Configuration();


  19.   NVIC_Configuration();


  20.   GPIO_Configuration();




  21.   TIM_TimeBaseStructure.TIM_Period = 65535;   //这里必须是65535
  22.      
  23.   TIM_TimeBaseStructure.TIM_Prescaler = 2;      
  24.   TIM_TimeBaseStructure.TIM_ClockDivision = 0;   
  25.   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  26.   TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);


  27.   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;  //管脚输出模式:翻转(TIM输出比较触发模式)
  28.    
  29.   TIM_OCInitStructure.TIM_Channel = TIM_Channel_1;         
  30.   TIM_OCInitStructure.TIM_Pulse = CCR1_Val;   //翻转周期

  31.   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//TIM输出比较极性低

  32.   TIM_OCInit(TIM2, &TIM_OCInitStructure);

  33.   TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable);//失能TIMx在CCR1上的预装载寄存器


  34.   TIM_OCInitStructure.TIM_Channel = TIM_Channel_2;         
  35.   TIM_OCInitStructure.TIM_Pulse = CCR2_Val;

  36.   TIM_OCInit(TIM2, &TIM_OCInitStructure);

  37.   TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable);


  38.   TIM_OCInitStructure.TIM_Channel = TIM_Channel_3;         
  39.   TIM_OCInitStructure.TIM_Pulse = CCR3_Val;

  40.   TIM_OCInit(TIM2, &TIM_OCInitStructure);

  41.   TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable);


  42.   TIM_OCInitStructure.TIM_Channel = TIM_Channel_4;         
  43.   TIM_OCInitStructure.TIM_Pulse = CCR4_Val;

  44.   TIM_OCInit(TIM2, &TIM_OCInitStructure);

  45.   TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Disable);


  46.   TIM_Cmd(TIM2, ENABLE);


  47.   TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);

  48.   while (1)
  49.   {
  50.   }
  51. }


  52. void RCC_Configuration(void)
  53. {  

  54.   RCC_DeInit();


  55.   RCC_HSEConfig(RCC_HSE_ON);


  56.   HSEStartUpStatus = RCC_WaitForHSEStartUp();

  57.   if(HSEStartUpStatus == SUCCESS)
  58.   {
  59.    
  60.     FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

  61.    
  62.     FLASH_SetLatency(FLASH_Latency_2);

  63.    
  64.     RCC_HCLKConfig(RCC_SYSCLK_Div1);

  65.    
  66.     RCC_PCLK2Config(RCC_HCLK_Div1);

  67.    
  68.     RCC_PCLK1Config(RCC_HCLK_Div4);

  69.    
  70.     RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

  71.    
  72.     RCC_PLLCmd(ENABLE);

  73.    
  74.     while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
  75.     {
  76.     }

  77.    
  78.     RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

  79.    
  80.     while(RCC_GetSYSCLKSource() != 0x08)
  81.     {
  82.     }
  83.   }


  84.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);


  85.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  86. }


  87. void GPIO_Configuration(void)
  88. {
  89.   GPIO_InitTypeDef GPIO_InitStructure;


  90.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
  91.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  92.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  93.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  94. }


  95. void NVIC_Configuration(void)
  96. {
  97.   NVIC_InitTypeDef NVIC_InitStructure;
  98.   
  99. #ifdef  VECT_TAB_RAM

  100.   NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
  101. #else

  102.   NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);  
  103. #endif


  104.   NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel;
  105.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  106.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  107.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  108.   NVIC_Init(&NVIC_InitStructure);
  109. }

  110. #ifdef  DEBUG

  111. void assert_failed(u8* file, u32 line)
  112. {


  113.   while (1)
  114.   {
  115.   }
  116. }
  117. #endif
 楼主| qn7a12 发表于 2021-10-25 22:08 | 显示全部楼层
本帖最后由 qn7a12 于 2021-10-25 22:14 编辑
  1. 中断服务:



  2. void TIM2_IRQHandler(void)
  3. {

  4.   if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//检查指定的TIM中断发生与否
  5.   {
  6.     TIM_ClearITPendingBit(TIM2, TIM_IT_CC1 );//清除TIMx的中断待处理位
  7. capture = TIM_GetCapture1(TIM2);
  8. TIM_SetCompare1(TIM2, capture + CCR1_Val );//设置TIMx自动重装载寄存器值
  9.         //将TIM2_CC1的值增加CCR1_Val,使得下一个TIM事件也需要CCR1_Val个脉冲,

  10.   }


  11.   if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)
  12.   {
  13.      TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
  14. capture = TIM_GetCapture2(TIM2);
  15.     TIM_SetCompare2(TIM2, capture + CCR2_Val);
  16.   }


  17.   if (TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET)
  18.   {
  19.     TIM_ClearITPendingBit(TIM2, TIM_IT_CC3);
  20. capture = TIM_GetCapture3(TIM2);
  21.     TIM_SetCompare3(TIM2, capture + CCR3_Val);
  22.   }


  23.   if (TIM_GetITStatus(TIM2, TIM_IT_CC4) != RESET)
  24.   {
  25.     TIM_ClearITPendingBit(TIM2, TIM_IT_CC4);
  26. capture = TIM_GetCapture4(TIM2);
  27.     TIM_SetCompare4(TIM2, capture + CCR4_Val);
  28.   }  
  29. }

coshi 发表于 2021-11-8 12:02 | 显示全部楼层
定时器的种类和数量都很多
drer 发表于 2021-11-8 12:05 | 显示全部楼层
捕获的话 对电平有限制吗
aoyi 发表于 2021-11-8 12:08 | 显示全部楼层
需要吧定时器配置在什么模式下呢
zljiu 发表于 2021-11-8 12:10 | 显示全部楼层
看波形的话 效果还是非常好的
wiba 发表于 2021-11-8 12:12 | 显示全部楼层
哪些定时器有这个功能呢
您需要登录后才可以回帖 登录 | 注册

本版积分规则

40

主题

542

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部