打印
[STM32F1]

【转】基于stm32f103zet6的定时器的学习2(定时器上溢)

[复制链接]
504|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
风萧寒|  楼主 | 2016-11-12 23:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
使用普通定时器2来产生中断,计数方式:增计数!
一、编程配置部分
1、首先进行中断配置,定时器中断肯定要配置的,代码如下:

[cpp] view plain copy
print?


  • void TIM2_NVIC_Configuration(void)  
  • {  
  •     NVIC_InitTypeDef NVIC_InitStructure;   
  •       
  •     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);                                                      
  •     NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;     
  •     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
  •     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;   
  •     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
  •     NVIC_Init(&NVIC_InitStructure);  
  • }  

这部分就不详述了
2、定时器的配置才是重点

[csharp] view plain copy
print?


  • /*TIM_Period--1000   TIM_Prescaler--71 -->中断周期为1ms*/  
  • void TIM2_Configuration(void)  
  • {  
  •     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  
  •     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);  
  •     TIM_DeInit(TIM2);  
  •     TIM_TimeBaseStructure.TIM_Period=1000;              /* 自动重装载寄存器周期的值(计数值) */  
  •     /* 累计 TIM_Period个频率后产生一个更新或者中断 */  
  •     TIM_TimeBaseStructure.TIM_Prescaler= (72 - 1);          /* 时钟预分频数 72M/72 */  
  •     TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;       /* 采样分频 */  
  •     TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; <span style="white-space:pre">        </span>/* 向上计数模式 */  
  •     TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);  
  •     TIM_ClearFlag(TIM2, TIM_FLAG_Update);               /* 清除溢出中断标志 */  
  •     TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);  
  •     TIM_Cmd(TIM2, ENABLE);  <span style="white-space:pre">                  </span>/* 开启时钟 */                                 
  •     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , DISABLE);      /*先关闭等待使用*/      
  • }  

还是一样,找到这个结构体

[csharp] view plain copy
print?


  • TIM_TimeBaseInitTypeDef{  
  • uint16_t  TIM_ClockDivision   
  • uint16_t  TIM_CounterMode   
  • uint16_t  TIM_Period   
  • uint16_t  TIM_Prescaler   
  • uint8_t  TIM_RepetitionCounter   
  • }  

1、TIM_ClockDivision用来设置时钟分频的,它的取值可以是

#define
TIM_CKD_DIV1   ((uint16_t)0x0000)
#define
TIM_CKD_DIV2   ((uint16_t)0x0100)
#define
TIM_CKD_DIV4   ((uint16_t)0x0200)
2、TIM_CounterMode用于设置计数模式

#define
TIM_CounterMode_CenterAligned1   ((uint16_t)0x0020)
#define
TIM_CounterMode_CenterAligned2   ((uint16_t)0x0040)
#define
TIM_CounterMode_CenterAligned3   ((uint16_t)0x0060)
#define
TIM_CounterMode_Down   ((uint16_t)0x0010)
#define
TIM_CounterMode_Up   ((uint16_t)0x0000)
3、TIM_Period

Specifies the period value to be loaded into the active Auto-Reload Register at the next update event. This parameter must be a number between 0x0000 and 0xFFFF.
就是一个重装值而已!
4、TIM_Prescaler明显是一个时钟与分频系数
Specifies the prescaler value used to divide the TIM clock. This parameter can be a number between 0x0000 and 0xFFFF
设置范围比较广,这里有一个计算公式

Specifies the repetition counter value. Each time the RCR downcounter reaches zero, an update event is generated and counting restarts from the RCR value (N)
这是在PWM里面用到的,这里可以不作设置
6、配置中断,清除中断标志位

[csharp] view plain copy
print?


  • TIM_ClearFlag(TIM2, TIM_FLAG_Update);                   /* 清除溢出中断标志 */  
  • TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);  


至此整个TIM2就配置完毕!不难得出,最后出来的结果就是:
/*TIM_Period--1000   TIM_Prescaler--71 -->中断周期为1ms*/
沙发
风萧寒|  楼主 | 2016-11-12 23:27 | 只看该作者
7、还漏了一个初始化函数,就是将TIMx设置为默认值!

[csharp] view plain copy
print?


  • void TIM_DeInit(TIM_TypeDef* TIMx)  
  • {  
  •   /* Check the parameters */  
  •   assert_param(IS_TIM_ALL_PERIPH(TIMx));   
  •    
  •   switch (*(uint32_t*)&TIMx)  
  •   {  
  •     case TIM1_BASE:  
  •       RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, ENABLE);  
  •       RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, DISABLE);   
  •       break;   
  •         
  •     case TIM2_BASE:  
  •       RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, ENABLE);  
  •       RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, DISABLE);  
  •       break;  
  •    
  •     case TIM3_BASE:  
  •       RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, ENABLE);  
  •       RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, DISABLE);  
  •       break;  
  •    
  •     case TIM4_BASE:  
  •       RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, ENABLE);  
  •       RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, DISABLE);  
  •       break;  
  •         
  •     case TIM5_BASE:  
  •       RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, ENABLE);  
  •       RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, DISABLE);  
  •       break;  
  •         
  •     case TIM6_BASE:  
  •       RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM6, ENABLE);  
  •       RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM6, DISABLE);  
  •       break;  
  •         
  •     case TIM7_BASE:  
  •       RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM7, ENABLE);  
  •       RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM7, DISABLE);  
  •       break;  
  •         
  •     case TIM8_BASE:  
  •       RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM8, ENABLE);  
  •       RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM8, DISABLE);   
  •       break;   
  •         
  •     default:  
  •       break;  
  •   }  
  • }  


可以看到这里设置了各种定时器的默认值,我们只需要传入一个参数就能自动的找到相应的分支进行初始化,非常明朗!
二、毫无疑问,我们既然产生了中断,那么我们的中断函数怎么实现呢?在哪里实现呢?接着看我们在 it.c 文件中实现的中断函数!

[csharp] view plain copy
print?


  • void TIM2_IRQHandler(void)  
  • {  
  •     if ( TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET )   
  •     {     
  •         TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update);      
  •          time++;  
  •     }            
  • }  

看看中断里面做了什么,没关系找手册,可以看到这个

[csharp] view plain copy
print?


  • TIM_IT_Update: TIM update Interrupt source   
  • TIM_IT_CC1: TIM Capture Compare 1 Interrupt source   
  • TIM_IT_CC2: TIM Capture Compare 2 Interrupt source   
  • TIM_IT_CC3: TIM Capture Compare 3 Interrupt source   
  • TIM_IT_CC4: TIM Capture Compare 4 Interrupt source   
  • TIM_IT_COM: TIM Commutation Interrupt source   
  • TIM_IT_Trigger: TIM Trigger Interrupt source   
  • TIM_IT_Break: TIM Break Interrupt source   

这就是那个函数的传入参数了,各种中断方式,Checks whether the TIM interrupt has occurred or not.用于检测是否产生对应的中断,因为我们在设置中断的时候就是设置的TIM_IT_Update中断方式,也就是更新事件,重载初值吧,至少我是这样理解的。
中断里面还清除了中断标志位,方便下一次进入中断嘛,然后还有就是对全局变量time自加1,方便主函数里面的检测!
好的,最后贴上主函数的代码,问题应该不大了。

[csharp] view plain copy
print?


  • /*******由于没有做外设测试的程序是:按键PA0仅一个LED灯******/  
  • /*******由于没有做外设测试的程序是:串口采用的是PA9->(T<->T),PA9->(R<->R)*****/  
  • #include "stm32f10x.h"      
  • #include "LED.h"  
  • #include "SysTick.h"  
  • #include "Delay.h"  
  • #include "Usart.h"  
  • #include "stdio.h"  
  • #include "Timer3.h"  
  •   
  • volatile u32 time; // ms 计时变量  
  •   
  • int main(void)  
  • {  
  •     //初初始化GPIO  
  •     LED_GPIO_Config();  
  •     //初始化系统定时器  
  •     SysTick_Init();  
  •     USART1_Config();  
  •         /* TIM2 定时配置 */  
  •     TIM2_NVIC_Configuration();  
  •   TIM2_Configuration();  
  •       
  •     printf("\r\n ("__DATE__ " - " __TIME__ ") \r\n");  
  •     START_TIME;  
  •     while(1)  
  •   {  
  •     if ( time == 1000 )<span style="white-space:pre">               </span> /* 1s 时间到 */  
  •     {  
  • <span style="white-space:pre">  </span>time = 0;  
  •             <span style="white-space:pre">          </span>/* LED1 取反 */        
  • <span style="white-space:pre">  </span>GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)((1-GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_0))));   
  •     }         
  •   }  
  • }  

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

68

主题

134

帖子

3

粉丝