stm32定时器之简单封装
Posted 旭日初扬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了stm32定时器之简单封装相关的知识,希望对你有一定的参考价值。
目录
一、定时器的封装与概念
/******************************************************************************
定时器初始化函数
*******************************************************************************/
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);
以上是关于stm32定时器之简单封装的主要内容,如果未能解决你的问题,请参考以下文章
stm32定时器tim6tim7,对定时时间的设置与哪些寄存器有关