STM32
直播中

费加罗

8年用户 817经验值
私信 关注
[问答]

STM32定时器总断配置过程是怎样的

STM32三种定时器有何区别呢?

STM32通用定时器的特点有哪些?
STM32定时器总断配置过程是怎样的?

回帖(1)

杨云

2021-11-23 09:22:34
  三种定时器的区别
  STM32F1xx系列总共有 八个定时器
  两个高级定时器 + 四个通用定时器 + 两个基本定时器
  
  通用定时器的特点描述
  1.位于ABP1低速总线上
  2.16位向下,向上/向下(中心对齐模式)计数模式,自动重装载计数器(TIMx_CNT)
  3.16位可编程(可以实现修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为1~65535任意数值
  4.四个独立通道(TIMx_CH1~4),通道用来支持:
  ①输入捕获
  ②输出比较
  ③PWM生成
  ④单脉冲模式输出
  5.可使用外部信号(TIM_ETR)控制定时器和定时器互连的同步威廉希尔官方网站 。
  AHB系统总线是72M的,桥接出来的APB2也是72M的,APB1有个二分频,所以是36M,是低速的时钟。
  
  定时器中断/事件产生 : (六个独立的IRQ/DMA 请求生成器)
  ①更新: 计数器向上/向下溢出,计数器初始化(软件或者外部/内部触发)
  ②触发事件:计数器的启动,停止,初始化或者由内部/外部触发计数
  ③输入捕获
  ④输出比较
  ⑤支持针对定位的增量编码器和霍尔传感器威廉希尔官方网站
  ⑥触发输入作为外部时钟或者按周期的电流管理
  STM32通用定时器 可以被用于:测量输入信号的脉冲长度(输入捕获),或者产生输入波形(输出比较和PWM)等。
  定时器的预分频器和RCC时钟控制预分频器,脉冲长度和波形周期可以在us到ms之间调整,每个通用定时器都是完全独立,没有互相共享任何内存。
  计数器模式
  STM32通用定时器 可以向上,向下,向上/向下双向计数模式
  ① 向上计数模式:计数值从0 计数到自动加载值(TIM_ARR),产生一个计数溢出事件,然后重新从0开始计数
  ②向下计数模式:计数器从自动装入的值(TIM_ARR)开始向下计数到0,产生一个计数溢出事件,然后从计数装入值重新开始。
  ③中央对齐模式:计数器从0开始到(自动装入值-1),产生计数溢出事件,然后向下计数到1,产生定时器溢出事件,然后从0开始计数。
  
  通用定时器工作过程
  1.时钟部分(时钟来源)
  ①内部时钟APB1倍频器
  ②外部引脚(通用定时器2,3,4)
  ③其他定时器
  ④外部通道
  2.时基单元
  ①预分频(除法)
  ②计数器时钟
  ③自动重装载值
  3.输入部分
  ①输入引脚
  ②边沿检测
  4.输出部分
  ①输出比较寄存器
  周期—重装载值
  占空比—比较值
  
  计数器时钟计算方法
  
  CK_INT是定时器时钟,APB1到CK_INT会 乘于1或者除于2
  为什么要 乘于1或者除于2?
  
  除非APB1分频系数为1,否则通用定时器时钟为PAB1的两倍
  举例:
  AHB= 72M
  APB1=36M (分频系数为2)
  通用定时器时钟为 36 x2= 72M
  CK_PSC:预分频器时钟的频率
  
  CK_PSC分频多少就除于N,就可以得到CK_CNT(计数器的频率)
  定时器相关寄存器
  1.计数器寄存器CNT : 当前计数值
  2.预分频寄存器 : 分频系数 (PSC+1) / N = CNT
  3.自动重装载寄存器: 重装载值
  4.控制寄存器: 控制计数方向
  定时器库函数结构体
  常用的是前四个成员,后面一个用于高级定时器
  typedef struct
  {
  uint16_t TIM_Prescaler; //初始化预分频值
  uint16_t TIM_Period; //设定自动装载值
  uint16_t TIM_CounterMode; //设定计数模式
  uint16_t TIM_ClockDivision; //输入捕获使用
  uint8_t TIM_RepetitionCounter; //高级定时器使用
  } TIM_TimeBaseInitTypeDef;
  定时器库函数结构体
  void TIM_TimeBaseInit 定时器初始化
  (TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
  void TIM_Cmd 定时器使能
  (TIM_TypeDef* TIMx, FunctionalState NewState);
  FlagStatus TIM_GetFlagStatus 定时器状态标志位
  (TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
  void TIM_ClearFlag 定时器清楚标志位
  (TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
  ITStatus TIM_GetITStatus 定时器中断标志位
  (TIM_TypeDef* TIMx, uint16_t TIM_IT);
  void TIM_ClearITPendingBit 定时器清楚中断标志位
  (TIM_TypeDef* TIMx, uint16_t TIM_IT);
  定时器总断配置过程
  1.使能时钟 定时器时钟
  2. 配置定时器结构体 ,
  3.开启定时器中断,配置中断结构体
  4.中断服务函数
  定时器配置LED每秒闪烁一次
  Tout = [ 重装载值(ARR+1) * 分频系数(PSC+1)] /Tclk(定时器的时钟)
  Tout = 100000(9999+1) *7200(分频系数 7199+1) /72M(72 000 000)
  通过定时器让LED灯间隔1s闪烁
  led.h
  #include “stm32f10x.h”
  void Led_init(void);
  led.c
  #include “stm32f10x.h”
  #include “led.h”
  void Led_init(void)
  {
  GPIO_InitTypeDef Led_init;
  //1.ʹÄÜAPB2µÄʱÖÓGPIO
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
  //2.½á¹¹ÌåÅäÖÃ
  Led_init.GPIO_Mode = GPIO_Mode_Out_PP;
  Led_init.GPIO_Pin = GPIO_Pin_13;
  Led_init.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_Init(GPIOC, &Led_init);
  }
  tim.h
  #include “stm32f10x.h”
  void tim_Init(void);
  tim.c
  #include “stm32f10x.h”
  #include “tim.h”
  /*
  1.ʹÄÜʱÖÓ£¬¶¨Ê±Æ÷ʱÖÓ
  2.ÅäÖö¨Ê±Æ÷½á¹¹Ìå
  3.¿ªÆô¶¨Ê±Æ÷Öжϣ¬ÅäÖÃÖжϽṹÌå
  */
  void tim_Init(void)
  {
  TIM_TimeBaseInitTypeDef timInitStruct;
  NVIC_InitTypeDef nvicInitStruct;
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  timInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
  timInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
  timInitStruct.TIM_Period = 10000 - 1;
  timInitStruct.TIM_Prescaler = 7200 - 1;
  TIM_TimeBaseInit(TIM2,&timInitStruct);
  TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
  TIM_Cmd(TIM2,ENABLE);
  nvicInitStruct.NVIC_IRQChannel = TIM2_IRQn;
  nvicInitStruct.NVIC_IRQChannelPreemptionPriority = 1;
  nvicInitStruct.NVIC_IRQChannelSubPriority = 1;
  nvicInitStruct.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&nvicInitStruct);
  }
  main.c
  #include “stm32f10x.h”
  #include “led.h”
  #include “relay.h”
  #include “shake.h”
  #include “exti.h”
  #include “usart.h”
  #include “stdio.h”
  #include “tim.h”
  void delay(uint16_t time)
  {
  uint16_t i =0;
  while(time--){
  i=12000;
  while(i--);
  }
  }
  int main()
  {
  Led_init();
  Relay_Init();
  Shake_init();
  exti_init();
  usart_init();
  tim_Init();
  //³õʼ»¯Òý½Å
  GPIO_SetBits(GPIOA, GPIO_Pin_3);
  GPIO_SetBits(GPIOC, GPIO_Pin_13);
  // while(1)
  // {
  // usartSendStr(USART1,“°ÂÀï¸ø\r\n”);
  // int i = printf(“Finny\r\n”);
  // printf(“%d\r\n”,i);
  // putchar(‘2’);
  // delay(1000);
  // }
  }
  //ÍⲿÖжÏ
  //void EXTI1_IRQHandler(void)
  //{
  // if (EXTI_GetITStatus( EXTI_Line1 ) != RESET){// ÅжÏÊÇ·ñ·¢ÉúÖжÏ
  // GPIO_ResetBits(GPIOA, GPIO_Pin_3);
  // usartSendStr(USART1,“Open light success\r\n”);
  // delay(1000);
  // GPIO_SetBits(GPIOA, GPIO_Pin_3);
  // usartSendStr(USART1,“Close light success\r\n”);
  // }
  // EXTI_ClearFlag(EXTI_Line1);
  //
  //}
  //´®¿ÚÖжÏ
  //void USART1_IRQHandler(void)
  //{
  // char temp;
  //
  // if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET){
  //
  // temp = USART_ReceiveData(USART1);
  // if(temp == ‘o’){
  // GPIO_ResetBits(GPIOC, GPIO_Pin_13);
  // usartSendStr(USART1,“Open LED light success\r\n”);
  // }
  //
  // if(temp == ‘c’){
  // GPIO_SetBits(GPIOC, GPIO_Pin_13);
  // usartSendStr(USART1,“Close LED light success\r\n”);
  // }
  //
  // }
  //}
  //¶¨Ê±Æ÷ÖжÏ
  void TIM2_IRQHandler(void)
  {
  static uint16_t temp;
  if(TIM_GetITStatus(TIM2,TIM_IT_Update) != RESET)
  {
  if(temp++ %2 == 1){
  GPIO_ResetBits(GPIOC, GPIO_Pin_13);
  }else{
  GPIO_SetBits(GPIOC, GPIO_Pin_13);
  }
  }
  TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
  }
举报

更多回帖

发帖
×
20
完善资料,
赚取积分