当前位置:网站首页>stm32定时器之简单封装

stm32定时器之简单封装

2022-08-09 06:42:00 旭日初扬

目录

一、定时器的封装与概念

二、时钟结构框图

 2.1、解析

三、初始化TIM2

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

3.2、定时器初始化


一、定时器的封装与概念

/******************************************************************************
                                 定时器初始化函数


*******************************************************************************/
void TIMx_Init(st_u32 RCC_APB1Periph,st_u16 per,st_u16 psc,st_u16 clk_div,st_u16 Count_mode,TIM_TypeDef* TIMx)
{
	/*uint32_t RCC_APB1Periph = RCC_APB1Periph_TIM2|RCC_APB1Periph_TIM3|RCC_APB1Periph_TIM4
	                          |RCC_APB1Periph_TIM5|RCC_APB1Periph_TIM6|RCC_APB1Periph_TIM7;*/
	//  定时器结构体
  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	
	//  预分配值
	st_u16 PreValue=0;
	
	//使能定时器时钟 TIM5
  RCC_APB1PeriphClockCmd(RCC_APB1Periph, ENABLE);
	
	PreValue =(st_u16)psc; 
	
  //  设置自动重装载寄存器周期的值	 计数到5000为500ms
  //  计数一次的时间1/(TIMxCLK/(PSC+1))=1/1000
	//  定时器周期,实际就是设定自动重载寄存器的值,在事件生成时更新到影子寄存器。可设置范围为 0 至 65535。

	TIM_TimeBaseInitStructure.TIM_Period = per;
	
	//  设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
	//  定时器预分频器设置,时钟源经该预分频器才是定时器时钟,它设定
  //  TIMx_PSC 寄存器的值。可设置范围为 0 至 65535,实现 1 至 65536 分频。
	TIM_TimeBaseInitStructure.TIM_Prescaler = 0;
	
	//  时钟分割    设置时钟分割:TDTS = Tck_tim
	//  时钟分频,设置定时器时钟 CK_INT 频率与数字滤波器采样时钟
  //  频率分频比,基本定时器没有此功能,不用设置。
	TIM_TimeBaseInitStructure.TIM_ClockDivision =clk_div; 
	
	//  计数模式  TIM向上计数模式
	//  可是在为向上计数(TIM_CounterMode_Up)、向下计数(TIM_CounterMode_Down)以及三种中心对齐模式。TIM_CounterMode_CenterAligned1   TIM_CounterMode_CenterAligned2 TIM_CounterMode_CenterAligne3
  //  基本定时器只能是向上计数,即 TIMx_CNT 只能从 0 开始递增,并且无需初始化。
	TIM_TimeBaseInitStructure.TIM_CounterMode = Count_mode;  
	
	 //  及时装入PrescalerValue的值
	TIM_PrescalerConfig(TIM2, PreValue, TIM_PSCReloadMode_Immediate);
	// TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);    	
		
	TIM_TimeBaseInit(TIMx, &TIM_TimeBaseInitStructure);
	//TIM_Cmd(TIMx, ENABLE);
}

二、时钟结构框图

 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 组从高位开始,前面是定义抢先式优 先级的位,后面用于定义子优先级。

/*******************************************************************************
* 函 数 名         : NVIC_InitConfig
                     
* 函数功能		     : 中断通道初始化函数
* 输    入         : NVIC_IRQl    中断通道
                     NVIC_IRQlPP  抢占式优先级
                     NVIC_IRQlSP  子优先级
		                 
* 输    出         : 无
NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。

中断优先级寄存器 NVIC_IPRx,用来配置外部中断的优先级,IPR 宽度为 8bit,原则上每个外部中断可配置的优先级为 0~255,数值越小,优先级越高。stm32f103只使用高四位

@arg NVIC_PriorityGroup_0:  0bit for 抢占优先级
                            4 bits for 子优先级
@arg NVIC_PriorityGroup_1:  1 bit for 抢占优先级
                            3 bits for 子优先级
.................................................

为了方便管理我们把中断服务函数统一写在 stm32f10x_it.c 这个库文件中。
*******************************************************************************/

void NVIC_InitConfig(uint8_t NVIC_IRQl,uint8_t NVIC_IRQlPP,uint8_t NVIC_IRQlSP)
	{
  	
	NVIC_InitTypeDef NVIC_InitStructure;
	//  中断通道   中断源
  NVIC_InitStructure.NVIC_IRQChannel = NVIC_IRQl;
		
	//  抢占式优先级   具体的值要根据优先级分组来确定
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=NVIC_IRQlPP ;
		
	//  中断通道子优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_IRQlSP;
		
  //  IRQ通道使能		
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;		
		
  //  根据指定的参数初始化VIC寄存器		
	NVIC_Init(&NVIC_InitStructure);	
}
	

3.2、定时器初始化

void APB1Psc_Config(void)
{
  
	//  如果APB1不分频,则定时器时钟TIMxCLK=HCLK,如果APB1分频>2,则TIMxCLK=2*HCLK
	//  计数器频率CNTCLK=TIMxCLK/(psc+1) =18/6=3M    设分频系数6-1
	//  计数器计数一次的时间 1/CNTCLK=1/3000 ms
	//  1/CK_CLK * ARR=1ms ==> ARR= 3000
	//  HCLK/8 = 9  TIMxCLK=18
	
	
	#ifdef DEBUG_APB1
		 RCC_PCLK1Config(RCC_HCLK_Div4);
	#else
	  RCC_PCLK1Config(RCC_HCLK_Div8);  
	#endif
    TIM2_Init();
	
}

#define DEBUG_1ms
void TIM2_Init(void)
{
   //  中断源      抢占式优先级0   响应式优先级3
	 NVIC_InitConfig(TIM2_IRQn,1,2);
	
	 #ifdef DEBUG_1ms
	 //  配置一个1ms中断定时器
	 //  定时器配置  1、使能定时器  2、arr  3、psc  4、向上计数模式   5、定时器2   
	 TIMx_Init(RCC_APB1Periph_TIM2,3000, 6-1,0,TIM_CounterMode_Up,TIM2);
	#endif
	 //  TIM2中断触发   当计数器的值从0计数到arr是会触发更新中断(TIM_IT_Update)
	 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	 TIM_Cmd(TIM2, ENABLE);
}

原网站

版权声明
本文为[旭日初扬]所创,转载请带上原文链接,感谢
https://xurichuyang.blog.csdn.net/article/details/126188950