STM32标准库——定时器中断、外部时钟(九)

一、定时中断

Init

cs 复制代码
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIM_InternalClockConfig(TIM2);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = 10000 - 1;
TIM_TimeBaseInitStruct.TIM_Prescaler = 7200 - 1; 
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
TIM_ClearFlag(TIM2, TIM_IT_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel  = TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStruct);

TIM_Cmd(TIM2, ENABLE);
定时器时钟与基础配置

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);

开启 TIM2 时钟,APB1 外设默认关时钟,不开则后续配置无效。

TIM_InternalClockConfig(TIM2);

指定 TIM2 用内部 72MHz 时钟,默认配置,可省略。

定时器时基核心配置

TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;

定义时基配置结构体,标准库固定写法。

TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;

时钟不分频,与定时无关,固定配置。

TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;

向上计数,从 0 到预设值溢出触发中断,定时中断默认模式。

TIM_TimeBaseInitStruct.TIM_Period = 10000 - 1;

自动重装值 9999,计数器从 0 开始,减 1 才是 10000 次计数。

TIM_TimeBaseInitStruct.TIM_Prescaler = 7200 - 1;

预分频器 7199,减 1 实现 7200 倍分频,72MHz 主频分频为 10kHz 计数时钟。

TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;

通用定时器无此功能,固定置 0。

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);

将配置写入寄存器,时基配置正式生效。

定时器中断配置

TIM_ClearFlag(TIM2, TIM_IT_Update);

清除初始化产生的中断标志,防止启动后立即触发中断。

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

使能 TIM2 更新中断,允许溢出时发送中断请求。

NVIC 中断控制器配置

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

配置中断优先级分组 2,工程仅需配置一次。

NVIC_InitTypeDef NVIC_InitStruct;

定义 NVIC 配置结构体,标准库固定写法。

NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;

指定配置 TIM2 对应的中断通道。

NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;

使能 TIM2 中断通道,允许 NVIC 处理其请求。

NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;

设置 TIM2 抢占优先级 2,分组 2 下范围 0-3。

NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;

设置 TIM2 响应优先级 1,分组 2 下范围 0-3。

NVIC_Init(&NVIC_InitStruct);

写入 NVIC 配置,中断优先级与使能正式生效。

启动定时器

TIM_Cmd(TIM2, ENABLE);

启动 TIM2,计数器开始工作,正式进入 1 秒定时。

核心定时逻辑

72MHz 主频经 7200 倍分频得 10kHz 计数时钟,每 100μs 计数 1 次;计数器从 0 数到 9999 共 10000 次,总计 1 秒,溢出触发更新中断。

中断函数

TIM2的的中断函数是TIM2_IRQHandler(void),因为我们要在显示屏中显示Num,所以可以直接将这个中断函数放在main文件中,如果放在定时器的文件中,那么就extern uint16_t Num;声明在这个文件中有定义这个变量,调用的时候程序就会自行查找。

cs 复制代码
void TIM2_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
    {
        Num++;
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    }
}

使用TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)去获取定时中断的标准位

中断结束后要手动复位中断TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

调用
cs 复制代码
#include "stm32f10x.h"                  // Device header
#include "Delay.h"  
#include "OLED.h" 
#include "Timer.h" 

uint16_t Num = 0;
int main(void)
{
	
	OLED_Init();
	Timer_Init();
	OLED_ShowString(1,1,"Num:");
	
	while(1)
	{
		
		
		OLED_ShowNum(1,5,Num,5);
		
		OLED_ShowNum(2,5,TIM_GetCounter(TIM2),5);
	}
	
}

void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		Num++;
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}

使用TIM_GetCounter(TIM2)获取计数值

二、外部时钟

cs 复制代码
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOA, GPIO_Pin_0);
	
	TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x0F);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period = 10 - 1;
	TIM_TimeBaseInitStruct.TIM_Prescaler = 1 - 1; 
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
	
	TIM_ClearFlag(TIM2, TIM_IT_Update);
	
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel  = TIM2_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
	
	NVIC_Init(&NVIC_InitStruct);
	
	TIM_Cmd(TIM2, ENABLE);

因为采用的是外部时钟源,所以要先打开GPIO,输入模式可以任意配置。GPIOA0 是 TIM2 的外部触发输入(ETR)复用引脚。

TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x0F);

配置 TIM2 使用外部 ETR 引脚(PA0)的脉冲信号作为计数时钟源

参数含义说明:

  • TIM_ExtTRGPSC_OFF:外部信号不分频,直接作为定时器时钟
  • TIM_ExtTRGPolarity_NonInverted:外部信号高电平 / 上升沿有效,不反相
  • 0x0F:外部信号滤波,有效滤除引脚杂波,让触发更稳定

这个滤波可以不加,直接写0x00,但是上电测试不稳定的话可以加上合适的滤波。

TIM_TimeBaseInitStruct.TIM_Prescaler = 1 - 1;

预分频器设为 0,实际不分频,定时器直接以外部 ETR 输入的原始信号作为计数时钟。

TIM_TimeBaseInitStruct.TIM_Period = 10 - 1;自动重装值设为 9,计数器从 0 数到 9 即溢出触发中断,计数仅 10 次。

cs 复制代码
uint16_t Timer_Getcounter(void)
{
    return TIM_GetCounter(TIM2);
}

封装 TIM_GetCounter (TIM2) 为独立函数,方便工程中任意位置直接调用获取 TIM2 当前计数值,无需重复写原函数,简化代码调用,提升可读性和复用性。

其他的代码和上面基本一致

cs 复制代码
#include "stm32f10x.h"                  // Device header
#include "Delay.h"  
#include "OLED.h" 
#include "Timer.h" 

uint16_t Num = 0;
int main(void)
{
	
	OLED_Init();
	Timer_Init();
	OLED_ShowString(1,1,"Num:");
	OLED_ShowString(2,1,"CNT:");
	
	while(1)
	{
		
		
		OLED_ShowNum(1,5,Num,5);
		
		OLED_ShowNum(2,5,Timer_Getcounter(),5);
	}
	
}

void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		Num++;
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}
相关推荐
帅次8 小时前
系统分析师-信息物理系统分析与设计
stm32·单片机·嵌入式硬件·mcu·物联网·iot·rtdbs
澜莲Alice8 小时前
STM32 MPLAB X IDE 软件安装-玩转单片机-英文版沉浸式安装
stm32·单片机·嵌入式硬件
良许Linux8 小时前
IIC总线的硬件部分的两个关键点:开漏输出+上拉电阻
单片机·嵌入式硬件
✎ ﹏梦醒͜ღ҉繁华落℘9 小时前
单片机基础知识 -- ADC分辨率
单片机·嵌入式硬件
Q_21932764559 小时前
车灯控制与报警系统设计
人工智能·嵌入式硬件·无人机
雾削木10 小时前
树莓派部署 HomeAssistant 教程
stm32·单片机·嵌入式硬件
Q_219327645510 小时前
基于单片机的破壁机自动控制系统设计
单片机·嵌入式硬件
我是一棵无人问荆的小草10 小时前
stm32f103芯片多个IO配置成外部中断
stm32·单片机·嵌入式硬件
wjykp10 小时前
ESP32xxx烧录
stm32·单片机·嵌入式硬件
早起huo杯黑咖啡11 小时前
【NOR Flash】关于芯片的高耐久性分区的编程/擦除周期和最小保留时间的数据
单片机·嵌入式硬件