STM32在运行时读取时间定时器开关CNT值的问题

sponsored links
STM32 定时器用于外部脉冲计数,修改版,解决3..4库对应的无响应外部脉冲的问题
这里先总结一下各个time对应的gpio
TIMER1 & --& &PA12
TIMER2 & --& &PA0
& TIMER3 & --& &PD2
TIMER4 & --& &PE0
暂时够了,更多的建议参考数据手册
基于库3.4代码,网上参考了很多代码,一直有问题,估计是库版本的问题,引用下边的一片文章,红色文字为本人注释和修改。
STM32 定时器用于外部脉冲计数
&&&& 因为用stm32f103c8作主控制器,来控制小车,小车的转速由两路光电编码盘输入(左右各一路).因此想到外部时钟触发模式(TIM——ETRClockMode2Config)。
&&&& 可以试好好久,发现TIM1不能计数,到网上查了很久,也没有找到相关的文章,开始怀疑TIM1是不是需要特殊设置。经过很久的纠结,终于找到了问题——其实是我自己在GPIO设置的时候,后面的不小心覆盖了前面的了——没想到自己也会犯这么SB的事情。
&&&& 现总结程序如下:
第一步,设置GPIO
GPIO_InitTypeDef GPIO_InitS
/* PA0,PA12-& 左右脉冲输入 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M时钟速度
GPIO_Init(GPIOA, &GPIO_InitStructure);
注意:(1)stm32f103c8只有TIM1_ETR(PA12,Pin33),和TIM2_CH1_ETR(PA0,Pin10)两个可以用。其它更多管脚的芯片,有更多的可以输入(如100管脚的有4个可以输入的);(2)外部时钟输入与中断无关;(3)stm32f103c8的这个两个应用中,不需要重映射。
对于哪些需要重映射,参考数据手册。
第二步:设置RCC
&& RCC_ClocksTypeDef RCC_ClockF
SystemInit();//源自system_stm32f10x.c文件,只需要调用此函数,则可完成RCC的配置.
RCC_GetClocksFreq(&RCC_ClockFreq);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
第三步,设置定时器模式
void TIM1_Configuration(void) //只用一个外部脉冲端口
TIM_TimeBaseInitTypeDef&& TIM_TimeBaseS
&& //配置TIMER1作为计数器
&& TIM_DeInit(TIM1);
&& TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
TIM_TimeBaseStructure.TIM_Prescaler = 0x00;//设置预分频可以将外部信号分频
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); // Time base configuration
TIM_ITRxExternalClockConfig(TIM2,TIM_TS_ETRF); //我测试中一直不能用的原因是缺少这句话,缺少后,timer的驱动时钟源默认是RCC,需要更改为外部ETR输入才行。
TIM_ETRClockMode2Config(TIM1, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);
TIM_SetCounter(TIM1, 0);
TIM_Cmd(TIM1, ENABLE);
void TIM2_Configuration(void) //只用一个外部脉冲端口
TIM_TimeBaseInitTypeDef&& TIM_TimeBaseS
&& //配置TIMER2作为计数器
&& TIM_DeInit(TIM2);
&& TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
TIM_TimeBaseStructure.TIM_Prescaler = 0x00;
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); // Time base configuration
TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);
TIM_SetCounter(TIM2, 0);
TIM_Cmd(TIM2, ENABLE);
第四步,可以在主函数中读取计数器的值,其它的应用,就看具体的情况了。
u16 COUN1=0;
u16 COUN2=0;
int main(void)
ChipHalInit();
ChipOutHalInit();
&& COUN1=TIM1-&CNT;
&& COUN2=TIM2-&CNT;
然后就可以用了
当然你可以使能中断,TIM_ARRPreloadConfig(TIM2, ENABLE);
/*预先清除所有中断位*/
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
/* 4个通道和溢出都配置中断*/
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
并且在终端中重装填计数器数据,既可以在计数若干后产生一次中断
void TIM2_IRQHandler(void)
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);&
// TIM_Cmd(TIM2, DISABLE);
TIM2-&CNT=65530; &
仁者见仁吧,以后有机会再深入研究。。不得不说,用了stm32 的api库后,很多寄存器都懒得看了。。。。悲剧啊
源:STM32 定时器用于外部脉冲计数 STM32 定时器(一)——定时器时间的计算 STM32的定时器是灰常NB的,也是灰常让人头晕的(当然是对于白菜来说的). STM32中的定时器有很多用法: (一)系统时钟(SysTick) 设置非常简单,以下是产生1ms中断的设置,和产生10ms延时的函数: void RCC_Configuration(void)
我的Delphi开发经验谈(本人修改版) 收藏 开发环境--------
Delphi 7是一个很经典的版本,在Win2000/XP下推荐安装Delphi 7来开发软件,在Vista下推荐使用Delphi 2007开发软件.安装好Delphi 7后,应立即安装Delphi 7 Update Pack 1,Delphi 2007则建议尽量安装最新的版本 ...
定时器2+串口发送 USART.c #include &STM32Lib\\stm32f10x.h& /********************************************** **串口配置函数,这里使能了两个串口,其中串口2使用了中断接收模式 ** ********************************** ...
电磁场仿真软件CST原版宏:Parameter Mesh的修改版(自动更新参数取值) 作者:aaron8967 主页:http://aaron8967.blog.51cto.com 说明: 我在学习和使用CST软件的过程中,首先建立了参数化的结构模型,然后想通过改变结构参数的取值,让CST自动对不同的结构进行仿真计算.但是CST自带的宏程序无法完全满足我要求 ...
STM32定时器溢出模式设置 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 环境: 主机:WIN7 开发环境:MDK4.23 MCU:STM32F103CBT6 源代码1: 说明:定时器采用TIM2,时钟源为内部8M晶振,向上溢出模式.此定时器用在延时函数,最小可以延时1us,故没有采用中断形式定时. 初始化 ...亮点嵌入式-stm32运行一段后不进定时器中断,不知道是什么原因-爱板网论坛 -
电子工程师学习交流园地
后使用快捷导航没有帐号?
查看: 5067|回复: 10
注册时间最后登录阅读权限10积分35精华0帖子
白丁, 积分 35, 距离下一级还需 15 积分
该用户从未签到
目前遇到的问题,设备有一个led灯,程序正常运行时闪烁;主程序中开启看门狗了,LED闪烁是在定时器中断中完成的,但现在LED不闪了,程序还没有复位;我猜测,程序中主程序还在正常运行,只是不能进入定时器中断了;
程序中一共开启了5个中断,中断优先级分组设置为 NVIC_PriorityGroup_0,一共开启5个中断,三个串口中断子优先级分别为1、2、3,一个定时器2中断子优先级为0,一个RTC中断子优先级为4;
定时器中断程序如下
void TIM2_IRQHandler(void)
&&if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
&&//第一层函数使用。
&&if(systime2!=0xffffffff)
&&systime2++;
&&if(systime3!=0xffffffff)
&&systime3++;
&&if(systime4!=0xffffffff)
&&systime4++;
&&if(systime44!=0xffffffff)
&&systime44++;
&&if(systime45!=0xffffffff)
&&systime45++;
&&//ms延时函数用
&&if(systime10 &= 60000)& && && &
& && &systime10++;& && && && && & //系统心跳时间累加
&&//-------------------------------------------------------
&&//-------------------------------------------------------
&&//LED灯状态控制
&&if((systime5 & led_en) && (led_en&0))
& &&&LED_EN_HIGH();//亮
&&else if(led_en&4000)
& &&&LED_EN_LOW(); //灭
&&systime5 ++;
&&if(systime5 &= (led_en&&1))
& &&&systime5 = 0;
//------------------------------------------------------------------------------
& & capture = TIM_GetCapture1(TIM2);
& & TIM_SetCompare1(TIM2, capture + CCR1_Val);
&&TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
注册时间最后登录阅读权限30积分385精华0帖子
秀才, 积分 385, 距离下一级还需 115 积分
TA的每日心情开心 16:04签到天数: 40 天连续签到: 1 天[LV.5]常住居民I
我帮你分析一下啊,按照你的分析你程序是运行的,定时器优先级那么高 不可能不会进去定时器,那么有可能就是定时器配合是否正确。
给你的建议:
你能否通过jlink仿真一下看程序跑哪里去了?或者在程序运行中加一些标志如LED闪烁,串口发送数据等判断程序运行到哪儿了呢。
注册时间最后登录阅读权限30积分385精华0帖子
秀才, 积分 385, 距离下一级还需 115 积分
TA的每日心情开心 16:04签到天数: 40 天连续签到: 1 天[LV.5]常住居民I
还有就是验证你的看门狗能否工作,就是不去喂狗,系统能否到时间自动复位。
注册时间最后登录阅读权限10积分35精华0帖子
白丁, 积分 35, 距离下一级还需 15 积分
该用户从未签到
本帖最后由 外面的世界很精 于
15:28 编辑
测试过看门狗,工作正常;这个问题不是上电就会有,有可能需要连续上电几天后才会出现,这个是最头疼的一点,而且我没有手段重现问题
注册时间最后登录阅读权限30积分385精华0帖子
秀才, 积分 385, 距离下一级还需 115 积分
TA的每日心情开心 16:04签到天数: 40 天连续签到: 1 天[LV.5]常住居民I
外面的世界很精 发表于
测试过看门狗,工作正常;这个问题不是上电就会有,有可能需要连续上电几天后才会出现,这个是最头疼的一点 ...
这个就很头疼了啊!我也没招了,希望你能早点找到问题所在!
注册时间最后登录阅读权限100积分4992精华0帖子
TA的每日心情奋斗8&小时前签到天数: 688 天连续签到: 7 天[LV.9]以坛为家II
这个是优先级没有选对,你把定时器优先级设比定时器高,试下,再有用得着看门狗吗,闭了它
注册时间最后登录阅读权限10积分35精华0帖子
白丁, 积分 35, 距离下一级还需 15 积分
该用户从未签到
ddllxxrr 发表于
这个是优先级没有选对,你把定时器优先级设比定时器高,试下,再有用得着看门狗吗,闭了它 ...
没太看明白什么意思?
注册时间最后登录阅读权限10积分35精华0帖子
白丁, 积分 35, 距离下一级还需 15 积分
该用户从未签到
谢谢各位的关注
注册时间最后登录阅读权限10积分3精华0帖子
白丁, 积分 3, 距离下一级还需 47 积分
该用户从未签到
楼主解决了 我有时候也是而且我的中断 也有好多呢&&和你 有时候差不多
注册时间最后登录阅读权限10积分10精华0帖子
白丁, 积分 10, 距离下一级还需 40 积分
TA的每日心情衰 22:59签到天数: 1 天连续签到: 1 天[LV.1]初来乍到
路过学习一下
爱板会员勋章
注册成为爱板网会员
活跃会员勋章
经常参与各类话题的讨论,发帖内容较有主见
技术先锋勋章
经常在论坛进行技术交流、传播、讨论
发帖机器勋章
在论坛积极发帖,数量巨大,质量较高
站长推荐 /5
Powered by Discuz!技术小站:
& 参加直播现场,与专家互动,学最新知识
& 学习业内最热门知识,还有好礼送
& 看视频,填问卷,拿好礼
& 海量精华技术资源 限时阅读下载
张飞电子工程师速成全集
10天掌握PCB AD画板
教你高速PCB项目整体设计
如何设计STM32单片机系统?
物联网操作系统从写到用
讲师:华清远见
讲师:林超文
讲师:郑振宇
讲师:李述铜
移入鼠标可放大二维码
stm32定时器时间计算
来源:互联网 作者:日 16:27
[导读] STM32定时器的工作原理 STM32之所以能够实现定时,是单片机内部在计数脉冲(来自晶振) T=1/F (F为频率) 例如:我们以51单片机举例,假设单片机搭配12MHz的晶振,由于51单片机是12分频(即1个机器周期有12个时钟周期),则单片机的最小定时时间为 1 2 MHz / 2 = 1 MHz Tt = 1 / 1 MHz = 1 us 最小定时时间T=1/1MHz=1us 51单片机定时器: 方式0 13位最大定时时间间隔2^13=8.192ms 方式1 16位最大定时时间间隔2^16=65.536ms 方式2 8位最大定时时间间隔2^8=256us 由此我们知道对于一个
  STM32定时器的工作原理
  STM32之所以能够实现定时,是单片机内部在计数脉冲(来自晶振)
  T=1/F (F为频率)
  例如:我们以51单片机举例,假设单片机搭配12MHz的晶振,由于51单片机是12分频(即1个机器周期有12个时钟周期),则单片机的最小定时时间为
  1 2 MHz / 2 = 1 MHz
  Tt = 1 / 1 MHz = 1 us
  最小定时时间T=1/1MHz=1us
  51单片机定时器:
  方式0 13位最大定时时间间隔2^13=8.192ms
  方式1 16位最大定时时间间隔2^16=65.536ms
  方式2 8位最大定时时间间隔2^8=256us
  由此我们知道对于一个定时器而言要做到精确定时需要关注2个内容
  1、分频器(分频比)
  2、定时计数器的值
  STM32定时器的时钟
  CK_CNT表示定时器工作频率
  MX_PSC表示分频系数
  则定时器的工作频率计算公式为
  CK_CNT=定时器时钟/( Mx_PSC+1)
  由此我们可得到STM32单片机1个时钟周期
  为:T=1/ CK_CNT
  例如普通定时器模块的时钟为72MH2,分频比位7199,那么我们想要得到一个1秒钟的定时,定时计数器的值需要设定为 》 mx arr = 1 0 0 0 0
  因为0=10KHz时钟周期T=1/10KHz=100us100us&10000=1S
  结论:分频比7199定时计数器的值10000
  注意两点:
  (1)TIMx(1-8),在库设置默认的情况下,都是72M的时钟;
  (2)TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
  是重复计数,就是重复溢出多少次才给你来一个溢出中断,
  它对应的寄存器叫TIM1 RCR.
  如果这个值不配置,上电的时候寄存器值可能随机的,本来1秒中断一次,可能变成N 秒中断一次,让计算量变大。
  stm32定时器时间计算
  系统时钟是72Mhz,TIM1 是由PCLK2 (72MHz)得到,TIM2-7是由 PCLK1 得到
  关键是设定 时钟预分频数,自动重装载寄存器周期的值
  /*每1秒发生一次更新事件(进入中断服务程序)。RCC_Configuration()的SystemInit()的
  RCC-》CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2表明TIM3CLK为72MHz。因此,每次进入中
  断服务程序间隔时间为
  ((1+TIM_Prescaler )/72M)*(1+TIM_Period )=((1+7199)/72M)*(1+9999)=1秒 */
  定时器的基本设置
  1、 TIM_TimeBaseStructure.TIM_Prescaler = 7199;//时钟预分频数 例如 :时钟频率=72/(时钟预分频+1)
  2、TIM_TimeBaseStructure.TIM_Period = 9999; // 自动重装载寄存器周期的值(定时时间) 累计 0xFFFF个频率后产生个更新或者中断(也是说定时时间到)
  3、 TIM_TimeBaseStructure.TIM_CounterMode = TIM1_CounterMode_Up; //定时器模式 向上计数
  4、 TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; //时间分割值
  5、 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);//初始化定时器2
  6、 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //打开中断 溢出中断
  7、 TIM_Cmd(TIM2, ENABLE);//打开定时器
  或者:
  TIM_TimeBaseStructure.TIM_Prescaler = 35999;//分频35999 72M/
  (35999+1)/2=1Hz 1秒中断溢出一次
  TIM_TimeBaseStructure.TIM_Period = 2000; //计数值2000
  ((1+TIM_Prescaler )/72M)*(1+TIM_Period )=((1+35999)/72M)*(1+2000)=1秒 */
关注电子发烧友微信
有趣有料的资讯及技术干货
下载发烧友APP
打造属于您的人脉电子圈
关注发烧友课堂
锁定最新课程活动及技术直播
声明:电子发烧友网转载作品均尽可能注明出处,该作品所有人的一切权利均不因本站而转移。
作者如不同意转载,既请通知本站予以删除或改正。转载的作品可能在标题或内容上或许有所改动。
定时器时间计算相关文章
定时器时间计算相关下载
stm32相关文章
stm32相关下载
论坛精华干货
供应链服务
版权所有 (C) 深圳华强聚丰电子科技有限公司
电信与信息服务业务经营许可证:粤B2-第31章 &&&&TIM&基本定时器
全套集视频教程和页教程请到秉火论坛下载:
野火视频教程优酷观看网址:
本章参考资料:《中文参考手册》、《规格书》、库帮助文档《》。
学习本章时,配合《中文参考手册》基本定时器章节一起阅读,效果会更佳,特别是涉及到寄存器说明的部分。
特别说明,本书内容是以系列控制器资源讲解。
31.1 TIM简介
定时器最基本的功能就是定时了,比如定时发送数据、定时采集数据等等。如果把定时器与结合起来使用的话可以实现非常丰富的功能,可以测量输入信号的脉冲宽度,可以生产输出波形。定时器生产控制电机状态是工业控制普遍方法,这方面知识非常有必要深入了解。
系列控制器有个高级控制定时器、个通用定时器和个基本定时器,还有个看门狗定时器。看门狗定时器不在本章讨论范围,有专门讲解的章节。控制器上所有定时器都是彼此独立的,不共享任何资源。各个定时器特性参考表。
表 01 各个定时器特性
定时器类型
计数器分辨率
计数器类型
预分频系数
捕获比较通道
最大接口时钟
最大定时器时钟
递增、递减、递增递减
递增、递减、递增递减
递增、递减、递增递减
其中最大定时器时钟可通过寄存器配置为或者。
定时器功能强大,这一点透过《中文参考手册》讲解定时器内容就有多页就显而易见了。定时器篇幅长,内容多,对于新手想完全掌握确实有些难度,特别参考手册是先介绍高级控制定时器,然后介绍通用定时器,最后才介绍基本定时器。实际上,就功能上来说通用定时器包含所有基本定时器功能,而高级控制定时器包含通用定时器所有功能。所以高级控制定时器功能繁多,但也是最难理解的,本章我们先选择最简单的基本定时器进行讲解。
31.2 基本定时器
基本定时器比高级控制定时器和通用定时器功能少,结构简单,理解起来更容易,我们就开始先讲解基本定时器内容。基本定时器主要两个功能,第一就是基本定时功能,生成时基,第二就是专门用于驱动数模转换器。关于驱动具体应用参考章节。
控制器有两个基本定时器和,功能完全一样,但所用资源彼此都完全独立,可以同时使用。在本章内容中,以统称基本定时器。
基本上定时器和是一个位向上递增的定时器,当我在自动重载寄存器添加一个计数值后并使能,计数寄存器就会从开始递增,当的数值与值相同时就会生成事件并把寄存器清,完成一次循环过程。如果没有停止定时器就循环执行上述过程。这些只是大概的流程,希望大家有个感性认识,下面细讲整个过程。
31.3 基本定时器功能框图
基本定时器的功能框图包含了基本定时器最核心内容,掌握了功能框图,对基本定时器就有一个整体的把握,在编程时思路就非常清晰,见图。
首先先看图中绿色框内容,第一个是带有阴影的方框,方框内容一般是一个寄存器名称,比如图中主体部分的自动重载寄存器或预分频器,这里要特别突出的是阴影这个标志的作用,它表示这个寄存器还自带有影子寄存器,在硬件结构上实际是有两个寄存器,源寄存器是我们可以进行读写操作,而影子寄存器我们是完全无法操作的,有内部硬件使用。影子寄存器是在程序运行时真正起到作用的,源寄存器只是给我们读写用的,只有在特定时候特定事件发生时才把源寄存器的值拷贝给它的影子寄存器。多个影子寄存器一起使用可以到达同步更新多个寄存器内容的目的。
接下来是一个指向右下角的图标,它表示一个事件,而一个指向右上角的图标表示中断和输出。这个我们把它放在图中主体更好理解。图中的自动重载寄存器有影子寄存器,它左边有一个带有""字母的事件图标,表示在更新事件生成时就把自动重载寄存器内容拷贝到影子寄存器内,这个与上面分析是一致。寄存器右边的事件图标、中断和输出图标表示在自动重载寄存器值与计数器寄存器值相等时生成事件、中断和输出。
图 01 基本定时器功能框图
1.&&&&①时钟源
定时器要实现计数必须有个时钟源,基本定时器时钟只能来自内部时钟,高级控制定时器和通用定时器还可以选择外部时钟源或者直接来自其他定时器等待模式。我们可以通过专用时钟配置寄存器的位设置所有定时器的时钟频率,我们一般设置该位为默认值,使得表中可选的最大定时器时钟为,即基本定时器的内部时钟频率为。
基本定时器只能使用内部时钟,当和控制寄存器的位置时,启动基本定时器,并且预分频器的时钟来源就是。对于高级控制定时器和通用定时器的时钟源可以来找控制器外部时钟、其他定时器等等模式,较为复杂,我们在相关章节会详细介绍。
2.&&&&②控制器
定时器控制器控制实现定时器功能,控制定时器复位、使能、计数是其基础功能,基本定时器还专门用于转换触发。
3.&&&&③计数器
基本定时器计数过程主要涉及到三个寄存器内容,分别是计数器寄存器、预分频器寄存器、自动重载寄存器,这三个寄存器都是位有效数字,即可设置值为至。
首先我们来看图中预分频器,它有一个输入时钟和一个输出时钟。输入时钟来源于控制器部分,基本定时器只有内部时钟源所以实际等于,即。在不同应用场所,经常需要不同的定时频率,通过设置预分频器的值可以非常方便得到不同的,实际计算为:等于。
图是将预分频器的值从改为时计数器时钟变化过程。原来是分频,和频率相同。向寄存器写入新值时,并不会马上更新输出频率,而是等到更新事件发生时,把寄存器值更新到影子寄存器中,使其真正产生效果。更新为分频后,在连续出现个脉冲后才产生一个脉冲。
图 02 基本定时器时钟源分频
在定时器使能置时,计数器根据频率向上计数,即每来一个脉冲,值就加。当值与的设定值相等时就自动生成事件并自动清零,然后自动重新开始计数,如此重复以上过程。为此可见,我们只要设置和这两个寄存器的值就可以控制事件生成的时间,而我们一般的应用程序就是在事件生成的回调函数中运行的。在递增至与值相等,我们叫做为定时器上溢。
自动重载寄存器用来存放于计数器值比较的数值,如果两个数值相等就生成事件,将相关事件标志位置位,生成和中断输出。有影子寄存器,可以通过寄存器的位控制影子寄存器功能,如果位置,影子寄存器有效,只有在事件更新时才把值赋给影子寄存器。如果位为,修改值马上有效。
4.&&&&定时器周期计算
经过上面分析,我们知道定时事件生成时间主要由和两个寄存器值决定,这个也就是定时器的周期。比如我们需要一个周期的定时器,具体这两个寄存器值该如何设置内。假设,我们先设置寄存器值为,即当从开始计算,刚好等于时生成事件,总共计数次,那么如果此时时钟源周期为即可得到刚好的定时周期。
接下来问题就是设置寄存器值使得输出为周期的时钟。预分频器的输入时钟为,所以设置预分频器值为即可满足。
31.4 定时器初始化结构体详解
标准库函数对定时器外设建立了四个初始化结构体,基本定时器只用到其中一个即,该结构体成员用于设置定时器基本工作参数,并由定时器基本初始化配置函数调用,这些设定参数将会设置定时器相应的寄存器,达到配置定时器工作环境的目的。这一章我们只介绍结构体,其他结构体将在相关章节介绍。
初始化结构体和初始化库函数配合使用是标准库精髓所在,理解了初始化结构体每个成员意义基本上就可以对该外设运用自如了。初始化结构体定义在文件中,初始化库函数定义在文件中,编程时我们可以结合这两个文件内注释使用。
代码清单 01 定时器基本初始化结构体
1 typedef struct {
uint16_t TIM_P // 预分频器
uint16_t TIM_CounterM // 计数模式
uint32_t TIM_P // 定时器周期
uint16_t TIM_ClockD // 时钟分频
uint8_t TIM_RepetitionC // 重复计算器
7 } TIM_TimeBaseInitTypeD
(1)&&&&TIM_Prescaler:定时器预分频器设置,时钟源经该预分频器才是定时器时钟,它设定TIMx_PSC寄存器的值。可设置范围为0至65535,实现1至65536分频。
(2)&&&&TIM_CounterMode:定时器计数方式,可是在为向上计数、向下计数以及三种中心对齐模式。基本定时器只能是向上计数,即TIMx_CNT只能从0开始递增,并且无需初始化。
(3)&&&&TIM_Period:定时器周期,实际就是设定自动重载寄存器的值,在事件生成时更新到影子寄存器。可设置范围为0至65535。
(4)&&&&TIM_ClockDivision:时钟分频,设置定时器时钟CK_INT频率与数字滤波器采样时钟频率分频比,基本定时器没有此功能,不用设置。
(5)&&&&TIM_RepetitionCounter:重复计数器,属于高级控制寄存器专用寄存器位,利用它可以非常容易控制输出PWM的个数。这里不用设置。
虽然定时器基本初始化结构体有个成员,但对于基本定时器只需设置其中两个就可以,想想使用基本定时器就是简单。
31.5 基本定时器定时实验
在转换中几乎都用到基本定时器,使用有关基本定时器触发转换内容在章节讲解即可,这里就利用基本定时器实现简单的定时功能。
我们使用基本定时器循环定时并使能定时器中断,每到就在定时器中断服务函数翻转彩灯,使得最终效果彩灯暗,亮,如此循环。
31.5.1 硬件设计
基本定时器没有相关,这里我们只用定时器的定时功能,无效其他外部引脚,至于彩灯硬件可参考章节。
31.5.2 软件设计
这里只讲解核心的部分代码,有些变量的设置,头文件的包含等并没有涉及到,完整的代码请参考本章配套的工程。我们创建了两个文件:和文件用来存基本定时器驱动程序及相关宏定义,中断服务函数放在文件中。
1.&&&&编程要点
(1)&&&&初始化RGB彩灯GPIO;
(2)&&&&开启基本定时器时钟;
(3)&&&&设置定时器周期和预分频器;
(4)&&&&启动定时器更新中断,并开启定时器;
(5)&&&&定时器中断服务函数实现RGB彩灯翻转。
2.&&&&软件分析
代码清单 02 宏定义
1 #define BASIC_TIM TIM6
2 #define BASIC_TIM_CLK RCC_APB1Periph_TIM6
4 #define BASIC_TIM_IRQn TIM6_DAC_IRQn
5 #define BASIC_TIM_IRQHandler TIM6_DAC_IRQHandler
使用宏定义非常方便程序升级、移植。
代码清单 03 NVIC配置
1 static void TIMx_NVIC_Configuration(void)
NVIC_InitTypeDef NVIC_InitS
// 设置中断组为0
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
// 设置中断来源
NVIC_InitStructure.NVIC_IRQChannel = BASIC_TIM_IRQn;
// 设置抢占优先级
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// 设置子优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
实验用到定时器更新中断,需要配置,实验只有一个中断,对配置没什么具体要求。
基本定时器模式配置
代码清单 04 基本定时器模式配置
1 static void TIM_Mode_Config(void)
TIM_TimeBaseInitTypeDef TIM_TimeBaseS
// 开启TIMx_CLK,x[6,7]
RCC_APB1PeriphClockCmd(BASIC_TIM_CLK, ENABLE);
/* 累计 TIM_Period个后产生一个更新或者中断*/
//当定时器从0计数到4999,即为5000次,为一个定时周期
TIM_TimeBaseStructure.TIM_Period = 5000-1;
//定时器时钟源TIMxCLK = 2 * PCLK1
// PCLK1 = HCLK / 4
// =& TIMxCLK=HCLK/2=SystemCoreClock/2=90MHz
// 设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=10000Hz
TIM_TimeBaseStructure.TIM_Prescaler = 9000-1;
// 初始化定时器TIMx, x[2,3,4,5]
TIM_TimeBaseInit(BASIC_TIM, &TIM_TimeBaseStructure);
// 清除定时器更新中断标志位
TIM_ClearFlag(BASIC_TIM, TIM_FLAG_Update);
// 开启定时器更新中断
TIM_ITConfig(BASIC_TIM,TIM_IT_Update,ENABLE);
// 使能定时器
TIM_Cmd(BASIC_TIM, ENABLE);
使用定时器之前都必须开启定时器时钟,基本定时器属于总线外设。
接下来设置定时器周期数为,即计数次生成事件。设置定时器预分频器为,基本定时器使能内部时钟,频率为,经过预分频器后得到的频率。然后就是调用函数完成定时器配置。
函数用来在配置中断之前清除定时器更新中断标志位,实际是清零寄存器的位。
使用函数配置使能定时器更新中断,即在发生上溢时产生中断。
最后使用函数开启定时器。
定时器中断服务函数
代码清单 05 定时器中断服务函数
1 void BASIC_TIM_IRQHandler (void)
if ( TIM_GetITStatus( BASIC_TIM, TIM_IT_Update) != RESET ) {
LED1_TOGGLE;
TIM_ClearITPendingBit(BASIC_TIM , TIM_IT_Update);
我们在函数启动了定时器更新中断,在发生中断时,中断服务函数就得到运行。在服务函数内我们先调用定时器中断标志读取函数获取当前定时器中断位状态,确定产生中断后才运行彩灯翻转动作,并使用定时器标志位清除函数清除中断标志位。
代码清单 06 主函数
1 int main(void)
LED_GPIO_Config();
/* 初始化基本定时器定时,1s产生一次中断 */
TIMx_Configuration();
while (1) {
实验用到彩灯,需要对其初始化配置。函数是定义在文件的完成彩灯初始化配置的程序。
函数是定义在文件的一个函数,它只是简单的先后调用和两个函数完成配置和基本定时器模式配置。
31.5.3 下载验证
保证开发板相关硬件连接正确,把编译好的程序下载到开发板。开始彩灯是暗的,等一会彩灯变为红色,再等一会又暗了,如此反复。如果我们使用表钟与彩灯闪烁对比,可以发现它是每改变一次彩灯状态的。
31.6 每课一问
1.&&&&计算基本定时器一次最长定时时间,如果需要使用基本定时器产生100s周期事件有什么办法实现?
2.&&&&修改实验程序,在保使其每0.5s翻转一次LED1的同时在每10s翻转LED2。
阅读(...) 评论()}

我要回帖

更多关于 定时器怎么设置时间 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信