STM32定时器(TIM1、TIM2、TIM3、TIM4、TIM5、TIM8)⾼级
定时器+。。。
2.1 时钟来源
计数器时钟可以由下列时钟源提供:
·内部时钟(CK_INT)
·外部时钟模式1:外部输⼊脚(TIx)
·外部时钟模式2:外部触发输⼊(ETR)
·内部触发输⼊(ITRx):使⽤⼀个定时器作为另⼀个定时器的预分频器,如可以配置⼀个定时器Timer1⽽作为另⼀个定时器Timer2的预分频器。
由于今天的学习是最基本的定时功能,所以采⽤内部时钟。TIM2-TIM5的时钟不是直接来⾃于APB1,⽽是来⾃于输⼊为APB1的⼀个倍频器。这个倍频器的作⽤是:当APB1的预分频系数为1时,这个倍频器不起作⽤,定时器的时钟频率等于APB1的频率(36MHZ);
当APB1的预分频系数为其他数值时(即预分频系数为2、4、8或16),这个倍频器起作⽤,定时器的时钟频率等于APB1的频率的2倍。{
假如APB1预分频为2(变成36MHZ),则定时器TIM2-5的时钟倍频器起作⽤,将变成2倍的APB1(2x36MHZ)将为72MHZ给定时器提供时钟脉冲。⼀般APB1和APB2的RCC时钟配置放在初始化函数中例如下⾯的void RCC_Configuration(void)配置函数所⽰,将APB1进⾏2分频,导致TIM2时钟变为72MHZ输⼊。
如果是1分频则会是36MHZ输⼊,如果4分频:CKINT=72MHZ/4x2=36MHZ; 8分频:CKINT=72MHZ/8x2=18MHZ;16分频:
CKINT=72MHZ/16x2=9MHZ
}
//系统时钟初始化配置
void RCC_Configuration(void)
{
//定义错误状态变量
ErrorStatus HSEStartUpStatus;
//将RCC寄存器重新设置为默认值
RCC_DeInit();
//打开外部⾼速时钟晶振
RCC_HSEConfig(RCC_HSE_ON);
//等待外部⾼速时钟晶振⼯作
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if(HSEStartUpStatus == SUCCESS)
{
//设置AHB时钟(HCLK)为系统时钟
RCC_HCLKConfig(RCC_SYSCLK_Div1);
//设置⾼速AHB时钟(APB2)为HCLK时钟
RCC_PCLK2Config(RCC_HCLK_Div1);
//设置低速AHB时钟(APB1)为HCLK的2分频(TIM2-TIM5输⼊TIMxCLK频率将为72MHZ/2x2=72MHZ输⼊)
RCC_PCLK1Config(RCC_HCLK_Div2);
//设置FLASH代码延时
FLASH_SetLatency(FLASH_Latency_2);
//使能预取指缓存
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
//设置PLL时钟,为HSE的9倍频 8MHz * 9 = 72MHz
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
//使能PLL
RCC_PLLCmd(ENABLE);
//等待PLL准备就绪
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
//设置PLL为系统时钟源
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
散粉和粉饼
//判断PLL是否是系统时钟
while(RCC_GetSYSCLKSource() != 0x08);
}
//允许TIM2的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
/
/允许GPIO的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
}
三、定时器代码实例
中断优先级就不贴出来了,⾃⼰可以配置下
Tout= ((arr+1)*(psc+1))/Tclk;
过失的近义词
arr:计数重装值,psc分频数,Tclk系统时钟频率,Tout⼀个周期的时间。
Tout= ((arr+1)*(psc+1))/Tclk;
3.1、定时器1使⽤
这⾥假设APB2时钟是1分频即72MHZ(如果是4分频则为36MHZ [=72MHZ/4x2=36MHZ] )配置,void RCC_Configuration(void)中配置如下代码:
1//设置⾼速AHB时钟(APB2)为HCLK时钟
2 RCC_PCLK2Config(RCC_HCLK_Div1);
则这⾥:APB2的时钟为1分频故出来的APB2时钟还是72MHZ,TIM1对系统时钟APB2(72MHZ)再进⾏7200分频,然后计数重载初值设置为100,则⼀个定时周期Tout=(100-1+1)*(7200-1+1)/72,000,000=1/10=0.1s,即100ms为⼀个计数周期
1//放到主函数的初始化中初始化
2void Timer1CountInitial(void)
3 {
4//定时=36000/72000x2=0.001s=1ms;
5 TIM_TimeBaInitTypeDef TIM_TimeBaStructure;
6///////////////////////////////////////////////////////////////
7 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
8
9 TIM_TimeBaStructure.TIM_Period = 100-1;//⾃动重装值(此时改为100ms)
10 TIM_TimeBaStructure.TIM_Prescaler = 7200-1;//时钟预分频
11// TIM_TimeBaStructure.TIM_Prescaler = 36000-1;//时钟预分频
12 TIM_TimeBaStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
13// TIM_TimeBaStructure.TIM_Period = 2-1;//⾃动重装值
14// TIM_TimeBaStructure.TIM_Period = 10-1;//⾃动重装值(此时改为10ms)
15 TIM_TimeBaStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频1
16 TIM_TimeBaStructure.TIM_RepetitionCounter = 0;
17 TIM_TimeBaInit(TIM1,&TIM_TimeBaStructure);
18
19 TIM_ClearFlag(TIM1,TIM_FLAG_Update);
20 TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);
21 TIM_Cmd(TIM1, ENABLE);
22 }
23
24
25void TIM1_UP_IRQHandler(void)
26 {
27//TIM_TimeBaStructure.TIM_Period = 100-1;//⾃动重装值(此时进中断的周期为100ms)
28if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
29 {
30//添加⾏程开关去抖程序
31if(XingChengTickNum_QuFantan<1000)//
32 {
33 XingChengTickNum_QuFantan++;
34 } 54}
55 TIM_ClearITPendingBit(TIM1,TIM_IT_Update);58 }
3.2、定时器2使⽤
Tout= ((arr+1)*(psc+1))/Tclk;
arr:计数重装值,psc分频数,Tclk系统时钟频率,Tout⼀个周期的时间。
假设APB1时钟是2分频即72MHZ(如果是1分频则为36MHZ)配置,void RCC_Configuration(void)中配置如下代码:
//设置低速AHB时钟(APB1)为HCLK的2分频(TIM2-TIM5输⼊TIMxCLK频率将为72MHZ/2x2=72MHZ输⼊)
RCC_PCLK1Config(RCC_HCLK_Div2);
这⾥:APB1的时钟为分频故出来的APB2时钟还是72MHZ,TIM1是对系统时钟APB2(72MHZ)进⾏7200分频,
则:Tout=(4-1+1)*(36000-1+1)/72,000,000=4/2,000=2ms
void TIM2_Int_Init(void)
{
TIM_TimeBaInitTypeDef TIM_TimeBaStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_DeInit(TIM2);
TIM_TimeBaStructure.TIM_Period = 4 - 1;//2000 - 1;
TIM_TimeBaStructure.TIM_Prescaler = (36000 - 1);健脾养胃的药
TIM_TimeBaStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaInit(TIM2, &TIM_TimeBaStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM2, ENABLE);
}
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
interrupt_rtc();//可以使你⾃⼰定义的执⾏函数
}
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update);
}
3.3、定时器3使⽤
假设APB1时钟是2分频即72MHZ(如果是1分频则为36MHZ)配置,void RCC_Configuration(void)中配置如下代码:
1//设置低速AHB时钟(APB1)为HCLK的2分频(TIM2-TIM5输⼊TIMxCLK频率将为72MHZ/2x2=72MHZ输⼊)
2 RCC_PCLK1Config(RCC_HCLK_Div2);
TIM3_Int_Init(4-1,36000-1);
网店推广方法
则:Tout=(4-1+1)*(36000-1+1)/72,000,000=4/2,000=2ms
//通⽤定时器3中断初始化
//这⾥时钟选择为APB1的2倍,⽽APB1为36M
//arr:⾃动重装值。
//psc:时钟预分频数
//这⾥使⽤的是定时器3!
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaInitTypeDef TIM_TimeBaStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
TIM_TimeBaStructure.TIM_Period = arr; //设置在下⼀个更新事件装⼊活动的⾃动重装载寄存器周期的值计数到5000为500ms
TIM_TimeBaStructure.TIM_Prescaler =psc; //设置⽤来作为TIMx时钟频率除数的预分频值 10Khz的计数频率
TIM_TimeBaStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaInit(TIM3, &TIM_TimeBaStructure); //根据TIM_TimeBaInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIMx外设
}
//定时器3中断服务程序
void TIM3_IRQHandler(void) //TIM3中断
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发⽣与否:TIM 中断源
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源
LED1=!LED1;
}
}
3.4、定时器4使⽤
假设APB1时钟是4分频即72/4=18MHZ(如果是4分频则TIMxCLK=18MHZx2=36MHZ)配置,void RCC_Configuration(void)中配置如下代码:
1//在void RCC_Configuration(void)中配置APB1时钟4分频或1分频都变为36MHZ
2//设置低速AHB时钟(APB1)为HCLK的4分频(TIM2-TIM5输⼊TIMxCLK频率将为72MHZ/4x2=36MHZ输⼊)
3 RCC_PCLK1Config(RCC_HCLK_Div4);//加⼊使⽤4分频
TIM4_Int_Init(4-1,36000-1);
则:Tout=(4-1+1)*(36000-1+1)/36,000,000=4/1,000=4ms
void TIM4_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaInitTypeDef TIM_TimeBaStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //时钟使能
//定时器TIM4初始化
颁奖曲
TIM_TimeBaStructure.TIM_Period = arr; //设置在下⼀个更新事件装⼊活动的⾃动重装载寄存器周期的值
立春吃什么食物养生
TIM_TimeBaStructure.TIM_Prescaler =psc; //设置⽤来作为TIMx时钟频率除数的预分频值
TIM_TimeBaStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaInit(TIM4, &TIM_TimeBaStructure); //根据指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM4中断,允许更新中断
//中断优先级NVIC设置
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //TIM3中断
春娇与志明台词
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM4, ENABLE); //使能TIMx
}
做错事检讨书
//定时器4中断服务程序
void TIM4_IRQHandler(void) //TIM3中断
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) //检查TIM4更新中断发⽣与否
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update ); //清除TIMx更新中断标志
LED0=!LED0;
// Get_Angle();
}
}
3.5、定时器5使⽤
假设APB1时钟是1分频即36MHZ(如果是1分频则TimexCLK=36MHZx1=36MHZ)配置,void RCC_Configuration(void)中配置如下代码:1//在void RCC_Configuration(void)中配置APB1时钟4分频或1分频都变为36MHZ
2//设置低速AHB时钟(APB1)为HCLK的4分频(TIM2-TIM5输⼊TIMxCLK频率将为72MHZ/4x2=36MHZ输⼊)
3 RCC_PCLK1Config(RCC_HCLK_Div1);//假如使⽤1分频
TIM5_Int_Init(4-1,36000-1);
则:Tout=(4-1+1)*(36000-1+1)/36,000,000=4/1,000=4ms
void TIM5_Init(u16 arr,u16 psc)
{
TIM_TimeBaInitTypeDef TIM_TimeBaStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //时钟使能
TIM_TimeBaStructure.TIM_Period = arr; //设置在下⼀个更新事件装⼊活动的⾃动重装载寄存器周期的值计数到5000为500ms
TIM_TimeBaStructure.TIM_Prescaler =psc; //设置⽤来作为TIMx时钟频率除数的预分频值 10Khz的计数频率
TIM_TimeBaStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaInit(TIM5, &TIM_TimeBaStructure); //根据TIM_TimeBaInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
TIM_Cmd(TIM5, ENABLE); //使能TIMx外?
}
//定时器5中断服务程序
void TIM5_IRQHandler(void) //TIM3中断
{
if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET) //检查指定的TIM中断发⽣与否:TIM 中断源
{
TIM_ClearITPendingBit(TIM5, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源
LED1=!LED1;
}
}