1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > STM32基于固件库学习笔记(4)(通用定时器)TIM3定时1S中断

STM32基于固件库学习笔记(4)(通用定时器)TIM3定时1S中断

时间:2019-09-01 09:48:49

相关推荐

STM32基于固件库学习笔记(4)(通用定时器)TIM3定时1S中断

STM32F103ZE系列定时器资源

有 TIME1 和 TIME8 等高级定时器,也有 TIME2~TIME5 等通用定时器,还有 TIME6 和TIME7 等基本定时器。

通用定时器:是一个通过可编程预分频器(PSC)驱动的 16 位自动装载计数器(CNT)构成;可以用来测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等功能。STM3 的通用 TIMx (TIM2、TIM3、TIM4 和 TIM5)定时器功能包括:

1)16 位向上、向下、向上/向下自动装载计数器(TIMx_CNT)。

2)16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为 1~65535 之间的任意数值。

3)4 个独立通道(TIMx_CH1~4),这些通道可以用来作为:

A.输入捕获

B.输出比较

C.PWM 生成(边缘或中间对齐模式)

D.单脉冲模式输出

4)可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外一个定时器)的同步电路。

5)如下事件发生时产生中断/DMA:

A.更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)

B.触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)

C.输入捕获

D.输出比较

E.支持针对定位的增量(正交)编码器和霍尔传感器电路

F.触发输入作为外部时钟或者按周期的电流管理定时器的时钟来源有 4 个:

1)内部时钟(CK_INT)

2)外部时钟模式 1:外部输入脚(TIx)

3)外部时钟模式 2:外部触发输入(ETR)

4)内部触发输入(ITRx):使用 A 定时器作为 B 定时器的预分频器(A 为 B 提供时钟)

使用定时器的一般步骤

注:

因为本次是使用TIM3,所以所有代码都是配置TIM3;

本次使用到的库函数有:"stm32f10x_rcc.h"和"stm32f10x_rcc.c"时钟库

"stm32f10x_tim.h"和"stm32f10x_tim.c"定时器库

"misc.h"和"miscc"中断库

1)TIM3时钟使能

TIM3 是挂载在 APB1 之下

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

2)复位TIM3

很多时候都没写这一步,不过建议还是写上。

TIM_DeInit(TIM6);//复位

3)初始化定时器参数 数, 设置 自动重装值 , 分频系数 ,计数方式

主要通过使用定时器库函数中,定时器初始化函数

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;

定时器定时时间计算公式

T ( 一 次 中 断 的 时 间 ) = ( 设 置 的 初 值 T I M P e r i o d + 1 ) ∗ ( 设 置 的 分 频 系 数 T I M P r e s c a l e r + 1 ) 时 钟 频 率 T(一次中断的时间)=\frac {(设置的初值TIM_Period+1)*(设置的分频系数TIM_Prescaler+1)}{时钟频率} T(一次中断的时间)=时钟频率(设置的初值TIMP​eriod+1)∗(设置的分频系数TIMP​rescaler+1)​

时钟频率根据TIM_ClockDivision的值来计算,在APB1时钟线上初始为72MHZ

4)设置 TIM3_DIER 允许更新中断

void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);//第一个参数是定位到某个定时器上、第三个就是失能还是使能ENABLE或NABLE/*第二个用来指明我们使能的定时器中断的类型,定时器中断的类型有很多种,包括更新中断 TIM_IT_Update,触发中断 TIM_IT_Trigger,以及输入捕获中断等。*/

5)居然使用中断,就得初始化线上中断,设置触发条件等。

//系统初始化就为2组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置 NVIC 中断分组 2: 2 位抢占优先级, 2 位响应优先级//中断优先级 NVIC 设置NVIC_InitTypeDef NVIC_ITDef_TIM6;NVIC_ITDef_TIM6.NVIC_IRQChannel = TIM6_IRQn; //TIM6 中断NVIC_ITDef_TIM6.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级 0 级NVIC_ITDef_TIM6.NVIC_IRQChannelSubPriority = 3; //从优先级 3 级NVIC_ITDef_TIM6.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能NVIC_Init(&NVIC_ITDef_TIM6); //初始化 NVIC 寄存器

6)许允许TIM3工作能 ,也就是使能TIM3 。

也就相当于开定时器。

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);//第一个参数是定位到某个定时器上、第二个就是失能还是使能ENABLE或NABLE

7 )编写中断服务函数。

先看看获取中断标志位函数

//先判断这种中断是否使能,再判断标志位ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t);//直接判断标志位FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);//主要有这几个中断标志位#define TIM_IT_Update/*TIM中断源*/ #define TIM_IT_CC1/*TIM捕获/比较1中断源*/#define TIM_IT_CC2/*TIM捕获/比较2中断源*/#define TIM_IT_CC3/*TIM捕获/比较3中断源*/#define TIM_IT_CC4/*TIM捕获/比较4中断源*/#define TIM_IT_Trigger/*TIM触发中断源*/ //判断定时器溢出中断方法:if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){}

清楚标志位函数

void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);

注:使用的TIM_GetITStatus()函数判断标志位,就用TIM_ClearITPendingBit()函数清标志位。

定时器中断函数格式

//定时器 3 中断服务程序//TIM3_IRQHandler在“USART1_IRQHandler”固件库给好了的名字void TIM3_IRQHandler(void) //TIM3 中断{if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查 TIM3 更新中断发生与否{TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除 TIM3 更新中断标志 }}

完整程序

/*主要实现LED间隔1s闪烁,其时间用定时器定时中断完成*/#include "stm32f10x.h" // Device header//初始化LED灯 -> PB5推挽输出、高电平void LED_Init_PB5(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_ITDef_PB5;GPIO_ITDef_PB5.GPIO_Pin = GPIO_Pin_5;GPIO_ITDef_PB5.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出 GPIO_ITDef_PB5.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOB,&GPIO_ITDef_PB5);GPIO_SetBits(GPIOB,GPIO_Pin_5);// 置为高电平}void TIM6_Init(void){RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//挂载tim6时钟TIM_DeInit(TIM6);//复位 TIM_TimeBaseInitTypeDef TIM_TITDef_TIM6;TIM_TITDef_TIM6.TIM_Prescaler = 7199;//72MHzTIM_TITDef_TIM6.TIM_Period = 9999;// 1STIM_TITDef_TIM6.TIM_CounterMode = TIM_CounterMode_Up;//向上计数TIM_TITDef_TIM6.TIM_ClockDivision = TIM_CKD_DIV1;//自动重载计数周期值TIM_TimeBaseInit(TIM6,&TIM_TITDef_TIM6);TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);//更新中断NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置 NVIC 中断分组 2:2 位抢占优先级,2 位响应优先级//中断优先级 NVIC 设置NVIC_InitTypeDef NVIC_ITDef_TIM6;NVIC_ITDef_TIM6.NVIC_IRQChannel = TIM6_IRQn; //TIM6 中断NVIC_ITDef_TIM6.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级 0 级NVIC_ITDef_TIM6.NVIC_IRQChannelSubPriority = 3; //从优先级 3 级NVIC_ITDef_TIM6.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能NVIC_Init(&NVIC_ITDef_TIM6); //初始化 NVIC 寄存器TIM_Cmd(TIM6,ENABLE);//使能 TIM6}void TIM6_IRQHandler(void) //TIM6 中断{if (TIM_GetITStatus(TIM6,TIM_IT_Update) != RESET) //检查 TIM6 更新中断发生与否{if(GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_5))//读取PB5当前状态{GPIO_ResetBits(GPIOB,GPIO_Pin_5);// 置0}else {GPIO_SetBits(GPIOB,GPIO_Pin_5);// 置1}TIM_ClearITPendingBit(TIM6,TIM_IT_Update ); //清除 TIM6 更新中断标志}}int main(void){LED_Init_PB5();TIM6_Init();//1swhile(1){; }}

STM32F10x_StdPeriph_Lib_V3.5.0(官方固件库)

链接:STM32固件库使用手册的中文翻译版 提取码:4lkx

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。