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

1.定时器概念

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

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

第五篇,STM32系统定时器和通用定时器编程_第1张图片

 

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

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

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

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

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

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

第五篇,STM32系统定时器和通用定时器编程_第2张图片

 第五篇,STM32系统定时器和通用定时器编程_第3张图片

 

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

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属于基本定时器。

第五篇,STM32系统定时器和通用定时器编程_第4张图片

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

第五篇,STM32系统定时器和通用定时器编程_第5张图片

 

三种计数模式:

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

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

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

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

第五篇,STM32系统定时器和通用定时器编程_第6张图片

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

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

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

第五篇,STM32系统定时器和通用定时器编程_第7张图片

 

(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

你可能感兴趣的:(STM32编程,单片机,嵌入式硬件)