stm32定时器中断与误区_第1页
stm32定时器中断与误区_第2页
stm32定时器中断与误区_第3页
stm32定时器中断与误区_第4页
stm32定时器中断与误区_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

stm32定时器中断与误区STM32的定时器知识相当复杂,这里列举一些基础知识,在之后的文章我会写一下它的各种应用。通用定时器是一个通过可编程预分频器驱动的16位自动装载计数器构成。它适用于多种场合,包括定时中断、测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM)。每个定时器都是完全独立的,没有互相共享任何资源,它们可以一起同步操作。STM32F103RC系列有4个通用定时器,2个高级定时器和两个基本定时器:我们最常使用通用定时器,功能包括:1、16位向上、向下、向上/向下自动装载计数器(TIMx_CNT),例如向上是指:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件。2、16位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为1~65535之间的任意数值。3、4个独立通道(TIMx_CH1~4)。4、支持多种中断,如溢出中断等。这里我们讲述使用通用定时器中断实验:一、定时器时钟选择我们常使用内部时钟(CK_INT),通过配置TIMx_SMCR的SMS[2:0],配置为000。该时钟是ABP1时钟的的1倍(APB1不分频)或2倍(APB1分频)。二、计数器模式可选择向上、向下或者向上/向下。三、定时时间计算溢出时间=(自动加载值(ARR)+1)(预分频系数(PSC)+1)/定时器时钟(Tclk)四、库函数配置1、使能能定时器时钟。2、初始化定时器,配置ARR,PSC(在stm32f10x_tim.c)TIM_TimeBaseInit();其中的结构体:typedefstruct{uint16_tTIM_Prescaler;//设置分频系数uint16_tTIM_CounterMode;//计数方式uint16_tTIM_Period;//自动重装载值uint16_tTIM_ClockDivision;uint8_tTIM_RepetitionCounter;}TIM_TimeBaseInitTypeDef;3、开启定时器中断,配置中断优先级分组NVIC。voidTIM_ITConfig();NVIC_Init();4、使能定时器。TIM_Cmd();5、编写中断服务函数。TIMx_IRQHandler();stm32定时器误区在用到STM32定时器的更新中断时,发现有些情形下只要开启定时器就立即进入一次中断。准确说,只要使能更新中断允许位就立即响应一次更新中断【当然前提是相关NVIC也已经配置好】。换言之,只要使能了相关定时器更新中断,不管你定时间隔多长甚至不在乎你是否启动了相关定时器,它都会立即进入一次定时器更新中断服务程序。以STM32F051芯片为例,做了几种不同顺序的组合测试。根据测试发现,的确有些情况下一运行TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);【即使能更新中断】就立即进入更新中断服务程序。当然后面的中断都是正常的。老实说,这个问题比较容易忽视,有些情况下也无关紧要,但有些情况可能会给应用带来困扰。从STMCU相关技术手册似乎并不能明显地找到关于这个问题的很合适或者逻辑性很强的前因后果。经过验证测试,如果注意一下相关指令代码顺序是可以回避这个问题的。先做更新中断标志的清除操作,即清除TIMx-》SR寄存器里的UIF标志,然后做定时器更新中断的使能操作。至于开启相关定时器的指令摆放位置并不严格。下面是相关动作的操作顺序及结果,可以参考、验证之。这里共罗列了6种写法,其中有3种情形是会立即进入中断的,另外3种不会。TIM_ClearITPendingBit(TIM1,TIM_IT_Update);//清除更新中断请求位TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);//使能定时器1更新中断TIM_Cmd(TIM1,ENABLE);//启动定时器(1)。。。。。。不会立即进入更新中断程序。TIM_ClearITPendingBit(TIM1,TIM_IT_Update);//清除更新中断请求位TIM_Cmd(TIM1,ENABLE);TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);//使能定时器1更新中断(2)。。。。。。不会立即进入更新中断程序。TIM_Cmd(TIM1,ENABLE);TIM_ClearITPendingBit(TIM1,TIM_IT_Update);//清除更新中断请求位TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);//使能定时器1更新中断(3)。。。。。。不会立即进入更新中断程序。TIM_ClearITPendingBit(TIM1,TIM_IT_Update);//清除更新中断请求位TIM_Cmd(TIM1,ENABLE);(5)。。。。。。立即进入更新中断程序。(6)。。。。。。立即进入更新中断程序。顺便提下关于定时器里UG位和URS位的使用,分别在TIMx-》EGR和TIMx-》CR1寄存器里。对UG位置1可以产生更新事件并对相关计数器和寄存器重新初始化,如果URS位为0的话,同时会产生更新中断。如果不希望对UG位置1的同时产生更新中断,得置URS位为1,否则会立即进入更新中断。另外我们平时使用定时器的时候多数都是处于开启状态,平时的定时中断书写格式一般是:voidTIM3_IRQHandler(void){if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET){TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//要处理的事件内容。。。。}}但是,项目的实验过程中,我使用的定时器处理事件稍微有点特殊,即,定时器不是一直处于开启状态,而且关闭时候也是在中断里关闭。大概形式这样:voidTIM3_IRQHandler(void){if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET){TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//要处理的事件内容。。。。TIM_Cmd(TIM3,DISABLE);//失能(函数外使能)}}看似没错,而且也看似正常。但是,处理的事件内容出现了很多未知错误(由于我的这个处理事件有很强的时序性,开始和结束都比较严格),无法正常执行。通过后来的调试中发现(把处理时间改为点灯或者打印输出方式),发现是:TIM_Cmd(TIM3,DISABLE);扰乱了时序关系。当失能后,其实中断并没有真正失能,还会再进入一次中断,因此事件又被执行了一次,对于时序比较严格的事件,就产生了问题!找到了原因,因此,我猜测虽然定时器失能并且关闭了定时器,但是可能中断标志位并没真正清除,虽然中断开始已经清除过一次,但估计因为失能使得标志位又被置位了,因此,我在失能前面加了句清除中断更新标志位,如下:voidTIM3_IRQHandler(void){if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET){TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//要处理的事件内容。。。。TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//再清除标志位TIM_Cmd(TIM3,DISABLE);//失能(函数外使能)}}果然,程序可以正常的时序运行。比较纳闷关定时器前又得清下标志位,因此引起了另一个好奇心,是不是在其他地方关闭定时器(如主函数)

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论