定时器中断实验

来源:互联网 发布:嫌疑人影评知乎 编辑:程序博客网 时间:2024/05/22 14:01
STM32的定时器
TIME1和TIME8高级定时器
TIME2~TIME5通用定时器
TIME6 和TIME7 基本定时器。

STM32的通用 TIMx (TIM2、 TIM3、 TIM4 和 TIM5)定时器功能包括:1)16 位向上、向下、向上/向下自动装载计数器( TIMx_CNT)。2)16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为 1~65535 之间的任意数值。3) 4 个独立通道( TIMx_CH1~4),这些通道可以用来作为: 1、输入捕获2、输出比较3、PWM 生成(边缘或中间对齐模式)4、 单脉冲模式输出4)可使用外部信号( TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外一个定时器)的同步电路。5)如下事件发生时产生中断/DMA: 1、更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发) 2、触发事件(计数器启动、停止、初始化或者由内部/外部触发计数) 3、输入捕获 4、输出比较 5、支持针对定位的增量(正交)编码器和霍尔传感器电路 6、触发输入作为外部时钟或者按周期的电流管理
定时器中断实验步骤:
1) TIM3 时钟使能。
TIM3 是挂载在 APB1 之下,所以我们通过 APB1 总线下的使能使能函数来使能 TIM3。函数为:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
2) 初始化定时器参数: 设置自动重装值, 分频系数,计数方式等。函数为:
voidTIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
第一个参数是确定是哪个定时器。
第二个参数是定时器初始化参数结构体指针
typedef struct
{
uint16_t TIM_Prescaler; 设置分频系数
uint16_t TIM_CounterMode; 设置计数方式
uint16_t TIM_Period; 设置自动重载计数周期值
uint16_t TIM_ClockDivision; 设置时钟分频因子
uint8_t TIM_RepetitionCounter;
} TIM_TimeBaseInitTypeDef;
通用定时器只有前面四个参数有用,最后一个参数 TIM_RepetitionCounter 是高级定时器才有用的

3) 设置 TIM3_DIER 允许更新中断。
函数为:void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
第一个参数是选择定时器号,取值为 TIM1~TIM17。
第二个参数是使能的定时器中断的类型,如更新中断 TIM_IT_Update, 触发中断IM_IT_Trigger, 输入捕获中断等等。
第三个参数是失能还是使能。

4) TIM3 中断优先级设置。
要产生中断,必不可少的要设置 NVIC 相关寄存器,NVIC_Init 函数实现中断优先级的设置。

5) 允许 TIM3 工作,也就是使能 TIM3。
配置完定时器后,开启定时器,通过 TIM3_CR1 的 CEN 位来设置。函数为:
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
比如我们要使能定时器 3,方法为:TIM_Cmd(TIM3, ENABLE); //使能 TIMx 外设

6) 编写中断服务函数。
编写定时器中断服务函数,用来处理定时器产生的相关中断。中断产生后,通过状态寄存器的值来判断此次产生的中断属于什么类型。然后执行相关的操作,这里使用的是更新(溢出)中断,所以在状态寄存器 SR 的最低位。在处理完中断之后应该向 TIM3_SR 的最低位写 0,来清除该中断标志。
读取中断状态寄存器的值判断中断类型的函数是:
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t)
判断定时器 TIMx 的中断类型 TIM_IT 是否发生中断。比如,我们要判断定时器 3 是否发生更新(溢出)中断,方法为:if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){}

清除中断标志位的函数是:void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
作用是,清除定时器 TIMx 的中断 TIM_IT 标志位。
比如我们在TIM3 的溢出中断发生后,我们要清除中断标志位,方法是:
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );

通过TIM3 的中断来控制 DS1 的亮灭
代码部分:
time.c
  1. #include "timer.h"  
  2. #include "led.h"  
  3. //通用定时器 3 中断初始化  
  4. //这里时钟选择为 APB1 的 2 倍,而 APB1 为 36M  
  5. //arr:自动重装值。  
  6. //psc:时钟预分频数  
  7. //这里使用的是定时器 3!  
  8. void TIM3_Int_Init(u16 arr,u16 psc)  
  9. {  
  10.  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  
  11. NVIC_InitTypeDef NVIC_InitStructure;  
  12. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //①时钟 TIM3 使能  
  13. //定时器 TIM3 初始化  
  14. TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载寄存器周期的值  
  15. TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置时钟频率除数的预分频值  
  16. TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割  
  17. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数  
  18. TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);  //②初始化 TIM3  
  19. TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );  //③允许更新中断  
  20. //中断优先级 NVIC 设置  
  21. NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3 中断  
  22. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级 0 级  
  23. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级 3 级  
  24. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  //IRQ 通道被使能  
  25. NVIC_Init(&NVIC_InitStructure);   //④初始化 NVIC 寄存器  
  26. TIM_Cmd(TIM3, ENABLE);  //⑤使能 TIM3  
  27. }  
  28. //定时器 3 中断服务程序⑥  
  29. void TIM3_IRQHandler(void//TIM3 中断  
  30. {  
  31. if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查 TIM3 更新中断发生与否  
  32. {  
  33. TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除 TIM3 更新中断标志  
  34. LED1=!LED1;  
  35. }  
  36. }  

main.c
  1. int main(void)  
  2. {  
  3. delay_init();  //延时函数初始化   
  4. NVIC_Configuration(); //设置 NVIC 中断分组 2:2 位抢占优先级, 2 位响应优先级  
  5. 200  
  6. uart_init(9600);  //串口初始化波特率为 9600  
  7. LED_Init();  //LED 端口初始化  
  8. TIM3_Int_Init(4999,7199); //10Khz 的计数频率,计数到 5000 为 500ms  
  9.  while(1)  
  10. {  
  11. LED0=!LED0;  
  12. delay_ms(200);   
  13. }  
  14. }  
原创粉丝点击