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 //放到主函数的初始化中初始化
2 void Timer1CountInitial(void)
3 {
4 //定时=36000/72000x2=0.001s=1ms;
5 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
6 ///////////////////////////////////////////////////////////////
7 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
8
9 TIM_TimeBaseStructure.TIM_Period = 100-1;//自动重装值(此时改为100ms)
10 TIM_TimeBaseStructure.TIM_Prescaler = 7200-1;//时钟预分频
11 // TIM_TimeBaseStructure.TIM_Prescaler = 36000-1;//时钟预分频
12 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
13 // TIM_TimeBaseStructure.TIM_Period = 2-1;//自动重装值
14 // TIM_TimeBaseStructure.TIM_Period = 10-1;//自动重装值(此时改为10ms)
15 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频1
16 TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
17 TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);
18
19 TIM_ClearFlag(TIM1,TIM_FLAG_Update);
20 TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);
21 TIM_Cmd(TIM1, ENABLE);
22 }
23
24
25 void TIM1_UP_IRQHandler(void)
26 {
27 //TIM_TimeBaseStructure.TIM_Period = 100-1;//自动重装值(此时进中断的周期为100ms)
28 if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
29 {
30 //添加行程开关去抖程序
31 if(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_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_DeInit(TIM2); TIM_TimeBaseStructure.TIM_Period = 4 - 1;//2000 - 1;
TIM_TimeBaseStructure.TIM_Prescaler = (36000 - 1);
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); 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_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能 TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化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_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //时钟使能
//定时器TIM4初始化
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化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_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //时钟使能 TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化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;
}
}
STM32定时器(TIM1、TIM2、TIM3、TIM4、TIM5、TIM8)高级定时器+普通定时器,配置使用的更多相关文章
- 高级定时器TIM1&TIM8
高级定时器 初识stm32高级定时器: (1)高级控制定时器(TIM1 和 TIM8)和通用定时器在基本 ...
- js定时器关闭,js定时器停止,一次关闭所有正在运行的定时器,自定义函数clearIntervals()一次关闭所有正在运行的定时器
js定时器关闭,一次关闭所有正在运行的定时器,自定义函数clearIntervals()一次关闭所有正在运行的定时器,原理:利用数组存储定时器id,然后遍历数组,关闭定时器 附上页面的截图,代码在截图 ...
- STM32高级定时器TIM1产生两路互补的PWM波(带死区)
测试环境:Keil 5.20.0.0 STM32F103RBT6 固件库版本:STM32F10x_StdPeriph_Lib_V3.5.0(2011) 本文使用TIM1的通道1,通道2,产生两路1kh ...
- STM32开发板的TIM3开启和关闭
关闭定时器中断要考虑好多情况 1)关闭定时器时,定时器是否在处在工作状态 2)关闭定时器时,定时器是否正好进入中断,造成关闭程序出现断层,进而无法实现完整关闭程序,此时可以使用高一级别的外部中断强制进 ...
- STM32输入捕获TIM2四通道
相比于一通道,原子的例程里因为清了计数时间,所以要对程序进行修改. 记录上升沿后的计数,然后记录下降沿的计数.相减后计算高电平时间,对于定时器中断间隔的边界要分开处理. 这里因为我的接收机时间是1ms ...
- CC2530红外学习球学码函数(P1.2接红外一体接收头,使用定时器tim1的复用功能2)
P1.2GPIO配置: void cap_gpio_init(){ P1SEL |= 0x04; P1DIR &= ~0x04; PERCFG |= 0x40; P2SEL |= 0x20; ...
- Java多线程与并发库高级应用-传统定时器技术回顾
传统定时器技术回顾(jdk1.5以前) public class TraditionalTimerTest { static int count = 0; public static void mai ...
- STM32学习笔记 —— 0.1 Keil5安装和DAP仿真下载器配置的相关问题与注意事项
Keil5安装的注意事项 安装细节在此不再做过多赘述,主要介绍一下注意事项: 安装路径中不能有中文. ARM的Keil的路径不能与51的Keil的有冲突,必须将目录分开. Keil5中不会自动添加芯片 ...
- STM32中TIMx的映射及其通道
TIMx,通道x,无映射,部分映射,完全映射 TIM1_CH1, PA8, PE9, TIM1_CH2, PA9, PE11 TIM1_CH3, PA10, PE1 ...
- 【STM32H7教程】第34章 STM32H7的定时器应用之TIM1-TIM17的PWM实现
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第34章 STM32H7的定时器应用之TIM1-T ...
随机推荐
- this.$refs 获取的值是undefined
以下是父组件内的代码截图 如果想取子组件内的方法,参数,等可以试以下两种方法 1.在mounted内使用this.$nextTick(()=>{ }) 2.直接再undated() {} 内 ...
- 小米手机MIUI安装APK时自动获取安装权限(自动点击权限框)
这篇主要是记录一下在完全没学过Android的情况下硬拗完的这个APK,拖了很久查了很多资料才勉强写完,比较垃圾但还是实现功能了.记录的过程我也尽量把知识点贴出来. 一开始是看了一个大佬的分享贴( ...
- Linux环境使用Docker安装MongoDb
系统环境: CentOS 7.6 64位(同样适用于Ubuntu) 安装步骤: 1.创建文件夹 /home/docker/mongo/config /home/docker/mongo/data 2. ...
- React 事件绑定this指向
1. 推荐:使用class的实例方法 class Hello extends React.Component { handleClick = () => { this.setState({ .. ...
- promethus+grafana监控
1.监控 MySQL (终端可以安装在任意主机,不一定按在mysql节点上,注:mysql版本需在5.5以上) I.首先在mysql中添加监控使用的用户: create user 'exp'@'%' ...
- Cadvisor+prometheus+grafana
部署Cadvisor [root@localhost ~]# docker run -d \ --volume=/:/rootfs:ro \ --volume=/var/run:/var/run:ro ...
- java面向对象九个经典例子程序
1 Hello world例子 1 package Example; //定义自己的包名 2 3 public class Example1 //定义一个类 4 { 5 public static v ...
- 全局 使用 stylus 变量
首先 安装 啦 npm i stylus stylus-loader -D 之后 使用全局变量 然后在组件中引用改变量 -->没有用! 原因还没有在build/utils.js文件 全局引入 ...
- python机器学习——随机森林算法
背景与原理: 首先我们需要知道集成学习的概念,所谓集成学习,就是使用一系列学习器进行学习,并且通过某种规则把这些学习器的学习结果整合起来从而获得比单个学习器学习效果更好的机器学习方法.这样的方法可以用 ...
- 4组-Beta冲刺-1/5
一.基本情况 队名:摸鲨鱼小队 组长博客:https://www.cnblogs.com/smallgrape/p/15590583.html github链接:https://github.com/ ...