当前位置:   article > 正文

6.2 定时器定时中断&定时器外部时钟_tim_etrclockmode2config

tim_etrclockmode2config
  1. 定时器定时中断

1.1接线图

因为定时器和中断系统的电路都在STM32内部,定时中断是为我们程序设计提供服务的,芯片外部只需要插一个OLED显示数据。

1.2 设计思路

本设计采用模块化编程,在配置好的工程基础上在System文件夹中加上Timer.c、Timer.h两部分。

在Timer.c首先进行函数的初始化。

初始化定时器大致思路

1. 第⼀步,RCC开启时钟 ,定时器的基准时钟和整个外设的工作时钟就会同时打开。 2. 第⼆步,选择时基单元的时钟源 (内部时钟源) 3. 第三步,配置时基单元 4. 第四步,配置输出中断控制,允许更新中断输出到NVIC 5. 第五步,配置NVIC,在NVIC中打开定时器中断的通道,并分配⼀个优先级 6. 第六步,运⾏控制 7. 第七步,使能计数器,计数器使能后,计数器开始计数,当计数器更新时,触发中断

8. 第八部,定时器中断函数,中断函数每隔一段时间就能自动执行一次

1.3 知识储备--定时器常用库函数

  • 恢复缺省配置函数

void TIM_DeInit(TIM_TypeDef* TIMx);
  • 时基单元初始化函数

void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef*TIM_TimeBaseInitStruct);
  • 把结构体变量赋⼀个默认值函数

void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef*TIM_TimeBaseInitStruct);
  • 使能计数器函数 (对应运行控制)

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
  • 使能中断输出信号函数(中断输出控制)

void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);

时基单元时钟选择部分

  • 选择内部时钟函数

void TIM_InternalClockConfig(TIM_TypeDef* TIMx);
  • 选择ITRx其他定时器的时钟函数

void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
  • 选择TIx捕获通道的时钟函数

  1. void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
  2. uint16_t TIM_ICPolarity, uint16_t ICFilter);

TIMx--选择要配置的定时器

TIM_TIxExternalCLKSource--选择TIx具体的某个引脚

TIM_ICPolarity--输入极性

ICFilter--滤波器

  • 选择ETR通过外部时钟模式1输⼊的时钟函数

  1. void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
  2. uint16_t ExtTRGFilter);

参数2:预分频器 参数3:输⼊的极性 参数4:滤波器

  • 选择ETR通过外部时钟模式2输⼊的时钟函数

  1. void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
  2. uint16_t ExtTRGFilter);
  • 单独配置ETR引脚的预分频器、极性、滤波器这些参数的函数

  1. void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler,uint16_t TIM_ExtTRGPolarity,
  2. uint16_t ExtTRGFilter);
  • 单独写预分频值函数

void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler,uint16_t TIM_PSCReloadMode);

TIMx--选择要配置的定时器

Prescaler--要写入的预分频值

TIM_PSCReloadMode--写入模式,在更新事件⽣效,或者在写⼊后,⼿动产⽣⼀个更新事件,让这个值 立刻生效。

  • 改变计数器的计数模式函数

void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);
  • ⾃动重装器预装功能配置函数 TIM_ARRPreloadConfig设置为DISABLE 和ENABLE的问题,他的作⽤只是允许或禁⽌在定 时器⼯作时向ARR的缓冲器中写⼊新值,以便在更新事件发⽣时载⼊覆盖以前的值。

void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
  • 给计数器写⼊⼀个值函数

void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);
  • 给⾃动重装器写⼊⼀个值函数

void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);
  • 获取当前计数器的值函数

uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);
  • 获取当前预分频器的值函数

uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);

1.4 程序设计

Timer.h

  1. #ifndef __TIMER_H
  2. #define __TIMER_H
  3. void Timer_Init(void);
  4. #endif

Timer.c

  1. #include "stm32f10x.h" // Device header
  2. void Timer_Init(void)
  3. {
  4. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//开启TIM2时钟
  5. TIM_InternalClockConfig(TIM2);//使用内部时钟
  6. //配置时基单元
  7. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定义时基单元结构体
  8. TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//设置1分频,也就是不分频
  9. TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//设置向上计数
  10. TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;//ARR自动重装值(CK_PSC/(PSC+1)/(ARR+1))
  11. TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;//PSC预分频器的值,PSC不分频
  12. TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值,高级定时器特有
  13. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);//写入参数
  14. TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除更新标志位,避免刚初始化完就进中断。
  15. TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//中断输出
  16. //配置NVIC
  17. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组
  18. NVIC_InitTypeDef NVIC_InitStructure;//NVIC结构体
  19. NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//定时器通道
  20. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能
  21. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级
  22. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级
  23. NVIC_Init(&NVIC_InitStructure);//写⼊参数
  24. TIM_Cmd(TIM2, ENABLE);//开启定时器
  25. }
  26. //定时器2中断函数
  27. /*
  28. void TIM2_IRQHandler(void)
  29. {
  30. if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)//判断是否中断溢出
  31. {
  32. TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清除中断标志位
  33. }
  34. }
  35. */
  36. //将中断函数提到使用的地方

main.c

  1. #include "stm32f10x.h" // Device header
  2. #include "Delay.h"
  3. #include "OLED.h"
  4. #include "Timer.h"
  5. uint16_t Num;//定义16位全局变量Num
  6. int main(void)
  7. {
  8. OLED_Init();
  9. Timer_Init();//初始化定时器
  10. OLED_ShowString(1, 1, "Num:");
  11. while (1)
  12. {
  13. OLED_ShowNum(1, 5, Num, 5);
  14. }
  15. }
  16. //定时器2中断函数
  17. void TIM2_IRQHandler(void)
  18. {
  19. if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
  20. {
  21. Num ++;//每秒Num自动++
  22. TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  23. }
  24. }

2. 定时器外部时钟

1.1接线图

接一个对射式红外传感器,DO数字输出接到PA0引脚(TIM2的ETR引脚,在此引脚输入外部时钟)

1.2 设计思路

本设计采用模块化编程,在配置好的工程基础上在System文件夹中加上Timer.c、Timer.h两部分。

每次遮挡射式红外传感器CNT+1,加到9后,自动清零,同时申请中断,Num++

1.3程序设计

Timer.h

  1. #ifndef __TIMER_H
  2. #define __TIMER_H
  3. void Timer_Init(void);
  4. uint16_t Timer_GetCounter(void);
  5. #endif

Timer.c

  1. #include "stm32f10x.h" // Device header
  2. void Timer_Init(void)
  3. {
  4. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//开启TIM2时钟
  5. //配置GPIO
  6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIOA的时钟
  7. GPIO_InitTypeDef GPIO_InitStructure;//定义初始化结构体
  8. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
  9. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//开启引脚
  10. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设置响应速度
  11. GPIO_Init(GPIOA, &GPIO_InitStructure);//写入参数
  12. TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F);//使用外部时钟
  13. //配置时基单元
  14. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定义时基单元结构体
  15. TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//设置1分频,也就是不分频
  16. TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//设置向上计数
  17. TIM_TimeBaseInitStructure.TIM_Period = 10;//从0计到9
  18. TIM_TimeBaseInitStructure.TIM_Prescaler = 1;//PSC预分频器的值,PSC不分频
  19. TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值,高级定时器特有
  20. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);//写入参数
  21. TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除更新标志位
  22. TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//中断输出
  23. //配置NVIC
  24. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组
  25. NVIC_InitTypeDef NVIC_InitStructure;//NVIC结构体
  26. NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//定时器通道
  27. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能
  28. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级
  29. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//响应优先级
  30. NVIC_Init(&NVIC_InitStructure);//写⼊参数
  31. TIM_Cmd(TIM2, ENABLE);//开启定时器
  32. }
  33. //CNT计数器值
  34. uint16_t Timer_GetCounter(void)
  35. {
  36. return TIM_GetCounter(TIM2);
  37. }
  38. //定时器2中断函数
  39. /*
  40. void TIM2_IRQHandler(void)
  41. {
  42. if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)//判断是否中断溢出
  43. {
  44. TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清除中断标志位
  45. }
  46. }
  47. */
  48. //将中断函数提到使用的地方

main.c

  1. #include "stm32f10x.h" // Device header
  2. #include "Delay.h"
  3. #include "OLED.h"
  4. #include "Timer.h"
  5. uint16_t Num;
  6. int main(void)
  7. {
  8. OLED_Init();
  9. Timer_Init();
  10. OLED_ShowString(1, 1, "Num:");
  11. OLED_ShowString(2, 1, "CNT:");
  12. while (1)
  13. {
  14. OLED_ShowNum(1, 5, Num, 5);
  15. OLED_ShowNum(2, 5, Timer_GetCounter(), 5);
  16. }
  17. }
  18. void TIM2_IRQHandler(void)
  19. {
  20. if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
  21. {
  22. Num ++;
  23. TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  24. }
  25. }

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

闽ICP备14008679号