STM32入门——通用定时器

STM32入门——定时器(计时功能)

简介:本代码现象是通过OLED显示计数功能


计数功能:在一定频率下(单位时间内变化的次数)计数到设定值产生一个标志位,通过标志位进行计次,再循环,以实现计数的功能

例如:在72Mhz(72x106hz)下计数从0计到72,产生一个标志位,没次检测到标志位k+1,之后清除标志位,计数再从0开始依次往复,k的值就是T=[1/(72x106)]x72秒

流程图:

新建功能
配置定时器
开启TM2时钟
配置TIM2结构体
TIM_ClockDivision
TIM_CounterMode
TIM_Period
TIM_Prescaler
使能定时器TIM2
使能定时器更新中断TIM_ITConfig
配置中断
中断优先级分组NVIC_PriorityGroupConfig
NVIC_InitStructure
NVIC_IRQChannel
NVIC_IRQChannelPreemptionPriority
NVIC_IRQChannelSubPriority
NVIC_IRQChannelCmd
设置中断执行程序

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 时钟线包含以下几个部分,使用功能时都要开启相应的时钟

屏幕截图 2024-07-10 184128

屏幕截图 2024-07-09 132319

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

image-20240710181657415

image-20240710182240597

1、TIM_Period
TIM_Period 设置了在下一个更新事件装入活动的自动重装载寄存器周期的值。它的取值必须在 0x0000 和
0xFFFF 之间。

2、TIM_Prescaler
TIM_Prescaler 设置了用来作为 TIMx 时钟频率除数的预分频值。它的取值必须在 0x0000 和 0xFFFF 之间。

3TIM_ClockDivision
image-20240710182609727

4、TIM_CounterMode

image-20240710182643888

5使能TIM2中断

屏幕截图 2024-07-10 183314

6、使能TIM外设

image-20240710182709364

屏幕截图 2024-07-10 183257

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显示数字调用计数器的值即可
  • 44
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏夜星空似海

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值