基于STM32F4实现定时器中断功能(Tim2、Tim3)


前言

好多天没学习新的内容了,今天学习通用定时器。


一、定时器的概述

定时器最基本的功能就是定时了,如果把定时器和GPIO结合起来使用的话可以实现非常多的功能,可以测量输入信号的脉冲宽度,可以产生输出方波等等。stm32f407中有两个高级定时器,九个通用定时器,两个基本定时器,其中通用定时器的主要功能为定时计数、PWM输出、输入捕获、输出比较。

时钟的整体和来源如下图所示:
在这里插入图片描述
定时器主要有几个部分组成:最上层的时钟部分,中间的时间计数部分,左下的输入捕获部分和右下的输出比较部分。其中时钟的来源很多,内部时钟是用的最多的,内部时钟一般是来自于APB总线的时钟;ETR(External Trigger)则是来自外部的时钟,ITRx是内部定时器级联的输出,可以用来制作级联定时器。定时器本身有一个预分频器PSC,是需要设置的重要参数之一。

二、例程实现

1.例程介绍

这一次没有详细的介绍定时器,及每一个参数的介绍,对于一个新手来说并不是第一次就能全懂,我觉得先有一个大概的了解,把程序先跑一跑,在以后需要用到的时候再一点点进行深入学习。

我们定义两个计数值不一样的定时器中断对LED进行闪烁的操作来观察,他们之间的区别。

2.完整代码

代码如下:

#include "stm32f4xx.h"                  // Device header
#include "sys.h"   						//定义的是位带操作文件,可不要

//gpio、nvic、timer需要用到的结构体
static GPIO_InitTypeDef  GPIO_InitStructure;
static NVIC_InitTypeDef NVIC_InitStructure;
static TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

//自定义的一个延时函数
void delay_ms(uint32_t n)
{
	while(n--)
	{
		SysTick->CTRL = 0; // Disable SysTick
		SysTick->LOAD = (168000)-1; // Count from 255 to 0 (256 cycles)
		SysTick->VAL = 0; // Clear current value as well as count flag
		SysTick->CTRL = 5; // Enable SysTick timer with processor clock
		while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set
	}
	
	SysTick->CTRL = 0; // Disable SysTick
}


//定时器3初始化函数
void Tim3_init(void)
{
	//使能定时器3硬件时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	//配置定时器3分频值、计数值
	TIM_TimeBaseStructure.TIM_Period = 10000/2-1;//计数值500ms
	TIM_TimeBaseStructure.TIM_Prescaler = 8400-1;//进行8400的预分频值 42*2Mhz/8400=10000hz 10000次计数就是1秒
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;//在f407不支持,没有时钟分频
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
	
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
	
	//配置定时器3中断的触发方式
	TIM_ITConfig(TIM3,TIM_IT_Update, ENABLE);

	//配置定时器3的中断优先级
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	//使能定时器3工作
	TIM_Cmd(TIM3, ENABLE);
	
}


void Tim2_init(void)
{
	//使能定时器2硬件时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	//配置定时器2分频值、计数值
	TIM_TimeBaseStructure.TIM_Period = 1000-1;//计数值100ms
	TIM_TimeBaseStructure.TIM_Prescaler = 8400-1;//进行8400的预分频值 42*2Mhz/8400=10000hz 10000次计数就是1秒
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;//在f407不支持,没有时钟分频
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
	
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
	
	//配置定时器2中断的触发方式
	TIM_ITConfig(TIM2,TIM_IT_Update, ENABLE);

	//配置定时器2的中断优先级
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	//使能定时器2工作
	TIM_Cmd(TIM2, ENABLE);
	
}



int main(void)
{
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOE时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能GPIOF时钟

	//GPIOF9,F10初始化设置
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
	GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化
	
	
	
	GPIO_SetBits(GPIOF,GPIO_Pin_9 |GPIO_Pin_10);
	
	//定时器 3初始化
	Tim3_init();
	Tim2_init();
	while(1)
	{
		
	
		
	}
}

//查看向量表(misc.h)可以找到对应的中断函数名
void TIM3_IRQHandler(void)
{
	//判断标志位
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
	{
		PFout(10)^=1;//对led进行闪烁操作
		//清空标志位
		TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
	}
}

void TIM2_IRQHandler(void)
{
	//判断标志位
	if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
	{
		PFout(9)^=1;
		//清空标志位
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
}


总结

定时器是比较重要的功能,需要花时间学习,在后面的PWM输出中也会用到。如果每天可以有时间学习一些新的知识,在日积月累的情况下,相信一定会学有所成的。

  • 10
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32F4系列微控制器中的定时器(TIM)模块可以用于生成定时中断。在使用TIM定时器中断时,通常需要进行以下步骤: 1. 配置TIM定时器的基本参数:选择定时器的时钟源、预分频值和计数模式等,这些参数决定了定时器的工作频率和计数范围。 2. 配置定时器的自动重装载寄存器(ARR)和预分频寄存器(PSC):设置定时器的计数周期和预分频系数,以确定定时器的定时周期。 3. 配置定时器的工作模式:选择定时器的工作模式,比如单脉冲模式、重复模式或连续模式等。 4. 启用定时器中断:使能定时器中断,并设置中断优先级。 5. 编写中断处理函数:在中断处理函数中编写需要执行的代码,比如更改输出状态、处理数据等。 6. 启动定时器:使能定时器开始计数。 下面是一个使用TIM2定时器中断的示例代码: ```c #include "stm32f4xx.h" void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { // 中断处理代码 // ... TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } } int main(void) { // 初始化配置代码 // 使能定时器2中断 NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // 配置定时器2 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Period = 1000; // 定时周期为1ms TIM_TimeBaseStructure.TIM_Prescaler = 8400 - 1; // 预分频系数为8400,定时频率为10kHz TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); // 清除定时器2的中断标志位 TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 使能定时器2的更新中断 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // 启动定时器2 TIM_Cmd(TIM2, ENABLE); while (1) { // 主循环代码 // ... } } ``` 以上代码中,我们使用了TIM2定时器,并配置了1ms的定时周期。在中断处理函数`TIM2_IRQHandler`中,可以编写需要执行的代码。在主循环中,可以编写其他的程序逻辑。 希望这个简单的示例对你有所帮助!如果有任何问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值