STM32入门——定时器(计时功能)
简介:本代码现象是通过OLED显示计数功能
计数功能:在一定频率下(单位时间内变化的次数)计数到设定值产生一个标志位,通过标志位进行计次,再循环,以实现计数的功能
例如:在72Mhz(72x106hz)下计数从0计到72,产生一个标志位,没次检测到标志位k+1,之后清除标志位,计数再从0开始依次往复,k的值就是T=[1/(72x106)]x72秒
流程图:
1、库函数实现:
time.c
#include "stm32f10x.h" // Device header
uint16_t count = 0; //定义一个变量count
void timer_init(void)//定时器2初始化函数
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能定时器2时钟
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//定义定时器2结构体
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;//设置时钟分频因子
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//设置计数模式为向上计数
TIM_TimeBaseStructure.TIM_Period=1000-1;//计数周期,计数到1000-1被重置为0,并且产生一个更新中断
TIM_TimeBaseStructure.TIM_Prescaler=72-1;//设置预分频器72 PSC 即时钟频率为1MHZ
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化定时器2
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //使能定时器2更新中断
TIM_Cmd(TIM2, ENABLE); //使能定时器2
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC优先级分组2
NVIC_InitTypeDef NVIC_InitStructure; //定义NVIC初始化结构体
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //设置NVIC通道为定时器2中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //设置NVIC通道抢占优先级为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //设置NVIC通道子优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能NVIC通道
NVIC_Init(&NVIC_InitStructure); //初始化NVIC
}
void TIM2_IRQHandler()//定时器2中断服务函数,硬件自动调用,不需要手动调用
{
if(TIM_GetFlagStatus(TIM2,TIM_FLAG_Update)==1)//判断定时器2更新标志位是否产生
{
count++;//计数值加1 T=1000/1MHZ
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update); //清除定时器2更新标志位
}
}
uint16_t counter()//返回计数值
{
return count;
}
time.h
#ifndef __TIME_H
#define __TIME_H
void timer_init(void);
uint16_t counter();
#endif
main.c
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "time.h"
int main(void)
{
OLED_Init();//oled初始化
timer_init();//TM2初始化
while (1)
{
OLED_ShowNum(2, 1,counter(), 6);//显示计数值,第2行第1列,显示6位数,数字不够填充0
}
}
还有OLED模块,调用的网上分享的代码。
2、认识通用定时器
1、通用定时器基本功能:(主要的,不是全部)
1.计数器,输入捕获,输出比较,pwm生成,单脉冲输出
计数模式:向上计数,向下计数,中央对齐计数
捕获/比较通道:每一个捕获/比较通道都是围绕着一个捕获/比较寄存器(包含影子寄存器),包括捕获的输入部分
(数字滤波、多路复用和预分频器),和输出部分(比较器和输出控制)
输入捕获:输入捕获功能允许定时器捕捉外部事件的发生时间,例如检测边缘(上升、下降或双边缘)并记录下这个事件发生时的计数器值。这对于测量信号周期、脉冲宽度或其他与时间相关的特性非常有用
PWM输入模式:脉冲宽度调制(PWM)是一种广泛使用的信号类型,用于控制模拟电路,如电机速度、灯光亮度等。通过在固定频率下改变信号的占空比(即高电平相对于整个周期的比例),可以实现精细的控制。通用定时器通常能产生多个PWM通道,每个通道都可以独立配置。
输出比较模式:这个功能使得定时器能够在计数器值达到预设值时产生一个输出信号。
单脉冲:单脉冲模式允许定时器在接收到特定的输入信号后仅产生一个脉冲。这种模式适用于需要发送单个脉冲信号的场合,例如触发ADC转换或启动其他外围设备。
2、实现计数功能:(根据固件库手册和stm32参考手册)
1,stm32有高级定时器(TIM1,TIM8)和通用定时器(TIM2-TIM5)和基本定时器(TIM6和TIM7),我们以TIM2为例子进行开发
首先要开启TIM2的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能定时器2时钟
函数RCC_APB1PeriphClockCmd 时钟线包含以下几个部分,使用功能时都要开启相应的时钟
2创建TIM2初始化结构体,并初始化相应参数
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//定义定时器2结构体
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;//设置时钟分频因子
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//设置计数模式为向上计数
TIM_TimeBaseStructure.TIM_Period=1000-1;//计数周期,计数到1000-1被重置为0,并且产生一个更新中断 f=72/[(arr+1)*(psc+1)]
TIM_TimeBaseStructure.TIM_Prescaler=72-1;//设置预分频器为72 PSC
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化定时器2
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //使能定时器2更新中断
TIM_Cmd(TIM2, ENABLE); //使能定时器2
1、TIM_Period
TIM_Period 设置了在下一个更新事件装入活动的自动重装载寄存器周期的值。它的取值必须在 0x0000 和
0xFFFF 之间。
2、TIM_Prescaler
TIM_Prescaler 设置了用来作为 TIMx 时钟频率除数的预分频值。它的取值必须在 0x0000 和 0xFFFF 之间。
3TIM_ClockDivision
4、TIM_CounterMode
5使能TIM2中断
6、使能TIM外设
7、配置NVIC跟中断配置过程一样不在赘述
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC优先级分组2
NVIC_InitTypeDef NVIC_InitStructure; //定义NVIC初始化结构体
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //设置NVIC通道为定时器2中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //设置NVIC通道抢占优先级为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //设置NVIC通道子优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能NVIC通道
NVIC_Init(&NVIC_InitStructure); //初始化NVIC
8,设置中断执行程序
void TIM2_IRQHandler()//定时器2中断服务函数,硬件自动调用,不需要手动调用
{
if(TIM_GetFlagStatus(TIM2,TIM_FLAG_Update)==1)//判断定时器2更新标志位是否产生
{
count++;//计数值加1
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update); //清除定时器2更新标志位
}
}
9、设置返回计数函数
void TIM2_IRQHandler()//定时器2中断服务函数,硬件自动调用,不需要手动调用
{
if(TIM_GetFlagStatus(TIM2,TIM_FLAG_Update)==1)//判断定时器2更新标志位是否产生
{
count++;//计数值加1
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update); //清除定时器2更新标志位
}
}
10、主函数初始化,在OLED显示数字调用计数器的值即可
函数,硬件自动调用,不需要手动调用
{
if(TIM_GetFlagStatus(TIM2,TIM_FLAG_Update)==1)//判断定时器2更新标志位是否产生
{
count++;//计数值加1
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update); //清除定时器2更新标志位
}
}
10、主函数初始化,在OLED显示数字调用计数器的值即可