STM32定时器篇——通用定时器的使用(定时中断,PWM输出)

news2024/11/19 9:56:12

一、通用定时器的类型以及应用功能:

        通用定时器有:TIM2、TIM3、TIM4、TIM5,其总线挂载于APB1上,且有基本定时器的所有功能(定时中断、主模式触发ADC),并额外具有内外时钟源选择,输入捕获、输出比较、编码器接口、主从触发模式等功能。

二、通用定时器时钟介绍

             

         从上图可以看见,总线APB1(最大只能到36MHz)给通用定时器提供时钟,但不代表通用定时器的时钟频率为36MHz,因为通用定时器不直接由APB1提供,而是会先经过一个倍频器。

        见上图APB1预分频系数为1则倍频系数为1,则频率不变,否则频率乘二。而对APB1的预分频在启动文件就已经配置好了(system_stm32f10x.c中的SystemInit()函数),分频系数为2,故定时器时钟为72MHz。

1.外部时钟:

1.1:时钟来源

         主要作用:给时基单元提供一个CK_PSC的时钟。从上图可知,其时钟可以来自:

        1:内部(APB1)

        2:也可以来自外部时钟源(外部带ETR的引脚)

        3:也可以来自其他定时器即定时器的级联(ITR0、1、2、3)。 

        4:来自定时器的外部通道引脚(TI1FP1),通过选择器到达控制器。使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时 器Timer1而作为另一个定时器Timer2的预分频器

 1.2:计数器模式:

        通用定时器可以向上计数、向下计数、向上向下双向计数模式。

        向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并产生一个计数器溢出事件。

        向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后重新从自动装入的值开始计数并产生一个计数器溢出事件(与向上计数模式相反)。

        中央对齐模式:计数器从0计数到自动加载的值(TIMx_ARR)-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出的事件;然后再从0开始重新计数。

 2.时基单元

 时基单元包含:

          ● 计数器寄存器(TIMx_CNT)

          ● 预分频器寄存器 (TIMx_PSC)

          ● 自动装载寄存器 (TIMx_ARR)

         PSC预分频器对CK_PSC时钟进行分频产生CK_CNT这个时钟作为计数器的最终时钟。每来一个时钟计数器加1,当计数器达到溢出条件(等于自动装载寄存器的值),产生更新事件。

3.输入捕获:

         引脚输入信号经过输入滤波器和边缘检测器再经过预分频器(即几个上升沿检测一次),每次捕获后都有捕获信号产生,产生捕获事件(也可以产生捕获中断),然后将计数器的值转移到捕获/比较寄存器里面得到计数值(也就是可以得到时间),故可用于测量脉冲时间,即PWM的频率、占空比、脉冲间隔、电平持续时间等等。

 4.输出比较OC(Output Compare):

         首先在比较寄存器里面写入比较值,当计数器的值等于比较值时(不是直接和比较寄存器的值比较,是和其影子寄存器的值比较),即当计数器CNT大于比较寄存器CCR、小于CCR或者等于CCR时其输出会相应置0或者置1,其主要用于输出一定频率和占空比的PWM波形。 

三、定时器时间的计算

定时频率的计算:       

定时时间计算公式:Tout = ((arr+1)(psc + 1))/Tclk

比如定时1ms可以配置为:

        ARR:1000-1        PSC:72-1        或      ARR:100-1        PSC:720-1  等多种配法。

                计数器计数频率:CK_CNT = CK_PSC/(PSC+1)。时钟经过了PSC分频,除上分频系数得到计数器的频率,可以从图中看出来,时钟是先通过预分频再给到计数器的。则计数时间为:(PSC+1)/CK_PSC(时间为频率倒数),溢出时间等于计数器的时间乘上自动从装载值,因为自动重装载值决定计多少个数。即:Tout = ((arr+1)(psc + 1))/Tclk

        计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1)

                                                            = CK_PSC / (PSC + 1) / (ARR + 1);

 有了时间计算公式,则频率计算公式就可以得处来了,无非是倒数而已。

 四、通用定时器的使用

 1.定时器定时中断:

        步骤:(这里以TIM2为例子)

1.开启时钟:RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);

2.选择内部时钟(也可以不写,默认为内部时钟);TIM_InternalClockConfig(TIM2);

3. 配置时基单元:TIM_TimeBaseInit();

        主要有预分频的配置(TIM_ClockDivision)、计数器模式的配置(TIM_CounterMode)、ARR自动重装载器的值(TIM_Period)、PSC预分频的值(TIM_Prescaler)、重复计数器的值(TIM_RepetitionCounter为高级定时器才有的)。

4.开启中断以及配置NVIC:

        TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);

NVIC的配置:

配置优先级分组:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

再配置其中断通道、通道使能、抢占优先级以及相应优先级。 

5.使能定时器:TIM_Cmd(TIM2,ENABLE);

6.定时中断函数:

        首先得获取中断标志位:TIM_GetITStatus(TIM2,TIM_IT_Update),再写相应要处理的事情,最后别忘了清除中断标志TIM_ClearITPendingBit(TIM2,TIM_IT_Update)。为什么要在中断函数里面判断中断标志位呢?由于定时器中断有很多种,所以我们要判断是不是需要的那种中断。而关于清除中断是如果不清除中断会无限进入中断函数,所以需要清除中断。

void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period = 1000 - 1;
	TIM_TimeBaseInitStruct.TIM_Prescaler = 720 - 1;
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
	
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitSturcture;
	
	NVIC_InitSturcture.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitSturcture.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitSturcture.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitSturcture.NVIC_IRQChannelSubPriority = 0;
	NVIC_Init(&NVIC_InitSturcture);
	
	TIM_Cmd(TIM2,ENABLE);
}

void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		//中间为待处理的函数
	}
	TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}

2.定时器的PWM(Pulse Width Modulation脉冲宽度调制)输出

2.1 PWM的介绍

         PWM应用于在具有惯性的系统中,可以通过一系列脉冲的宽度进行调制来等效地获得所需要的模拟参量。这里介绍一下最后两种输出比较模式——PWM模式1和PWM模式2;

PWM模式1

向上计数:CNT<CCR时,REF置有效电平;CNT>=CCR时,REF置无效电平

向下计数:CNT>CCR时,REF置有效电平;CNT<=CCR时,REF置无效电平

PWM模式2

向上计数:CNT<CCR时,REF置无效电平;CNT>=CCR时,REF置有效电平

向下计数:CNT>CCR时,REF置无效电平;CNT<=CCR时,REF置有效电平

可以发现,向下计数和向上计数是相反的,而PWM模式1和PWM模式2是相反的!

下面介绍一下PWM的参数:

        PWM的频率:等于计数器的更新频率,没啥好解释的。

        PWM的占空比(高电平占整个周期的比例):Duty = CCR / (ARR + 1);当然,公式也不全是这样,和你的PWM模式配置有关。

        PWM的分辨率(PWM最小能设定到的高电平时间所占周期的比例):意思就是把一个周期的时间分成了多少份。假如PWM的频率为1000Hz,若最小能给到的时钟为60KHz,则分辨率为:(1/60k)/(1/1000) =  1.667%。同一系统中,由于时钟不变,提高频率,则周期变小,分辨率会变大。计算公式:Reso = 1/(ARR + 1);注:分辨率越小越好,分辨率越小,占空比变化越细腻,从公式中可以看出ARR越大越好。

 2.1 PWM的配置

 其步骤和前面定时中断相同,只是不配置中断并加上初始化输出比较单元。步骤有开启时钟,初始化时基单元,初始化输出比较单元。

这里介绍一下比较单元的初始化:TIM_OC1Init(TIM4,&TIM_OCInitStruct);用哪个通道就初始化哪个通道。配置内容有:输出比较模式(TIM_OCMode)、输出比较极性(TIM_OCPolarity)、输出状态(TIM_OutputState)、CCR值的设定(TIM_Pulse),最后使能定时器;

那么如何设置CCR的值呢?用到此函数:TIM_SetCompare1(TIM4,500);

void Motor_Init(void)
{
    /***** GPIO初始化 *****/
    GPIO_InitTypeDef  GPIO_InitStructure;
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 //使能B端口时钟
    
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;	 
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 		 //推挽复用输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
 	GPIO_Init(GPIOB, &GPIO_InitStructure);	  //初始化GPIOB
    /***** 初始化TIM *****/
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//不分频
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStruct.TIM_Period = 20000 - 1;//ARR
    TIM_TimeBaseInitStruct.TIM_Prescaler = 72 -1;//PSC
    TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//为高频计数器的,不需要
    
    TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStruct);
    /***** 初始化输出比较单元 *****/
    TIM_OCInitTypeDef TIM_OCInitStruct;
    
    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStruct.TIM_Pulse = 15000;
    
    TIM_OC1Init(TIM4,&TIM_OCInitStruct);
    TIM_OC2Init(TIM4,&TIM_OCInitStruct);
    TIM_OC3Init(TIM4,&TIM_OCInitStruct);
    TIM_OC4Init(TIM4,&TIM_OCInitStruct);
    /***** 启动定时器 *****/
    TIM_Cmd(TIM4,ENABLE);
}

当然,上面的GPIO根据你使用的IO口来确定,这里列举了TIM4的输出比较功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1863675.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学习笔记——动态路由——RIP(Rip 基本配置)

五、Rip 基本配置 主类网络(有类&#xff0c;major-net)&#xff1a; 使用自然掩码的网段 例如&#xff1a; 12.1.1.0/24--->12.0.0.0 192.168.1.0/24--->192.168.1.0 172.16.1.0/24--->172.16.0.0 基本配置&#xff1a; 济南总局&#xff1a; IP:192.168.1.1 /…

如何提高pcdn技术的传输效率?

提高PCDN技术的传输效率是一个复杂且多层面的任务&#xff0c;涉及多个关键策略和方法的结合。以下是一些具体的建议和措施&#xff0c;有助于提升PCDN技术的传输效率&#xff1a; 一&#xff0e;优化缓存策略&#xff1a; 精准定位热点内容&#xff0c;优先将这部分内容缓存…

Python-批量日期数据格式化处理

背景 用于批量格式化数据&#xff0c;背景就是领导给我我一张下面这样的表格&#xff0c;其中启用日期是五花八门的格式&#xff0c;大概有几万行&#xff0c;需要把启用日期一列统一格式化为“YYYY-MM-DD”的格式&#xff0c;显然&#xff0c;针对这种格式不统一的数据&#…

GPT-4搞不定的图推理,港科大7B模型搞定

大模型执行图推理任务&#xff0c;我们是希望大模型仅仅给出结果&#xff0c;还是在给出准确答案的同时&#xff0c;输出详细的推理过程&#xff1f; 先来看GPT-4的表现&#xff1a; 给出了一个非常简短且错误的答案&#xff08;判断该图中没有环&#xff09;&#xff0c;这可…

【扩散模型(二)】IP-Adapter 从条件分支的视角,快速理解相关的可控生成研究

系列文章目录 【扩散模型&#xff08;一&#xff09;】中介绍了 Stable Diffusion 可以被理解为重建分支&#xff08;reconstruction branch&#xff09;和条件分支&#xff08;condition branch&#xff09;本文将从该视角快速理解 IP-Adapter 以及相关可控生成研究。 文章目…

linux下OpenSSL升级到1.1以上版本

要将CentOS 7上的OpenSSL升级到1.1以上版本&#xff0c;您需要遵循以下步骤。请注意&#xff0c;这些步骤可能需要一些系统管理经验&#xff0c;因为您将从源代码编译和安装OpenSSL。 1. 更新系统软件包 首先&#xff0c;确保您的系统软件包是最新的。使用以下命令更新所有软…

智慧校园-毕业管理系统总体概述

在当今教育信息化的浪潮中&#xff0c;智慧校园毕业管理系统脱颖而出&#xff0c;它作为一项综合性的数字平台&#xff0c;全面覆盖了从毕业资格审查到学位授予的每一个关键步骤&#xff0c;旨在通过智能化手段&#xff0c;为高校的毕业管理工作带来革命性的变革。毕业管理系统…

下一代广域网技术2:SRv6

2.SRv6 SR架构设计之初&#xff0c;就为SR数据平面设计了两种实现方式&#xff1a;一种是SR-MPLS&#xff0c;其重用了MPLS数据平面&#xff0c;可以在现有IP/MPLS网络上增量部署&#xff1b;另一种是SRv6&#xff0c;使用IPv6数据平面&#xff0c;基于IPv6路由扩展头进行扩展…

第七届IAIC(成都)国际医美产业大会在蓉召开

四川省人民医院新丽美获“中国整形美容协会医疗救助与修复基金-成都市整形修复定点医院”“‘放心美 医无忧’全过程保障示范医院”两块授牌 2024年6月24日&#xff0c;第七届IAIC&#xff08;成都&#xff09;国际医美产业大会暨“医美之都”高峰会议省医院新丽美整形修复基地…

CesiumJS加载天地图数据后,可以实现什么效果?

说起地图&#xff0c;大家耳熟能详的百度地图、高德地图、腾讯地图等&#xff0c;由于授权的原因&#xff0c;使用起来心惊胆战的&#xff0c;而天地图就没有这方面的困扰&#xff0c;本文介绍下如何在cesium中时候用天地图数据&#xff0c;已经能够实现哪些交互效果。 一、关…

无限制数字(仅仅int类型)的大小的自然排序算法

直接上代码&#xff1a; #include <iostream> #include <vector> #include <string> #include <algorithm> #include <cctype>// Function to compare two strings in a natural way bool naturalCompare(const std::string& a, const std:…

录制视频怎么操作?手把手教会你!

在这个互联网科技高速发展的时代&#xff0c;录制视频已经成为了人们生活中一个不可或缺的技能。无论是记录游戏精彩瞬间、制作教程、分享生活趣事&#xff0c;还是进行在线教学&#xff0c;录制视频都是一种非常直观有效的方式。可是录制视频怎么操作呢&#xff1f;本文将介绍…

Vue组件生命周期深度剖析:从创建到销毁的八大钩子实战指南

系列文章目录 Vue核心指令解析&#xff1a;探索MVVM与数据操作之美 文章目录 系列文章目录前言一、Vue生命周期是什么&#xff1f;二、钩子函数讲解1. beforeCreate( 创建前 )2. created ( 创建后 &#xff09;3. beforeMount&#xff08;挂载前&#xff09;4. mounted&#xf…

第11章 规划过程组(制订项目管理计划)

第11章 规划过程组&#xff08;一&#xff09;11.1制订项目管理计划&#xff0c;在第三本版教材第368~372页&#xff1b; 文字图片音频方式 视频16 第一个知识点&#xff1a;主要输入 1、事业环境因素 政府或行业标准(如产品标准、质量标准、安全标准和工艺标准) 法律法规要求…

乐乐趣《牛津话科学 侃侃闪闪的科学大冒险》新书分享会圆满落幕

2024年6月21日&#xff0c;乐乐趣《牛津话科学 侃侃闪闪的科学大冒险》新书分享会在BIBF绘本展活动区举行。牛津大学出版社中国区首席内容官孙赫男、北京师范大学教育学部副教授张进宝、中国美协漫画艺术委员会秘书长王立军、荣信文化副总经理兼乐乐趣总编辑孙肇志围绕孩子的科…

【Python机器学习】聚类算法的对比与评估——在人脸数据集上比较算法

数据探查&#xff1a; 我们将k均值、DBSCAN和凝聚聚类算法应用于Wild数据集中的Labeled Faces&#xff0c;并查看它们是否找到了有趣的结构。我们将使用数据的特征脸表示&#xff0c;它由包含100个成分的PCA(whitenTrue)生成&#xff1a; peoplefetch_lfw_people(data_home &…

ChatGPT API技术教程OpenAI APIKey在线对接-Chat Completion对象

表示模型根据提供的输入返回的聊天完成响应。 {"id": "chatcmpl-123","object": "chat.completion","created": 1677652288,"model": "gpt-3.5-turbo-0125","system_fingerprint": "fp…

锂价跌至近3年最低,大型能源公司已出手抄底,巴菲特也在参与

长远来看&#xff0c;随着电动化进程的深入推进&#xff0c;锂的战略地位依然不可替代。但短期内&#xff0c;供需失衡和价格波动可能会持续&#xff0c;行业参与者需要调整策略以应对当前的挑战。 锂业&#xff0c;正经历自2021年以来最为严峻的调整期。作为电动汽车电池的关…

SpringBoot学习03-[Spring Boot与Web开发]

Spring Boot与Web开发 RestTemplateMockMvc在SPringBoot中使用 SpringBoot整合swagger2SpringBoot的springmvc自动配置底层原理包含ContentNegotiatingViewResolver和BeanNameViewResolverContentNegotiatingViewResolverBeanNameViewResolver 支持提供静态资源&#xff0c;包括…

Inner Transitions

Inner Transitions 内部转换是指不退出源状态的转换。当为具有异或分解的超状态定义时&#xff0c;内部转换是强大的。 使用内部转换可以极大地简化Stateflow图表&#xff0c;如以下示例所示&#xff1a; 使用内部转换之前 使用内部转换到连接结点之后 使用内部转换到历史节点…