lzh电子论坛

欢迎来到lzh电子论坛:
如果您对电子技术感兴趣就加入我们吧!在这里互相交流互相学习!主要讨论的方向有:单片机,ARM,PCB板设计,FPGA,汇编,C/C++等方面。
-----lzh电子论坛
lzhbbs.top-me.com
lzh电子论坛

电子的道路是孤独的,要懂得左手温暖右手,要懂得把debug当作快乐去欣赏,去享受,那样你才会成功...

欢迎访问lzh电子论坛。可通过【谷歌,SOSO,搜狗】搜索“lzh电子论坛”直接进入论坛。点击了解论坛详细制度


    完成定时器任务(2014.2.16)

    分享
    avatar
    风逍遥辉
    管理员
    管理员

    帖子数 : 45
    威望 : 0
    注册日期 : 13-01-15
    年龄 : 23
    地点 : 湖北理工学院12级电信本一

    完成定时器任务(2014.2.16)

    帖子 由 风逍遥辉 于 2014-02-16, 12:46 pm

    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 之间的任意数值。
    3)4 个独立通道(TIMx_CH1~4),这些通道可以用来作为:
    A.输入捕获
    B.输出比较
    C.PWM 生成(边缘或中间对齐模式)
    D.单脉冲模式输出
    4)可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外
    一个定时器)的同步电路。
    5)如下事件发生时产生中断/DMA:
    A.更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
    B.触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
    C.输入捕获
    D.输出比较
    E.支持针对定位的增量(正交)编码器和霍尔传感器电路
    F.触发输入作为外部时钟或者按周期的电流管理

    2.搞清楚配置定时器的步骤
    以通用定时器 TIM3 为实例,来说明要经过哪些步骤,才能
    达到这个要求,并产生中断。这里我们就对每个步骤通过库函数的实现方式来描述。首先要提
    到的是,定时器相关的库函数主要集中在固件库文件 stm32f10x_tim.h 和 stm32f10x_tim.c 文件
    中。

    1)TIM3 时钟使能。
    TIM3 是挂载在 APB1 之下,所以我们通过 APB1 总线下的使能使能函数来使能 TIM3。调
    用的函数是:
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

    2)初始化定时器参数,设置自动重装值,分频系数,计数方式等。
    在库函数中,定时器的初始化参数是通过初始化函数 TIM_TimeBaseInit 实现的:
    voidTIM_TimeBaseInit(TIM_TypeDef*TIMx,
    TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
    第一个参数是确定是哪个定时器,这个比较容易理解。第二个参数是定时器初始化参数结
    构体指针,结构体类型为 TIM_TimeBaseInitTypeDef,下面我们看看这个结构体的定义:
    typedef struct
    {
    uint16_t TIM_Prescaler;  
    uint16_t TIM_CounterMode;   
    uint16_t TIM_Period;    
    uint16_t TIM_ClockDivision; 
    uint8_t TIM_RepetitionCounter; 
    } TIM_TimeBaseInitTypeDef;      
    这个结构体一共有 5 个成员变量,要说明的是,对于通用定时器只有前面四个参数有用,
    最后一个参数 TIM_RepetitionCounter 是高级定时器才有用的,这里不多解释。
    第一个参数 TIM_Prescaler 是用来设置分频系数的,刚才上面有讲解。
    第二个参数 TIM_CounterMode 是用来设置计数方式,上面讲解过,可以设置为向上计数,
    向下计数方式还有中央对齐计数方式, 比较常用的是向上计数模式 TIM_CounterMode_Up 和向
    下计数模式 TIM_CounterMode_Down。
    第三个参数是设置自动重载计数周期值,这在前面也已经讲解过。
    第四个参数是用来设置时钟分频因子。
    针对 TIM3 初始化范例代码格式:
    TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;
    TIM_TimeBaseStructure.TIM_Period = 5000;
    TIM_TimeBaseStructure.TIM_Prescaler =7199;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    3)设置 TIM3_DIER 允许更新中断。
    因为我们要使用 TIM3 的更新中断,寄存器的相应位便可使能更新中断。在库函数里面定
    时器中断使能是通过 TIM_ITConfig 函数来实现的:
    void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
    第一个参数是选择定时器号,这个容易理解,取值为 TIM1~TIM17。
    第二个参数非常关键,是用来指明我们使能的定时器中断的类型,定时器中断的类型有很
    多种,包括更新中断 TIM_IT_Update,触发中断 TIM_IT_Trigger,以及输入捕获中断等等。
    第三个参数就很简单了,就是失能还是使能。
    例如我们要使能 TIM3 的更新中断,格式为:
    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );

    4)TIM3 中断优先级设置。
    在定时器中断使能之后,因为要产生中断,必不可少的要设置 NVIC 相关寄存器,设置中
    断优先级。之前多次讲解到用 NVIC_Init 函数实现中断优先级的设置,这里就不重复讲解。

    5)允许 TIM3 工作,也就是使能 TIM3。
    光配置好定时器还不行,没有开启定时器,照样不能用。我们在配置完后要开启定时器,
    通过 TIM3_CR1 的 CEN 位来设置。 在固件库里面使能定时器的函数是通过 TIM_Cmd 函数来实
    现的:
    void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
    这个函数非常简单,比如我们要使能定时器 3,方法为:
    TIM_Cmd(TIM3, ENABLE);   //使能 TIMx 外设

    6)编写中断服务函数。
    在最后,还是要编写定时器中断服务函数,通过该函数来处理定时器产生的相关中断。在
    中断产生后,通过状态寄存器的值来判断此次产生的中断属于什么类型。然后执行相关的操作,
    我们这里使用的是更新(溢出)中断,所以在状态寄存器 SR 的最低位。在处理完中断之后应
    该向 TIM3_SR 的最低位写 0,来清除该中断标志。
    在固件库函数里面,用来读取中断状态寄存器的值判断中断类型的函数是:
    ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t)
    该函数的作用是,判断定时器 TIMx 的中断类型 TIM_IT 是否发生中断。比如,我们要判断定
    时器 3 是否发生更新(溢出)中断,方法为:
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){}
    固件库中清除中断标志位的函数是:
    void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
    该函数的作用是,清除定时器 TIMx 的中断 TIM_IT 标志位。使用起来非常简单,比如我们在
    TIM3 的溢出中断发生后,我们要清除中断标志位,方法是:
    TIM_ClearITPendingBit(TIM3, TIM_IT_Update   );
    这里需要说明一下,固件库还提供了两个函数用来判断定时器状态以及清除定时器状态标
    志位的函数 TIM_GetFlagStatus 和 TIM_ClearFlag,他们的作用和前面两个函数的作用类似。只
    是在 TIM_GetITStatus 函数中会先判断这种中断是否使能,使能了才去判断中断标志位,而
    TIM_GetFlagStatus 直接用来判断状态标志位。


    3.利用通用定时器来使LED闪烁周期1s
    http://pan.baidu.com/s/1gdtCGKj
    avatar
    Admin
    管理员
    管理员

    帖子数 : 869
    威望 : 15
    注册日期 : 12-11-23
    年龄 : 25

    回复: 完成定时器任务(2014.2.16)

    帖子 由 Admin 于 2014-02-17, 9:06 am

    很详细,不知道对影子寄存器是否了解!
    avatar
    风逍遥辉
    管理员
    管理员

    帖子数 : 45
    威望 : 0
    注册日期 : 13-01-15
    年龄 : 23
    地点 : 湖北理工学院12级电信本一

    回复: 完成定时器任务(2014.2.16)

    帖子 由 风逍遥辉 于 2014-02-17, 9:49 am

    Admin 写道::很详细,不知道对影子寄存器是否了解!
    自动重装载寄存器(TIMx_ARR),该寄存器在物理上实际对应着 2 个寄存器。
    一个是程序员可以直接操作的,另外一个是程序员看不到的,这个看不到的寄存器在《STM32
    参考手册》里面被叫做影子寄存器。事实上真正起作用的是影子寄存器。根据 TIMx_CR1 寄存
    器中 APRE 位的设置:APRE=0 时,预装载寄存器的内容可以随时传送到影子寄存器,此时 2
    者是连通的;而 APRE=1 时,在每一次更新事件(UEV)时,才把预装在寄存器的内容传送到
    影子寄存器。
    avatar
    Admin
    管理员
    管理员

    帖子数 : 869
    威望 : 15
    注册日期 : 12-11-23
    年龄 : 25

    回复: 完成定时器任务(2014.2.16)

    帖子 由 Admin 于 2014-02-23, 5:13 pm

    产生pwm波试试,我以前试的时候,那个分頻系数不同产生相同占空比和周期的波,效果不同。要不测试几下搞几个图上来看看
    avatar
    aiMM
    中级会员
    中级会员

    帖子数 : 46
    威望 : 0
    注册日期 : 13-05-06

    回复: 完成定时器任务(2014.2.16)

    帖子 由 aiMM 于 2014-03-11, 6:12 pm

    STM32的定时器这么复杂啊,好难啊,想想学不学呢 Mad
    avatar
    Admin
    管理员
    管理员

    帖子数 : 869
    威望 : 15
    注册日期 : 12-11-23
    年龄 : 25

    回复: 完成定时器任务(2014.2.16)

    帖子 由 Admin 于 2014-03-11, 6:21 pm

    楼上,有点志气行不……
    avatar
    Feelplus
    管理员
    管理员

    帖子数 : 70
    威望 : 3
    注册日期 : 12-11-24

    回复: 完成定时器任务(2014.2.16)

    帖子 由 Feelplus 于 2014-03-12, 12:33 am

    aiMM 写道::STM32的定时器这么复杂啊,好难啊,想想学不学呢 Mad

    你说啥东西不都是一步步深入呢~高数和小学数学比怎么样,难度大了但是应用更广了呢


    _________________
    while(1)
    {
       I will
    }

      目前的日期/时间是2018-07-22, 3:24 am