• stm32定时器之简单封装


    目录

    一、定时器的封装与概念

    二、时钟结构框图

     2.1、解析

    三、初始化TIM2

    3.1、中断向量嵌套的封装与概念

    3.2、定时器初始化


    一、定时器的封装与概念

    1. /******************************************************************************
    2. 定时器初始化函数
    3. *******************************************************************************/
    4. void TIMx_Init(st_u32 RCC_APB1Periph,st_u16 per,st_u16 psc,st_u16 clk_div,st_u16 Count_mode,TIM_TypeDef* TIMx)
    5. {
    6. /*uint32_t RCC_APB1Periph = RCC_APB1Periph_TIM2|RCC_APB1Periph_TIM3|RCC_APB1Periph_TIM4
    7. |RCC_APB1Periph_TIM5|RCC_APB1Periph_TIM6|RCC_APB1Periph_TIM7;*/
    8. // 定时器结构体
    9. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    10. // 预分配值
    11. st_u16 PreValue=0;
    12. //使能定时器时钟 TIM5
    13. RCC_APB1PeriphClockCmd(RCC_APB1Periph, ENABLE);
    14. PreValue =(st_u16)psc;
    15. // 设置自动重装载寄存器周期的值 计数到5000为500ms
    16. // 计数一次的时间1/(TIMxCLK/(PSC+1))=1/1000
    17. // 定时器周期,实际就是设定自动重载寄存器的值,在事件生成时更新到影子寄存器。可设置范围为 0 至 65535。
    18. TIM_TimeBaseInitStructure.TIM_Period = per;
    19. // 设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率
    20. // 定时器预分频器设置,时钟源经该预分频器才是定时器时钟,它设定
    21. // TIMx_PSC 寄存器的值。可设置范围为 0 至 65535,实现 1 至 65536 分频。
    22. TIM_TimeBaseInitStructure.TIM_Prescaler = 0;
    23. // 时钟分割 设置时钟分割:TDTS = Tck_tim
    24. // 时钟分频,设置定时器时钟 CK_INT 频率与数字滤波器采样时钟
    25. // 频率分频比,基本定时器没有此功能,不用设置。
    26. TIM_TimeBaseInitStructure.TIM_ClockDivision =clk_div;
    27. // 计数模式 TIM向上计数模式
    28. // 可是在为向上计数(TIM_CounterMode_Up)、向下计数(TIM_CounterMode_Down)以及三种中心对齐模式。TIM_CounterMode_CenterAligned1 TIM_CounterMode_CenterAligned2 TIM_CounterMode_CenterAligne3
    29. // 基本定时器只能是向上计数,即 TIMx_CNT 只能从 0 开始递增,并且无需初始化。
    30. TIM_TimeBaseInitStructure.TIM_CounterMode = Count_mode;
    31. // 及时装入PrescalerValue的值
    32. TIM_PrescalerConfig(TIM2, PreValue, TIM_PSCReloadMode_Immediate);
    33. // TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    34. TIM_TimeBaseInit(TIMx, &TIM_TimeBaseInitStructure);
    35. //TIM_Cmd(TIMx, ENABLE);
    36. }

    二、时钟结构框图

     2.1、解析

    • STM32总共有8个定时器,分别是2个高级定时器(TIM1、TIM8),挂在APB2上。
    • 4个通用定时器(TIM2、TIM3、TIM4、TIM5)和2个基本定时器(TIM5、TIM6)挂载在APB1上。
    • 定时器时钟经过psc分频后得到驱动计数器计数的计数器时钟(CK_CNT)
    • CK_CNT=TIMxCLK/(PSC+1).
    • 计数器 CNT 是一个 16 位的计数器,只能往上计数,最大计数值为 65535。当计数达
    • 到自动重装载寄存器的时候产生更新事件,并清零从头开始计数.
    • 自动重装载寄存器 ARR 是一个 16 位的寄存器,这里面装着计数器能计数的最大数
    • 值。当计数到这个值的时候,如果使能了中断的话,定时器就产生溢出中断.
    • 定时器的定时时间等于计数器的中断周期乘以中断的次数。
    • 计数器在 CK_CNT 的驱动下,计一个数的时间则是 CK_CLK 的倒数,等于:1/(TIMxCLK/(PSC+1))。
    • 产生一次中断的时间则等于:1/(CK_CLK * ARR)。
    • 中断服务程序中设置一个变量TIME,记录中断次数,则定时时间:1/CK_CLK * (ARR+1)*time。

    三、初始化TIM2

    3.1、中断向量嵌套的封装与概念

    • .ARM cortex_m3 内核支持 256 个中断(16 个内核+240 外部)和可编程 256 级中断优先级 的设置,与其相关的中断控制和中断优先级控制寄存器(NVIC、SYSTICK 等)也都属于 cortex_m3 内核的部分。
    • STM32 采用了 cortex_m3 内核,所以这部分仍旧保留使用,但 STM32 并没有使用 cortex_m3 内核全部的东西(如内存保护单元 MPU 等),因此它的 NVIC 是 cortex_m3 内核的 NVIC 的子集。
    • STM32 目前支持的中断共为 84 个(16 个内核+68 个外部),和 16 级可编程中断优先级
    • 的设置。
    • STM32 可以支持的 68 个外部中断通道,已经固定的分配给相应的外部设备。每个中断
    • 通道都具备自己的中断优先级控制字节 PRI_n(8 位,但在 STM32 中只使用 4 位,高 4 位有 效)。
    • 4bit 的中断优先级控制位分成 2 组从高位开始,前面是定义抢先式优 先级的位,后面用于定义子优先级。

    1. /*******************************************************************************
    2. * 函 数 名 : NVIC_InitConfig
    3. * 函数功能 : 中断通道初始化函数
    4. * 输 入 : NVIC_IRQl 中断通道
    5. NVIC_IRQlPP 抢占式优先级
    6. NVIC_IRQlSP 子优先级
    7. * 输 出 : 无
    8. NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。
    9. 中断优先级寄存器 NVIC_IPRx,用来配置外部中断的优先级,IPR 宽度为 8bit,原则上每个外部中断可配置的优先级为 0~255,数值越小,优先级越高。stm32f103只使用高四位
    10. @arg NVIC_PriorityGroup_0: 0bit for 抢占优先级
    11. 4 bits for 子优先级
    12. @arg NVIC_PriorityGroup_1: 1 bit for 抢占优先级
    13. 3 bits for 子优先级
    14. .................................................
    15. 为了方便管理我们把中断服务函数统一写在 stm32f10x_it.c 这个库文件中。
    16. *******************************************************************************/
    17. void NVIC_InitConfig(uint8_t NVIC_IRQl,uint8_t NVIC_IRQlPP,uint8_t NVIC_IRQlSP)
    18. {
    19. NVIC_InitTypeDef NVIC_InitStructure;
    20. // 中断通道 中断源
    21. NVIC_InitStructure.NVIC_IRQChannel = NVIC_IRQl;
    22. // 抢占式优先级 具体的值要根据优先级分组来确定
    23. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=NVIC_IRQlPP ;
    24. // 中断通道子优先级
    25. NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_IRQlSP;
    26. // IRQ通道使能
    27. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    28. // 根据指定的参数初始化VIC寄存器
    29. NVIC_Init(&NVIC_InitStructure);
    30. }

    3.2、定时器初始化

    1. void APB1Psc_Config(void)
    2. {
    3. // 如果APB1不分频,则定时器时钟TIMxCLK=HCLK,如果APB1分频>2,则TIMxCLK=2*HCLK
    4. // 计数器频率CNTCLK=TIMxCLK/(psc+1) =18/6=3M 设分频系数6-1
    5. // 计数器计数一次的时间 1/CNTCLK=1/3000 ms
    6. // 1/CK_CLK * ARR=1ms ==> ARR= 3000
    7. // HCLK/8 = 9 TIMxCLK=18
    8. #ifdef DEBUG_APB1
    9. RCC_PCLK1Config(RCC_HCLK_Div4);
    10. #else
    11. RCC_PCLK1Config(RCC_HCLK_Div8);
    12. #endif
    13. TIM2_Init();
    14. }
    15. #define DEBUG_1ms
    16. void TIM2_Init(void)
    17. {
    18. // 中断源 抢占式优先级0 响应式优先级3
    19. NVIC_InitConfig(TIM2_IRQn,1,2);
    20. #ifdef DEBUG_1ms
    21. // 配置一个1ms中断定时器
    22. // 定时器配置 1、使能定时器 2、arr 3、psc 4、向上计数模式 5、定时器2
    23. TIMx_Init(RCC_APB1Periph_TIM2,3000, 6-1,0,TIM_CounterMode_Up,TIM2);
    24. #endif
    25. // TIM2中断触发 当计数器的值从0计数到arr是会触发更新中断(TIM_IT_Update)
    26. TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    27. TIM_Cmd(TIM2, ENABLE);
    28. }

  • 相关阅读:
    Java练习题-输出二维数组对角线元素和
    erlang练习题(二)
    燃烧化学平衡判据
    tiup cluster enable
    在windows Server安装Let‘s Encrypt的SSL证书
    今日睡眠质量记录79分
    物联网开发自学的一些建议
    [LC 总结] 前缀和(Prefix Sum)总结& 10 道相关练习题
    Swift新async/await并发中利用Task防止指定代码片段执行的数据竞争(Data Race)问题
    19、架构-虚拟化容器
  • 原文地址:https://blog.csdn.net/RONG_YAO/article/details/126188950