首页 时钟

时钟

举报
开通vip

时钟 132 3.7 定时器中断实验 这一节,我们将向大家介绍如何使用 STM32 的通用定时器,STM32 的定时器功能十分强 大,有 TIME1 和 TIME8 等高级定时器,也有 TIME2~TIME5 等通用定时器,还有 TIME6 和 TIME7 等基本定时器。在《STM32 参考手册》里面,定时器的介绍占了 1/5 的篇幅,足见其重 要性。这一节,我们选择难度适中的通用定时器来介绍。本节分为如下几个部分: 3.7.1 STM32 通用定时器简介 3.7.2 硬件设计 3.7.3 软件...

时钟
132 3.7 定时器中断实验 这一节,我们将向大家介绍如何使用 STM32 的通用定时器,STM32 的定时器功能十分强 大,有 TIME1 和 TIME8 等高级定时器,也有 TIME2~TIME5 等通用定时器,还有 TIME6 和 TIME7 等基本定时器。在《STM32 参考手册》里面,定时器的介绍占了 1/5 的篇幅,足见其重 要性。这一节,我们选择难度适中的通用定时器来介绍。本节分为如下几个部分: 3.7.1 STM32 通用定时器简介 3.7.2 硬件设计 3.7.3 软件设计 3.7.4 下载与测试 133 3.7.1 STM32 通用定时器简介 STM32 的通用定时器是一个通过可编程预分频器(PSC)驱动的 16 位自动装载计数器 (CNT)构成。STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产 生输出波形(输出比较和 PWM)等。 使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长 度和波形周期可以在几个微秒到几个毫秒间调整。STM32 的每个通用定时器都是完全独立的, 没有互相共享的任何资源。 STM3 的通用 TIMx (TIM2、TIM3、TIM4 和 TIM5)定时器功能包括: 1)16 位向上、向下、向上/向下自动装载计数器(TIMx_CNT)。 2)16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为 1~ 65535 之间的任意数值。 2)4 个独立通道(TIMx_CH1~4),这些通道可以用来作为: A.输入捕获 B.输出比较 C.PWM 生成(边缘或中间对齐模式) D.单脉冲模式输出 3)可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外 一个定时器)的同步电路。 4)如下事件发生时产生中断/DMA: A.更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发) B.触发事件(计数器启动、停止、初始化或者由内部/外部触发计数) C.输入捕获 D.输出比较 E.支持针对定位的增量(正交)编码器和霍尔传感器电路 F.触发输入作为外部时钟或者按周期的电流管理 由于 STM32 通用定时器比较复杂,这里我们不再多介绍,请大家直接参考《STM32 参考 手册》第 211 页,通用定时器一章。下面我们介绍一下与我们这节实验密切相关的几个通用定 时器的寄存器。 首先是控制寄存器 1(TIMx_CR1),该寄存器的各位描述如下: 134 135 图 3.7.1.1 寄存器 TIMx_CR1 各位描述 接下来介绍第二个与我们这节密切相关的寄存器:DMA/中断使能寄存器(TIMx_DIER)。 该寄存器是一个 16 位的寄存器,其各位描述如下: 图 3.7.1.2 寄存器 TIMx_ DIER 各位描述 这里我们仅关心它的第 6 位和第 0 位,第 6 位 TIE 为触发中断使能位,通过将该位置 1 使 能 TIMx 的中断触发,注意只要是 TIMx 需要使用中断,该位必须为 1。而第 0 位,则为允许更 新中断位,通过置 1,来允许由于更新事件而产生的中断。 接下来我们看第三个与我们这节有关的寄存器:预分频寄存器(TIMx_PSC)。该寄存器用 设置对时钟进行分频,然后提供给计数器,作为计数器的时钟。该寄存器的各位描述如下: 图 3.7.1.3 寄存器 TIMx_ PSC 各位描述 这里,我们的时钟来源有 4 个: 1)内部时钟(CK_INT) 2)外部时钟模式 1:外部输入脚(TIx) 3)外部时钟模式 2:外部触发输入(ETR) 4)内部触发输入(ITRx):使用 A 定时器作为 B 定时器的预分频器(A 为 B 提供时钟)。 这些时钟,具体选择哪个可以通过 TIMx_SMCR 寄存器的相关位来设置。这里的 CK_INT 时钟是从 APB1 倍频的来的,除非 APB1 的时钟分频数设置为 1,否则通用定时器 TIMx 的时钟 是 APB1 时钟的 2 倍,当 APB1 的时钟不分频的时候,通用定时器 TIMx 的时钟就等于 APB1 的时钟。这里还要注意的就是高级定时器的时钟不是来自 APB1,而是来自 APB2 的。 这里顺带介绍一下 TIMx_CNT 寄存器,该寄存器是定时器的计数器,该寄存器存储了当前 定时器的计数值。 接着我们介绍自动重装载寄存器(TIMx_ARR),该寄存器在物理上实际对应着 2 个寄存器。 一个是程序员可以直接操作的,另外一个是程序员看不到的,这个看不到的寄存器在《STM32 参考手册》里面被叫做影子寄存器。事实上真正起作用的是影子寄存器。根据 TIMx_CR1 寄存 器中 APRE 位的设置:APRE=0 时,预装载寄存器的内容可以随时传送到影子寄存器,此时 2 者是连通的;而 APRE=1 时,在每一次更新事件(UEV)时,才把预装在寄存器的内容传送到 影子寄存器。 自动重装载寄存器的各位描述如下: 136 图 3.7.1.4 寄存器 TIMx_ ARR 各位描述 最后,我们要介绍的寄存器是:状态寄存器(TIMx_SR)。该寄存器用来标记当前与定时 器相关的各种事件/中断是否发生。该寄存器的各位描述如下: 图 3.7.1.5 寄存器 TIMx_ SR 各位描述 关于这些位的详细描述,请参考《STM32 参考手册》第 245 页。 只要对以上几个寄存器进行简单的设置,我们就可以使用通用定时器了,并且可以产生中 断。 这一节,我们将使用定时器产生中断,然后在中断服务函数里面翻转 LED1 上的电瓶,来 指示定时器中断的产生。接下来我们以通用定时器 TIM3 为实例,来说明要经过哪些步骤,才 能达到这个要求,并产生中断。 1)TIM3 时钟使能。 这里我们通过 APB1ENR 的第 1 位来设置 TIM3 的时钟,因为 Stm32_Clock_Init 函数里面 把 APB1 的分频设置为 2 了,所以我们的 TIM3 时钟就是 APB1 时钟的 2 被,等于系统时钟。 2)设置 TIM3_ARR 和 TIM3_PSC 的值。 通过这两个寄存器,我们来设置自动重装的值,以及分频系数。这两个参数加上时钟频率 就决定了定时器的溢出时间。 3)设置 TIM3_DIER 允许更新中断。 因为我们要使用 TIM3 的更新中断,所以设置 DIER 的 UIE 位,并使能触发中断。 4)允许 TIM3 工作。 光配置好定时器还不行,没有开启定时器,照样不能用。我们在配置完后要开启定时器, 通过 TIM3_CR1 的 CEN 位来设置。 5)TIM3 中断分组设置。 在定时器配置完了之后,因为要产生中断,必不可少的要设置 NVIC 相关寄存器,以使能 TIM3 中断。 6)编写中断服务函数。 在最后,还是要编写定时器中断服务函数,通过该函数来处理定时器产生的相关中断。在 中断产生后,通过状态寄存器的值来判断此次产生的中断属于什么类型。然后执行相关的操作, 我们这里使用的是更新(溢出)中断,所以在状态寄存器 SR 的最低位。在处理完中断之后应 该向 TIM3_SR 的最低位写 0,来清除该中断标志。 通过以上几个步骤,我们就可以达到我们的目的了,使用通用定时器的的更新中断,来控 制外部 LED1 的翻转。 137 3.7.2 硬件设计 本节将通过 TIM3 的中断来控制 DS1 的亮灭,DS1 是直接连接到 PD2 上的,所以电路上不 需要任何改动。 3.7.3 软件设计 软件设计我们在之前的工程上面增加,首先在 HARDWARE 文件夹下新建 TIMER 的文件 夹。然后打开USER文件夹下的工程,新建一个 timer.c的文件和 timer.h的头文件,保存在TIMER 文件夹下,并将 TIMER 文件夹加入头文件包含路径。 我们在 timer.c 里输入如下代码: #include "timer.h" #include "led.h" //Mini STM32 开发板 //通用定时器 驱动代码 //正点原子@ALIENTEK //2010/6/1 //定时器 3 中断服务程序 //2ms 中断 1 次 void TIM3_IRQHandler(void) { if(TIM3->SR&0X0001)//溢出中断 { LED1=!LED1; } TIM3->SR&=~(1<<0);//清除中断标志位 } //通用定时器中断初始化 //这里始终选择为 APB1 的 2 倍,而 APB1 为 36M //arr:自动重装值。 //psc:时钟预分频数 //这里使用的是定时器 3! void Timerx_Init(u16 arr,u16 psc) { RCC->APB1ENR|=1<<1;//TIM3 时钟使能 TIM3->ARR=arr; //设定计数器自动重装值//刚好 1ms TIM3->PSC=psc; //预分频器 7200,得到 10Khz 的计数时钟 //这两个东东要同时设置才可以使用中断 TIM3->DIER|=1<<0; //允许更新中断 TIM3->DIER|=1<<6; //允许触发中断 138 TIM3->CR1|=0x01; //使能定时器 3 MY_NVIC_Init(1,3,TIM3_IRQChannel,2);//抢占 1,子优先级 3,组 2 } 该文件下包含一个中断服务函数和一个定时器初始化函数,中断服务函数比较简单,在每 次中断后,判断 TIM3 的中断类型,如果中断类型正确,则执行 LED1(DS1)的取反。 Timerx_Init 函数就是执行我们上面介绍的那 5 个步骤,使得 TIM3 开始工作,并开启中断。 该函数的 2 个参数用来设置 TIM3 的溢出时间。因为我们在 Stm32_Clock_Init 函数里面已经初 始化 APB1 的时钟为 2 分频,所以,TIM3 的时钟为 76M,再根据我们设计的 arr 和 psc 的值, 就可以计算中断时间了。计算公式如下: Tout=Tclk/psc*arr; 其中: Tclk:TIM3 的计数时钟(单位为 Khz)。 Tout:TIM3 溢出时间(单位为 ms)。 我们将 timer.c 文件保存,然后加入到 HARDWARE 组下。接下来,在 timer.h 文件里,我 们输入如下代码: #ifndef __TIMER_H #define __TIMER_H #include "sys.h" //Mini STM32 开发板 //定时器 驱动代码 //正点原子@ALIENTEK //2010/6/1 void Timerx_Init(u16 arr,u16 psc); #endif 关于这部分代码,我们不多说了。 最后,我们修改 main 函数如下: int main(void) { Stm32_Clock_Init(9); //系统时钟设置 delay_init(72); //延时初始化 uart_init(72,9600); //串口初始化 LED_Init(); //初始化与 LED 连接的硬件接口 Timerx_Init(5000,7199);//10Khz 的计数频率,计数到 5000 为 500ms while(1) { LED0=!LED0; delay_ms(200); } } 这里的代码和之前大同小异,此段代码对 TIM3 进行初始化之后,进入死循环等待 TIM3 139 溢出中断,当 TIM3_CNT 的值等于 TIM3_ARR 的值的时候,就会产生 TIM3 的更新中断,然 后在中断里面取反 LED1,TIM3_CNT 再从 0 开始计数。 3.7.4 下载与测试 在完成软件设计之后,我们将编译好的文件下载到 MiniSTM32 开发板上,观看其运行结果 是否与我们编写的一致。如果没有错误,我们将看 DS0 不停闪烁(每 400ms 闪烁一次),而 DS1 也是不停的闪烁,但是闪烁时间较 DS0 慢(1s 一次)。
本文档为【时钟】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_420570
暂无简介~
格式:pdf
大小:512KB
软件:PDF阅读器
页数:8
分类:互联网
上传时间:2011-07-25
浏览量:52