本文为野火学习笔记。
定时器分类
stm32f1系列。除互联型设备,共有8个定时器,分为基本,通用,高级3种定时器。不同的定时器有不同的功能。
基本定时器为 TIM6,TIM7 。其只能定时,没有外部IO,且16位计数器只能向上计数。
通用定时器为 TIM2/3/4/5 , 可以定时;也可输出比较和输入捕捉,每个定时器有4个IO,16位计数器可上下计数。
高级定时器为 TIM1/8 ,在通用的基础上多了互补输出信号的功能,每个定时器有8个IO口。
功能框图
下图为基本定时器的结构框图:
时钟源
定时器的时钟源名为 TIMxCLK,可以在时钟树中找到
可见 TIMxCLK 时钟是来自于APB1 的,而 APB1 的预分频器一般选择2分频,使得 APB1 总线的时钟为36M;因此,TIMExCLK 的时钟为72M.
计数器时钟
时钟接入触发控制器,经过 PSC 预分频器分频,驱动CNT计数器。 PSC 为16位分配器,可对时钟信号进行1~65536分频。最终计数器的时钟计算公式如下。
公式中分母+1的操作是官方规定的。
计数器
CNT 为16位计数器,只能向上计数,计数达到指定数时,更新事件,清零从头计数。
自动重载寄存器
寄存器中储存着计数最大值,计到此数,若配置了中断,会产生中断。
影子寄存器
自动重载寄存器ARR和预分频器PSC下有阴影,表示其有影子寄存器。影子寄存器起到缓冲的作用,若在计数器仍在计数时,修改ARR或PSC的值,如果直接写入,则计数器直接清零,重新开始计数。若向影子寄存器写入,则会在当前计数周期结束后,修改值,计数器不会被打断。
定时器时间计算
中断
基本定时器只在溢出时才会产生中断,溢出时也可产生DMA请求。TIMx_DIER寄存器控制DMA和中断的使能,TIMx_EGR 寄存器记录溢出事件的产生。
固件库编程
定时器初始化结构体
typedef struct
{
uint16_t TIM_Prescaler; //预分频器
uint16_t TIM_CounterMode; //计数模式
uint16_t TIM_Period; //ARR
uint16_t TIM_ClockDivision; //时钟分频
uint8_t TIM_RepetitionCounter; //重复计数器
} TIM_TimeBaseInitTypeDef;
在这里,计数模式表示的是向上还是向下计数。最后两个参数是不是基本定时器的功能,不用配置。
开始编程
基本寄存器十分简单,只能计时。这里编写一个使得LED以1秒间隔闪烁的程序。
初始化TIM6
void BASIC_TIM_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;
//BASIC_TIM_NVIC_Config(); //后面加上这句
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
TIM_TimeBaseStruct.TIM_Period = 1000;
TIM_TimeBaseStruct.TIM_Prescaler = 71;
TIM_TimeBaseInit(TIM6,&TIM_TimeBaseStruct);
//清除中断标志位
TIM_ClearFlag(TIM6,TIM_FLAG_Update);
//使能中断请求
TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);
//使能计数器
TIM_Cmd(TIM6,ENABLE);
//暂时关闭时钟,等待使用
}
基本定时器只能向上计数,因此,初始化结果体中只需配置 PSC 和ARR。配置PSC=71,ARR=1000。即计数一次为1ms。
接下来我们希望在计数完成发生中断,按照 中断应用总结 中的步骤,使能外设中断。
使用 TIM_ClearFlag 清除中断标志位,计数溢出的事件被称为更新事件,对应固件库中的标志位叫 TIM_FLAG_Update。然后使用 TIM_ITConfig 使能更新事件的中断。
最后使用 TIM_Cmd 使能定时器。这里我们完成了TIM6的初始化和外设中断使能,下面继续配置中断。
配置中断优先级分组
因程序只有这一个中断,优先级分组并不重要,这里配置中断优先级分组为0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
1
配置NVIC
static void BASIC_TIM_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStruct.NVIC_IRQChannel = TIM6_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 3;
NVIC_Init(&NVIC_InitStruct);
}
配置主优先级为0,子优先级为3。在初始化 TIM6 中使用这个函数。
中断服务函数
在 startup_stm32f10x_hd.s 中找到TIM6中断的函数名,在 stm32f10x_it.c 编写中断服务函数。
extern volatile uint16_t time;
void TIM6_IRQHandler(void)
{
if(TIM_GetITStatus(TIM6,TIM_IT_Update) != RESET)
{
time++;
TIM_ClearITPendingBit(TIM6,TIM_IT_Update);//清除中断标志位
}
}
进入中断后,检查是否真的中断,并设一个全局变量 time, 用来完成1s的记录。最后使用 TIM_ClearITPendingBit 清除中断标志位。
main函数
#define LED_G_GPIO_PIN GPIO_Pin_0
#define LED_G_GPIO_PORT GPIOB
#define LED_G_TEOOGLE {LED_G_PPIO_RORT->ODR ^= LED_G_GPIO_PIN;}
volatile uint16_t time=0;
int main(void)
{
LED_GPIO_Config();
BASIC_TIM_Config();
while(1)
{
if (time ==1000)//1s一进
{
time = 0;//计时归零
LED_G_TEOOGLE;//led反转
}
}
}
上一篇:STM32 SPI读写FLASH
下一篇:EXTI_ClearITPendingBit与EXTI_ClearFlag区别
推荐阅读最新更新时间:2024-11-06 10:33
设计资源 培训 开发板 精华推荐
- 基于 STM32 Nucleo 的 L62xx 系列双刷直流和步进电机驱动器的评估套件环境
- 使用 LT3480 的 600kHz 6.3V38V 输入 DC/DC 转换器在 5V 输出时提供 2A
- LT3988 演示板、双路 60V 降压型稳压器
- 具有 12VDC 和 24VAC 辅助输入的 LT4275CIMS 25W PD 解决方案的典型应用电路
- AM2S-2405SH30Z 5V 2瓦直流转直流转换器的典型应用
- LTC3413EFE 演示板,+/- 3A 单片 DDR 存储器终端电源,Vin = 2.25V-5.5V,Vout = Vref/2 +/- 3A
- LTC3851EUD-1、1.5V/15A 同步降压稳压器 (350kHz) 的典型应用电路
- 超迷你版复古风 SL2.1A USB HUB
- 19 V - 75 W 笔记本电脑适配器,带有跟踪升压 PFC 预调节器,使用 L6563 和 L6566A
- 340g