【stm32】定时器中断与定时器外部时钟

定时器中断

添加Timer.c和Timer.h文件

初始化

1.RCC开启时钟(TIM2是APB1总线的外设)

2.选择时基单元的时钟源,定时中断选择内部时钟源

3.配置时基单元,用一个结构体

4.配置输出中断控制,允许更新中断输出到NVIC

5.配置NVIC,在NVIC中打开定时器中断的通道,并分配优先级

6.运行控制,模块配置完成后,还需要使能计数器。定时器使能后,计数器开始计数,当计数器更新时,触发中断,最后写一个定时器的中断函数

c 复制代码
void TIM_DeInit(TIM_TypeDef* TIMx);

回复缺省配置

c 复制代码
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

时基单元初始化

c 复制代码
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

把结构体变量赋一个默认值

c 复制代码
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

使能计数器

NewState,新状态,使能/失能

c 复制代码
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);

使能中断输出信号

c 复制代码
void TIM_InternalClockConfig(TIM_TypeDef* TIMx);
//选择内部时钟
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
//选择ITRx其他定时器的时钟
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,uint16_t TIM_ICPolarity, uint16_t ICFilter);
//选择TIx捕获通道的时钟
//TIM_TIxExternalCLKSource:选择TIx具体的某个引脚
//TIM_ICPolarity:输入极性
//ICFilter:滤波器
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);
//选择ETR通过外部时钟模式1输入的时钟
//TIM_ExtTRGPrescaler:外部触发预分频器
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
//选择ETR通过外部时钟模式2输入的时钟
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_tTIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);
//单独用来配置ETR引脚的预分频器,极性,滤波器
c 复制代码
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);

单独写预分频值

Prescaler:预分频值

TIM_PSCReloadMode:模式(听从安排,在更新时间后生效;手动产生更新事件,立即生效)

c 复制代码
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);

改变计数器的计数模式

TIM_CounterMode:新的计数器模式

c 复制代码
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

自动重装寄存器预装功能配置

c 复制代码
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);

给计数器写入一个值

c 复制代码
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);

给自动重装寄存器写入一个值

c 复制代码
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);

获取当前计数器的值

c 复制代码
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);

获取当前的预分频器的值

在该程序中

如果想跨文件使用变量Num,解决方法两种:

1.用extern声明一下要用的变量

2.将中断函数放到主函数后面

问题:

c 复制代码
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
/* Generate an update event to reload the Prescaler and the Repetition counter
     values immediately */
//让值立即起作用,手动生成一个更新事件,但同时,更新事件和更新中断同时发生,更新中断会置中断标志位,所以一旦初始化完,更新中断就会立即进入,所以一上电就会立即进中断

解决方案:

c 复制代码
TIM_ClearFlag(TIM2 , TIM_FLAG_Update);

手动把更新中断标志位清除一下

Tim.c:

c 复制代码
void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
	
	TIM_InternalClockConfig(TIM2);
		
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2 , &TIM_TimeBaseInitStructure);
	
	TIM_ClearFlag(TIM2 , TIM_FLAG_Update);
	
	TIM_ITConfig(TIM2 , TIM_IT_Update , ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn ;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE ;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2 ;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1 ;
	NVIC_Init(&NVIC_InitStructure);
	
    TIM_Cmd(TIM2 , ENABLE);
}

main.c:

c 复制代码
uint16_t Num;

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);
	}
}

定时器外部时钟

当使用外部时钟:

连接到PA0上时

TIM_ETRClockModexConfig:

Mode 1:一个只有踩下油门踏板(高电平)才会转动的发动机。

Mode 2:一个每点火一次(边沿)就转动一下的发动机,无论油门踏板是否踩着

滤波器选择:

使用浮空输入情况:

外部输入信号功率很小,内部上拉电阻可能会影响到这个输入信号

c 复制代码
TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;

没有预分频,每次遮挡CNT都加1

如果有预分频,遮挡几次才会加一次

Timer.c:

c 复制代码
void Timer_Init(void)
{
	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);
	
	TIM_ETRClockMode2Config(TIM2 ,TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00);
		
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 10 - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2 , &TIM_TimeBaseInitStructure);
	
	TIM_ClearFlag(TIM2 , TIM_FLAG_Update);
	
	TIM_ITConfig(TIM2 , TIM_IT_Update , ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn ;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE ;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2 ;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1 ;
	NVIC_Init(&NVIC_InitStructure);
	
  TIM_Cmd(TIM2 , ENABLE);
}

uint16_t Timer_GetCounter(void)
{
	return TIM_GetCounter(TIM2);
}

main.c:

c 复制代码
uint16_t Num;

int main(void)
{
	OLED_Init();
	Timer_Init();
	
	OLED_ShowString(1, 1, "Num:");
	OLED_ShowString(1, 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);
	}
}

注:本文来源b站江协课程,为笔记

相关推荐
CC呢7 小时前
基于单片机宠物项圈/宠物防丢失设计
单片机·嵌入式硬件·宠物·单片机设计
Skylar_.9 小时前
嵌入式 - 硬件:51单片机(2)
单片机·嵌入式硬件
不懂机器人9 小时前
51单片机----LED与数码管模块
单片机·嵌入式硬件·51单片机
宋一平工作室9 小时前
嵌入式人别再瞎折腾了!这8个开源项目,解决按键/队列/物联网所有痛点,小白也能抄作业
c语言·stm32·单片机·嵌入式硬件·物联网·开源
m0_5713728210 小时前
关于嵌入式学习——嵌入式硬件2
linux·驱动开发·嵌入式硬件·学习
hardStudy_h10 小时前
详解STM32的完整启动流程
stm32·单片机·嵌入式硬件
陌夏微秋11 小时前
FPGA硬件设计4 ZYNQ外围-以太网-PL/PS
stm32·单片机·嵌入式硬件·fpga开发·硬件架构·硬件工程·信息与通信
亿道电子Emdoor11 小时前
【ARM】MDK如何实现使用Hex文件完成程序烧录
arm开发·stm32·单片机
IT狼~11 小时前
【串口助手】串口调试助手LTSerialTool v3.12.0发布
经验分享·嵌入式硬件·串口调试·串口助手·自编工具