• 第五篇,STM32系统定时器和通用定时器编程


    1.定时器概念

    定时器本质上是一个计数器,从某个值开始计数,当计数值达到某个值时定时时间到。定时的时间由计数的范围(初始计数值)和计数的快慢(当前计数值)来决定。 

    用定时器做延时或者心跳时钟,主要步骤包括启动,确定参考时钟频率,确定初始计数值,查询超时标志,如下图所示。

     

    ———————————————————————————————————————————

    2.systick ---------------------- 系统定时器

    systick是一个简单定时器,属于ARM核,常用于精准延时,也可以用作系统心跳时钟。

    (1)cortex-M4内核的系统定时器(参考权威指南9.5节)

    systick是一个向下计数,24位(0xffffff),具有自动重装载功能(在一个定时时间结束后,自动写入一个初始计数值,不需要开发人员在重新初始化赋值)的简单定时器。时钟源由外部提供,可以选择8分频的AHB时钟(21MHz)或者HCLK(168MHz)。

    Systick寄存器组织结构如下,通常需要配置的寄存器为控制和状态寄存器(CTRL),重装载值寄存器(LOAD),当前值寄存器(VAL)这三个。

     

     

    ———————————————————————————————————————————

    3.使用systick实现精准延时

    第一步,选择参考时钟(21MHzAHB时钟或者HLCK时钟);

    第二步,设置初始计数值来决定定时器周期(延时时间);

    第三步,使能定时器;

    第四步,查询超时的标志等待延时时间到。

    ———————————————————————————————————————————

    4.Sydtick定时器代码实现

    void delay_init(void)

    {
             //选择21MAHB时钟作为时钟源

    //SYSTICK控制和状态寄存器第二位置0

    //SysTick->CTRL &= ~(0x01<<2);   

    //SysTick->CTRL &= ~SysTick_CTRL_CLKSOURCE_Msk;

             //库函数写法

             SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);

    }

    //选择21MHz, 1um=21, 1ms=21000

    //毫秒延时 1ms = 21000  n<798 ------ (2^24)/21000

      

    void delay_ms(unsigned int nms)

    {
             //计算初始值放入初始值寄存器,从初始值开始计算

             SysTick->LOAD = 21000*nms-1;

             SysTick->VAL = 0;//当前计数值为0

            

             //启动systick开始计时

             SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;

            

             //等待计数值为0,控制寄存器的16位变1

             while(!(SysTick->CTRL&SysTick_CTRL_COUNTFLAG_Msk));

            

             //关闭systick

             SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;

    }

    ——————————————————————————————————————————————————————————————————————————————————————5.通用定时器

    (1)介绍

        定时器的基本功能是定时,通用定时器属于外设,通常和其他硬件配合使用,比如周期性采集传感器数据,周期性ADC转换,周期性上报数据,将通用定时器和GPIO结合产生更多的功能(PWM,脉冲检测.....)。

        stm32f407有14个外设定时器,TIM2~TIM5 TIM9~TIM14属于通用定时器,TIM1和TIM8属于高级定时器,TIM6和TIM7属于基本定时器。

    以TIM2~TIM5为例,了解通用定时器的使用

     

    三种计数模式:

    向上计数(递增)     0 ~ 初始计数值

    向下计数(递减)     初始计数值 ~ 0

    双向计数(递增/递减)     初始计数值 ~ 0 ~ 初始计数值

    通用定时器的原始时钟频率取决于所在总线和总线的分频系数

    ———————————————————————————————————————————

    6.定时器(TIM2)的库函数编程实现

        在工程中加入定时器的库函数源码

     

    (1)开启定时器2的时钟

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    (2)初始化定时器

    void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); 参数:     TIMx - 哪个定时器     TIM_TimeBaseInitStruct - 初始化结构      typedef struct {   uint16_t TIM_Prescaler;         /*!< 预分频系数 0x0000 and 0xFFFF */   uint16_t TIM_CounterMode;       /*!< 计数模式 @ref TIM_Counter_Mode */   uint32_t TIM_Period;            /*!< 初始计数值 0x0000 and 0xFFFF.  */    uint16_t TIM_ClockDivision;     /*!< 时钟因子 @ref TIM_Clock_Division_CKD */   uint8_t TIM_RepetitionCounter;  /*!< 高级定时器功能,忽略 */ } TIM_TimeBaseInitTypeDef;     

    (3)初始化NVIC

    NVIC_Init(...);

    (4)开启定时器中断使能

    void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState); 参数:     TIMx - 哪个定时器     TIM_IT - 哪个中断 TIM_IT_Update     NewState - 使能/禁止 ENABLE

    (5)实现定时器中断处理函数

    void TIM2_IRQHandler(void) {     if(TIM_GetITStatus(TIM2, TIM_IT_Update)==SET){         //......                  //清除中断标志         TIM_ClearITPendingBit(TIM2, TIM_IT_Update);     } }

    (6)启动定时器

    TIM_Cmd(TIM2,ENABLE);
    ————————————————
    版权声明:本文为CSDN博主「车水码浓」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/weixin_44651073/article/details/125576286

  • 相关阅读:
    R语言STAN贝叶斯线性回归模型分析气候变化影响北半球海冰范围和可视化检查模型收敛性...
    信息学奥赛一本通-编程启蒙3219:练36.2 不定方程求解
    一个 nginx 通过不同域名映射多个前端项目
    如何在 R 中创建线性模型预测区间 并可视化
    中央党校出版社元宇宙图书编委高泽龙在元宇宙100分第24期做分享
    tkinter上传文件
    MySQL 事务隔离级别 理论+实战分析
    数仓开发之DWD层(四)
    数据库 | VirusCircBase:环状 RNA病毒数据库
    LeetCode 11. 盛最多水的容器
  • 原文地址:https://blog.csdn.net/weixin_44651073/article/details/125582108