STM32-基本定时器TIM6-TIM7基本定时功能

1. stm32的timer简介
stm32中一共有11个定时器,其中2个高级控制定时器,4个普通定时器和2个基本定时器,以及2个看门狗定时器和1个系统嘀嗒定时器。其中系统嘀嗒定时器是前文中所描述的systick,看门狗定时器以后再详细研究。今天主要是研究剩下的8个定时器。
定时器 计数器分辨率 计数器类型 预分频系数 产生dma请求 捕获/比较通道 互补输出
tim1
tim8 16位 向上,向下,向上/向下 1-65536之间的任意数 可以 4 有
tim2
tim3
tim4
tim5 16位 向上,向下,向上/向下 1-65536之间的任意数 可以 4 没有
tim6
tim7 16位 向上 1-65536之间的任意数 可以 0 没有
其中tim1和tim8是能够产生3对pwm互补输出的高级登时其,常用于三相电机的驱动,时钟由apb2的输出产生。tim2-tim5是普通定时器,tim6和tim7是基本定时器,其时钟由apb1输出产生。由于stm32的timer功能太复杂了,所以只能一点一点的学习。因此今天就从最简单的开始学习起,也就是tim2-tim5普通定时器的定时功能。
2基本定时器tim6-tim7
2.1 时钟基本特征
基本定时器tim6和tim7各包含一个16位自动装载计数器,由各自的可编程预分频器驱动。它们可以作为通用定时器提供时间基准,特别地可以为数模转换器(dac) 提供时钟。实际上,它们在芯片内部直接连接到dac并通过触发输出直接驱动dac。这2个定时器是互相独立的,不共享任何资源。
2.2 tim6-7主要特征
tim6和tim7定时器的主要功能包括:
● 16位自动重装载累加计数器
● 16位可编程( 可实时修改)预分频器,用于对输入的时钟按系数为1~65536 之间的任意数值
分频
● 触发dac的同步电路
● 在更新事件(计数器溢出)时产生中断/dma 请求
图144 基本定时器框图
2.3 计数器模式
tim6-tim7可以由向上计数。向上计数模式中,计数器从0计数到自动加载值(timx_arr计数器内容),然后重新从0开始计数并且产生一个计数器溢出事件。
2.4 tim6-tim7基本定时器的寄存器
1.tim6和tim7控制寄存器1(timx_cr1)
arpe :自动重装载预装载使能 (auto-reload preload enable) 0:timx_arr 寄存器没有缓冲 1:timx_arr 寄存器具有缓 冲
urs:更新请求源 (update request source)
该位由软件设置和清除,以选择uev事件的请求源。
0:如果使能了中断或dma,以下任一事件可以产生一个更新中断或dma请求:
- 计数器上溢或下溢
- 设置ug位
- 通过从模式控制器产生的更新
1:如果使能了中断或dma,只有计数器上溢或下溢可以产生更新中断或dma请求。
udis:禁止更新 (update disable)
该位由软件设置和清除,以使能或禁止uev事件的产生。
0:uev使能。更新事件(uev) 可以由下列事件产生:
- 计数器上溢或下溢
- 设置ug位
- 通过从模式控制器产生的更新
产生更新事件后,带缓冲的寄存器被加载为预加载数值。
1 :禁止uev。不产生更新事件(uev) ,影子寄存器保持它的内容(arr 、psc)。但是如果设置
了ug位或从模式控制器产生了一个硬件复位,则计数器和预分频器将被重新初始化。
cen:计数器使能 (counter enable)
0:关闭计数器
1:使能计数器
2.tim6和tim7控制寄存器2(timx_cr2)
3. tim6和tim7 dma/中断使能寄存器(timx_dier)
ude:更新dma请求使能
0:禁止更新dma请求
1:使能更新dma请求
uie:更新中断使能
0:禁止更新中断
1:使能更新中断
4 。 tim6和tim7状态寄存器(timx_sr)
uif:更新中断标志 (update interrupt flag) 硬件在更新中断时设置该位,它由软件清除。
0:没有产生更新。
1:产生了更新中断。下述情况下由硬件设置该位:
– 计数器产生上溢或下溢并且timx_cr1 中的udis=0;
– 如果timx_cr1 中的urs=0并且udis=0,当使用timx_egr 寄存器的ug位重新初始化计数器cnt时。
5. tim6和tim7事件产生寄存器(timx_egr)
ug:产生更新事件 (update generation) 该位由软件设置,由硬件自动清除。
0:无作用
1 :重新初始化定时器的计数器并产生对寄存器的更新。注意:预分频器也被清除( 但预分频系数不变)。
6. tim6和tim7计数器(timx_cnt)
cnt[15:0]:计数器数值 (counter value)
7 .tim6和tim7预分频器(timx_psc)
psc[15:0] :预分频器数值 (prescaler value) 计数器的时钟频率ck_cnt 等于f ck_psc/(psc[15:0]+1) 。
在每一次更新事件时,psc的数值被传送到实际的预分频寄存器中。
8 .tim6和tim7自动重装载寄存器(timx_arr)
arr[15:0] :自动重装载数值 (prescaler value) arr的数值将传送到实际的自动重装载寄存器中。
如果自动重装载数值为0,则计数器停止。
2.5 编程步骤
1. 配置优先级;
2. 使能时钟
3. 配置gpio;
4. 配置time;
5.使能计数器;
6.开中断;
7.清除标志位;
具体配置如下:
(1) nvic_configuration(void);配置优先级
(2) void rcc_apb2periphclockcmd(uint32_t rcc_apb2periph, functionalstate newstate)使能时钟
(3) void gpio_init(gpio_typedef* gpiox, gpio_inittypedef* gpio_initstruct);配置gpio
(4) tim_configuration (void);配置tim6/tim7
(5) tim_cmd(tim7, enable);使能定时器
(6) tim_itconfig(tim7,tim_it_update,enable);使能中断
(7) tim_clearflag(tim7, tim_flag_update);清除标志位
步骤(4)中的预分频系数用来确定timx所使用的时钟频率,具体计算方法为:ck_int/(tim_perscaler+1)。ck_int是内部时钟源的频率,是根据2.1中所描述的apb1的倍频器送出的时钟,tim_perscaler是用户设定的预分频系数,其值范围是从0 – 65535。
步骤(4)中的时钟分割定义的是在定时器时钟频率(ck_int)与数字滤波器
(etr,tix)使用的采样频率之间的分频比例。tim_clockdivision的参数如下表:
tim_clockdivision 描述 二进制值
tim_ckd_div1 tdts = tck_tim 0x00
tim_ckd_div2 tdts = 2 * tck_tim 0x01
tim_ckd_div4 tdts = 4 * tck_tim 0x10
步骤(4)中需要禁止使用预装载缓冲器。当预装载缓冲器被禁止时,写入自动装入的值(timx_arr)的数值会直接传送到对应的影子寄存器;如果使能预加载寄存器,则写入arr的数值会在更新事件时,才会从预加载寄存器传送到对应的影子寄存器。
arm中,有的逻辑寄存器在物理上对应2个寄存器,一个是程序员可以写入或读出的寄存器,称为preload register(预装载寄存器),另一个是程序员看不见的、但在操作中真正起作用的寄存器,称为shadow register(影子寄存器);设计preload register和shadow register的好处是,所有真正需要起作用的寄存器(shadow register)可以在同一个时间(发生更新事件时)被更新为所对应的preload register的内容,这样可以保证多个通道的操作能够准确地同步。如果没有shadow register,或者preload register和shadow register是直通的,即软件更新preload register时,同时更新了shadow register,因为软件不可能在一个相同的时刻同时更新多个寄存器,结果造成多个通道的时序不能同步,如果再加上其它因素(例如中断),多个通道的时序关系有可能是不可预知的。
3. 程序源代码
本例实现的是通过tim7的定时功能,使得led灯按照1s的时间间隔来闪烁
原理图:
/*
* 文件名: main.c
* 内容简述:
* 从0开始创建一个工程,通过按键1触发中断1实现灯1的闪亮
* 再通过按键2触发中断抢占 中断1实现小灯2的闪亮
*
* 2个led指示灯,对应的gpio为 : pc3 pc1
* 输出为0点亮led
* 输出为1关闭led
* 2个按键 对应 pb7 pa11
*/
#include “stm32f10x.h”
/* 延时函数 */
void delay(__io uint32_t ncount)
{
//__io 就是volatile,加上这个后可以避免延时函数被编译器优化掉
for(;ncount != 0; ncount--);
}
/* gpio配置函数 */
void gpio_configuration(void)
{
/*定义2个结构体变量 */
gpio_inittypedef gpio_initstructure;
/*开启gpiob,gpioc ,复用口时钟的 时钟 */
rcc_apb2periphclockcmd(rcc_apb2periph_gpioc, enable);
rcc_apb1periphclockcmd(rcc_apb1periph_tim7, enable);
/*给gpio_initstructure.gpio_pin gpio_initstructure.gpio_mode gpio_initstructure.gpio_speed付初始值*/
gpio_initstructure.gpio_pin = gpio_pin_3;
// 将连接led3的gpio设置为推挽输出
gpio_initstructure.gpio_mode = gpio_mode_out_pp;
//设置为10mhz的速度
gpio_initstructure.gpio_speed = gpio_speed_50mhz;
//初始化gpioc
gpio_init(gpioc, &gpio_initstructure);
}
/********配置优先级*****************/
void nvic_configuration(void)
{
//定义一个结构体
nvic_inittypedef nvic_initstructure;
//设置优先级组
nvic_prioritygroupconfig(nvic_prioritygroup_0) ;
//设置 tim7线
nvic_initstructure.nvic_irqchannel =tim7_irqn;
//使能优先级
nvic_initstructure.nvic_irqchannelcmd = enable;
//配置抢断优先级
nvic_initstructure.nvic_irqchannelpreemptionpriority =0;
//配置响应优先级
nvic_initstructure.nvic_irqchannelsubpriority =0;
nvic_init(&nvic_initstructure);
//设置存入寄存器
nvic_setvectortable (nvic_vecttab_flash ,0x0);
}
//*****定时器初始化*********
void tim_configuration (void)
{
tim_timebaseinittypedef tim_timebasestructure;
// tim_cmd(tim7, disable);
//预分频系数为36000-1,这样计数器时钟为72mhz/36000 = 2khz
tim_timebasestructure.tim_prescaler = 36000 - 1;
//设置时钟分割 tim_ckd_div1=0x0000,不分割
tim_timebasestructure.tim_clockdivision = 0;
//设置计数器模式为向上计数模式
tim_timebasestructure.tim_countermode = tim_countermode_up ;
//设置计数溢出大小,每计2000个数就产生一个更新事件
tim_timebasestructure.tim_period = 2000 - 1;
tim_timebasestructure.tim_repetitioncounter = 0;
//将配置应用到tim7中
tim_timebaseinit(tim7,&tim_timebasestructure);
tim_updaterequestconfig( tim7, tim_updatesource_regular);
//使能计数器
tim_cmd(tim7, enable);
//使能中断
tim_itconfig(tim7,tim_it_update,enable);
//清除标志位
// tim_clearflag(tim7, tim_flag_update);
}
//*****************************
//主函数
int main(void)
{
/*
这个函数是st库中的函数,函数实体在
libraries\cmsis\core\cm3\system_stm32f10x.c
配置内部flash接口,初始化pll,配置系统时钟的频率
系统时钟缺省配置为72mhz
*/
gpio_configuration ();
nvic_configuration ();
tim_configuration ();
while(1)
{
}
}
it.c中的程序
void tim7_irqhandler(void)
{
//检测是否发生溢出更新事件
if(tim_getitstatus(tim7, tim_it_update)== set)
{
gpioc-》odr ^= gpio_pin_3;
tim_clearitpendingbit(tim7 , tim_flag_update);
}
}
编程心得:
1.注意应用定时器是要开的使能 tim_cmd(tim7, enable)-计数器使能 tim_itconfig (tim7,tim_it_update,enable)-中断使能 rcc_apb1periphclockcmd (rcc_apb1periph_tim7,enable)-时钟
2.进入中断后一定要记得清楚标志位 tim_clearitpendingbit(tim7 , tim_flag_update);

iphone8什么时候上市?iphone8渲染图流出,这或许才是你想要的iphone8
O-Free无线耳机评测 寻找耳机和随行翻译功能亮眼
奥地利微电子推出非接触式霍尔传感器IC AS5013
Google Pixel 2再爆最新消息:全面屏+骁龙836全球首发,怒怼三星S8
王刚博士讲述智能家居的发展历程
STM32-基本定时器TIM6-TIM7基本定时功能
网友华为Mate9出现问题!除了手机还有这些问题!
西安:2020年集成电路圆片产量增长43.7%,锂离子电池产量增长17.4%
光纤传输的优点与缺点_光纤传输原理是什么
如何使用AI、机器人和大数据增加FCR
大众和福特插手LG和SKI电池纠纷案,SKI或将扭转局势
千锤百炼 增强型灵云语音识别让车载语音交互更流畅
BGP、EBGP、IBGP、IGP还没搞清楚?
多媒体信息发布系统的传输设备种类及介绍
食用农产品合格证智能机的应用及性能
社交机器人越来越受到消费者的青睐 智能化程度越来越高
变频器故障代码大全
2020年规模商用5G已成业界共识今年将是5G发展的关键一年
是否可以用AI视觉技术减少公司人力投入?
全球十大传感器厂商盘点