当前位置:   article > 正文

[STM32学习笔记] 3.TIM_stm32l timer

stm32l timer

【系列笔记为跟随UP主江协科技学习STM32过程的一些问题,同时方便日后忘记时复习,文中部分内容来源于UP主的PPT同时加入个人理解】

一.TIM简介

TIM(Timer)定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断 ,16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时 不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能 根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型。

类型

编号

总线

功能

高级定时器

TIM1、TIM8

APB2

拥有通用定时器全部功能,并额外具有重复计数器、死区生成、互补输出、刹车输入等功能

通用定时器

TIM2、TIM3、TIM4、TIM5

APB1

拥有基本定时器全部功能,并额外具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能

基本定时器

TIM6、TIM7

APB1

拥有定时中断、主模式触发DAC的功能

 

 二.定时器中断

1.定时器中断基本结构

 

2.定时器中断常用库函数

 

  1. void TIM_DeInit(TIM_TypeDef* TIMx);//将指定的 TIM 外设重置为默认值。
  2. void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);//配置 TIM 的时基结构体。
  3. void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);//将 TIM 时间基准结构体初始化为默认设置。
  4. void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);//使能或禁用指定的 TIM 外设。
  5. void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);//使能或禁用指定 TIM 的指定中断。
  6. void TIM_InternalClockConfig(TIM_TypeDef* TIMx);//将内部时钟驱动 TIM 外设。
  7. void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);//配置 TIM 的预分频器和自动重装载寄存器的重新加载方式。
  8. void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);//配置 TIM 的计数器模式。
  9. void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);//使能或禁用 TIM 的自动重装载寄存器预加载功能。
  10. void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);//设置 TIM 的计数器值。
  11. void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);//设置 TIM 的自动重装载寄存器值。
  12. uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);//获取 TIM 的当前计数器值。
  13. uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);//获取 TIM 的预分频器值。
  14. FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);//检查 TIM 的指定标志位的状态。
  15. void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);//清除 TIM 的指定标志位。
  16. ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);//检查 TIM 的指定中断标志位的状态。
  17. void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);//清除 TIM 的指定中断标志位。

3.定时器中断初始化

  1. void Timer_EXITInit()
  2. {
  3. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_TIM3, ENABLE); //使能 APB1 时钟
  4. //将定时器2配置为内部时钟模式
  5. TIM_InternalClockConfig(TIM2);
  6. TIM_InternalClockConfig(TIM3);
  7. //初始化定时器时间基数
  8. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
  9. TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; // 设置时钟分频为不分频,对内部时钟无影响
  10. TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; // 设置计数模式
  11. TIM_TimeBaseInitStruct.TIM_Period = 10000-1; // 设置重载值
  12. TIM_TimeBaseInitStruct.TIM_Prescaler = 7200; // 设置预分频值
  13. TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; // 设置重复计数器为0,高级定时器参数
  14. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
  15. //清除中断标志位,避免上电进入中断
  16. TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  17. TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
  18. //启用定时器的更新中断 (TIM_IT_Update 更新(溢出)中断)
  19. TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
  20. TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
  21. //设置中断优先级组为2位抢占优先级+2位子优先级
  22. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  23. //配置中断管理寄存器
  24. NVIC_InitTypeDef NVIC_InitStructure;
  25. NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //选择中断通道为TIM2
  26. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  27. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //设置抢占式优先级为10~2^2
  28. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //设置子优先级为1 (0~2^2)
  29. NVIC_Init(&NVIC_InitStructure);
  30. }

4.定时器中断功能函数

  1. void TIM2_IRQHandler()
  2. {
  3. if(TIM_GetITStatus(TIM2,TIM_FLAG_Update) == SET)
  4. {
  5. TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update);
  6. }
  7. }

五.TIM输出比较(PWM)

1.OC(Output Compare)输出比较,输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形 每个高级定时器和通用定时器都拥有4个输出比较通道。

2.输出比较模式:

模式

描述

冻结

CNT=CCR时,REF保持为原状态

匹配时置有效电平

CNT=CCR时,REF置有效电平

匹配时置无效电平

CNT=CCR时,REF置无效电平

匹配时电平翻转

CNT=CCR时,REF电平翻转

强制为无效电平

CNT与CCR无效,REF强制为无效电平

强制为有效电平

CNT与CCR无效,REF强制为有效电平

PWM模式1

向上计数:CNT<CCR时,REF置有效电平,CNT≥CCR时,REF置无效电平

向下计数:CNT>CCR时,REF置无效电平,CNT≤CCR时,REF置有效电平

PWM模式2

向上计数:CNT<CCR时,REF置无效电平,CNT≥CCR时,REF置有效电平

向下计数:CNT>CCR时,REF置有效电平,CNT≤CCR时,REF置无效电平

常用模式一/二产生PWM信号。 

3.输出比较基本结构:

 

4.TIM3产生频率1khz,占空比50%PWM信号代码如下:

  1. void PWM_Init()
  2. {
  3. // 使能TIM3时钟
  4. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  5. // 使能GPIOA时钟
  6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  7. // 配置GPIOA的引脚6为复用推挽输出
  8. GPIO_InitTypeDef GPIOA_InitStructure;
  9. GPIOA_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  10. GPIOA_InitStructure.GPIO_Pin = GPIO_Pin_6;
  11. GPIOA_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  12. GPIO_Init(GPIOA, &GPIOA_InitStructure);
  13. // 配置定时器(TIM3)为内部时钟模式
  14. TIM_InternalClockConfig(TIM3);
  15. // 配置定时器(TIM3)的时间基准参数
  16. TIM_TimeBaseInitTypeDef TIM_TimeBase_InitStructure;
  17. TIM_TimeBase_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//决定数字滤波器采样频率的参数(输入捕获)
  18. TIM_TimeBase_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
  19. TIM_TimeBase_InitStructure.TIM_Period = 100 - 1; // 频率=72MHz/720/100=1khz
  20. TIM_TimeBase_InitStructure.TIM_Prescaler = 720 - 1; // 设置预分频值为720,分频后计数器频率为72Mhz/720=100000
  21. TIM_TimeBase_InitStructure.TIM_RepetitionCounter = 0;//产生单个周期的PWM信号
  22. TIM_TimeBaseInit(TIM3, &TIM_TimeBase_InitStructure);
  23. // 配置定时器(TIM3)的输出比较参数
  24. TIM_OCInitTypeDef TIM_OCInit_InitStructure;
  25. TIM_OCStructInit(&TIM_OCInit_InitStructure);//不对结构体互补输出成员赋值,先赋默认值
  26. TIM_OCInit_InitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  27. TIM_OCInit_InitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//极性选择,高电平有效,若比较器输出高电平则为PWM高电平;低电平有效,若比较器输出低电平则为PWM高电平
  28. TIM_OCInit_InitStructure.TIM_OutputState = TIM_OutputState_Enable;//定时器通道使能
  29. TIM_OCInit_InitStructure.TIM_Pulse = 50; // 设置占空比为50%
  30. TIM_OC1Init(TIM3, &TIM_OCInit_InitStructure);
  31. // 使能定时器(TIM3)
  32. TIM_Cmd(TIM3, ENABLE);
  33. }

5.运行过程修改预分频数和计数溢出值函数:

  1. void updatePWMFrequency(uint16_t newPrescaler, uint16_t newPeriod)
  2. {
  3. TIM_Cmd(TIM3, DISABLE); //关闭定时器后才可修改
  4. TIM_PrescalerConfig(TIM3, newPrescaler, TIM_PSCReloadMode_Immediate);// 配置新的预分频值,立即生效
  5. TIM_SetAutoreload(TIM3, newPeriod);//配置新的溢出值
  6. TIM_Cmd(TIM3, ENABLE);
  7. }

6.PWM实现呼吸灯:

  1. int main()
  2. {
  3. OLED_Init();
  4. PWM_Init();
  5. delay_init();
  6. EXTI_LEDInit();
  7. while(1)
  8. {
  9. OLED_ShowString(1,1,"frequency:");
  10. OLED_ShowNum(1,11,100-Pulse,3);
  11. OLED_ShowChar(1,14,'%');
  12. for(i = 0;i <= Pulse;i++)
  13. {
  14. TIM_SetCompare1(TIM3,i);
  15. delay_ms(10);
  16. }
  17. for(i = Pulse;i > 0;i--)
  18. {
  19. TIM_SetCompare1(TIM3,i);
  20. delay_ms(10);
  21. }
  22. }
  23. }

六.PWMI输入捕获

 1.输入捕获简介:IC(Input Capture)输入捕获 输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数 每个高级定时器和通用定时器都拥有4个输入捕获通道 可配置为PWMI模式,同时测量频率和占空比 可配合主从触发模式,实现硬件全自动测量。

2.频率测量方法:

        测频法:在时间T内,对上升沿计次,得到N,则频率 f=N / T,适用高频,频率越高标准时间内N越大,误差越小; 

        测周法:两个上升沿内,以标准频率fc计次,得到N ,则频率 f=f c/ N,适用低频,频率越低,周期越长,N越大,误差越小;

        中界频率:测频法与测周法误差相等的频率点 f=sqrt(fc/T)。

3.主从触发模式:

 

         主模式:可以将定时器内部的信号,映射到TRGO引脚,用于触发别的外设,所以这部分叫做主模式。

        从模式:就是接收其他外设或者自身外设一些信号,用于控制自身定时器的运行,也就是被别的信号控制。

        触发源选择:就是选择从模式的触发信号源,触发源选择,选择指定的一个信号,得到TRGI,TRGI去触发从模式,从模式可以在这个列表里,选这择项操作来在自动执行。

相关函数;

void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource);

 1.主模式输入信号选择(主模式暂不了解)

void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);

2. 从模式输入信号选择,TIM_InputTriggerSource选择通道。(TIM_TS_TI1FP1)

void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);

 3.从模式选择:

复位模式(TIM_SlaveMode_Reset )– 选中的触发输入(TRGI)的 上升沿 重新初始化计数器,并且产生一个更新寄存 器的信号。
门控模式(TIM_SlaveMode_Gated)  – 当触发输入 (TRGI) 为高时,计数器的时钟开启。一旦触发输入变为低,则计
数器停止 ( 但不复位 ) 。计数器的启动和停止都是受控的。
触发模式(TIM_SlaveMode_Trigger )– 计数器在触发输入 TRGI 的上升沿启动 ( 但不复位 ) ,只有计数器的启动是受控
的。
外部时钟模式1( TIM_SlaveMode_External1) – 选中的触发输入 (TRGI) 的上升沿驱动计数器

4.输入捕获基本结构:

TIM3从上升沿开始计数,到达下降沿后触发TI1FP2,CCR2=CNT,到达上升沿后CCR1=CNT,同时触发从模式,CNT重置。频率=fc/CCR1,占空比=CCR2/CCR1。

 TIMx_CH1和TIMx_CH2可同时接入同一捕获寄存器测量不同参数。由TIxFPy进行配置,表示由通道x输入至通道y的捕获寄存器。

5.输入捕获初始化:

  1. void IC_Init(void)
  2. {
  3. // 使能TIM3定时器时钟
  4. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  5. // 使能GPIOA端口时钟
  6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  7. // 配置GPIOA的GPIO_Pin_6引脚为上拉输入模式
  8. GPIO_InitTypeDef GPIO_InitStructure;
  9. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  10. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  11. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  12. GPIO_Init(GPIOA, &GPIO_InitStructure);
  13. // 配置TIM3定时器为内部时钟模式
  14. TIM_InternalClockConfig(TIM3);
  15. // 配置TIM3定时器的基本参数
  16. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  17. TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  18. TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  19. TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //计数器的溢出周期
  20. TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //设置计数器的时钟频率 1000000
  21. TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
  22. TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
  23. // 配置TIM3定时器的输入捕获参数
  24. TIM_ICInitTypeDef TIM_ICInitStructure;
  25. TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; // 配置通道1
  26. TIM_ICInitStructure.TIM_ICFilter = 0xF; // 配置输入滤波器
  27. TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //配置输入极性为上升沿触发
  28. TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; // 设置输入分频系数为不分频
  29. TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; // 配置输入源为直接映射到TI1
  30. TIM_ICInit(TIM3, &TIM_ICInitStructure);
  31. TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);//配置TI1FP2,自动根据TIM_ICInitStructure配置为与TI1FP1相反,即下降沿触发计数,交叉映射到TI1FP2.
  32. // 选择TIM3从模式输入触发源为TI1FP1,即TI1FP1每次上升沿触发从模式
  33. TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
  34. // 选择TIM3定时器的从模式为自动清零(TI1PF1的上升沿清零CNT)
  35. TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
  36. // 启动TIM3定时器
  37. TIM_Cmd(TIM3, ENABLE);
  38. }

 6.读取频率,占空比

  1. uint32_t IC_GetFreq(void)
  2. {
  3. return 1000000 / (TIM_GetCapture1(TIM3));
  4. }
  5. uint32_t IC_Getduty(void)
  6. {
  7. return TIM_GetCapture2(TIM3)*100/TIM_GetCapture1(TIM3);
  8. }

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号