9、江科大stm32视频学习笔记——定时器定时中断、定时器外部时钟

目录

1、定时器定时中断

(1)Timer.c

(2)main.c

2、定时器外部时钟

(1)与内部时钟在Timer.c不同的代码

(2)Timer.c

(3)main.c

3、知识点:

1、定时器定时中断

(1)Timer.c

#include "stm32f10x.h"                  // Device header

void Timer_Init(void)
{
	//第一步:RCC开启时钟
	//第二步:选择时基单元的时钟源,对于定时中断,选择内部时钟源
	//第三步:配置时基单元,包括预分频器、自动重装器、计数模式(用结构体配置)
	//第四步:配置输出中断控制,允许更新中断输出到NVIC
	//第五步:配置NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级
	//第六步:运行控制,整个模块配置完成后,使能计数器,否则计数器不运行
	//计数器使能后,计数器就会开始计数,当计数器更新时,触发中断,最后写个定时器中断函数
	//这样中断中断函数就能每隔一段时间自动执行一次
	
	
	//第一步:RCC开启时钟
	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;//ARR自动重装器的值
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;//PSC预分频器的值
	//预分频对72M进行7200分频,得到10K的计数频率,在10k的频率下,计数10k个数,就是1s
	//可以预分频给少点,自动重装给多一点,这样就是以一个比较高的频率计比较多的数,反之则反
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	//第四步:配置输出中断控制,允许更新中断输出到NVIC
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除向上溢出中断标志
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//使能更新中断
	
	//第五步:配置NVIC
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择分组2
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//中断通道,定时器2的通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//设置抢占优先级为2
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//设置响应优先级为1
	NVIC_Init(&NVIC_InitStructure);
	
	//第六步:启动定时器
	TIM_Cmd(TIM2, ENABLE);
}


/*当作参考,哪个文件需要可以复制过去
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
	{
		
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}
*/

(2)main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"

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

2、定时器外部时钟

对射性红外传感器:接PA0引脚,在PA0引脚输入外部时钟

(1)与内部时钟在Timer.c不同的代码

	//通过ETR引脚的外部时钟模式2配置
	//TIM_ExtTRGPSC_OFF:无需分频,TIM_ExtTRGPolarity_NonInverted,:
	//不反向,高电平或上升沿有效,0x0F:暂时不用滤波器
	TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F);

	TIM_TimeBaseInitStructure.TIM_Period = 10 - 1;//把只改得小一点,因为手动的没这么块
	TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;

uint16_t Timer_GetCounter(void)
{
	//实时看TNT的值
	return TIM_GetCounter(TIM2);
}

(2)Timer.c

#include "stm32f10x.h"                  // Device header

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);
	
	//通过ETR引脚的外部时钟模式2配置
	//TIM_ExtTRGPSC_OFF:无需分频,TIM_ExtTRGPolarity_NonInverted,:
	//不反向,高电平或上升沿有效,0x0F:暂时不用滤波器
	TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F);
	
	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)
{
	//实时看TNT的值
	return TIM_GetCounter(TIM2);
}

/*
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
	{
		
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}
*/

(3)main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"

uint16_t Num;

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

3、知识点:

(1)浮空输入:一旦浮空,电平可能会跳个没完。应用场景:外部的输入信号功率很小,内部的上拉电阻可能会影响到输入信号,这时就可以用浮空输入,防止影响外部输入的电平

(2)extern:告诉编译器,已经在别的文件中定义了该变量,至于在哪里,直接去找吧

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值