当前位置: 首页 > article >正文

stm32单片机个人学习笔记7(TIM定时中断)

前言

本篇文章属于stm32单片机(以下简称单片机)的学习笔记,来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记,只能做参考,细节方面建议观看视频,肯定受益匪浅。

STM32入门教程-2023版 细致讲解 中文字幕_哔哩哔哩_bilibili

一、TIM简介

二、定时器类型

三、基本定时器框图

向上的箭头UI表示,计数值等于重装值产生的中断称为“更新中断”,之后会通往NVIC,再配置好NVIC的定时器通道,定时器更新中断就能得到CPU的响应了 

向下的箭头U表示,“更新事件”,其不会触发中断,但能触发内部其它电路的工作

可以将U更新事件映射到TRGO上,然后TRGO就会直接去触发DAC了,实现硬件自动化 

四、通用定时器框图

通用定时器支持向上计数模式和向下计数模式和中央对齐模式

向上计数模式是从0自增,增到重装值(基本定时器仅支持这一模式)

向下计数模式是从重装值自减,减到0

中央对齐模式是先从0自增,增到重装值,再从重装值自减,减到0

ETRF提供外部时钟,就是“外部时钟模式2”

当TRGI当作外部时钟来使用时,就是“外部时钟模式1” ,ITR是来自其它定时器的时钟信号(具体连接关系参考下表),实现定时器的级联

五、定时中断基本结构

六、预分频器时序

预分配缓冲器(影子寄存器) 才是真正起作用的,预分频控制寄存器的供我们读写的,作用是当计数值计到一半时,改变分频系数,其计数频率不会立马发生改变,而是在下一个计数周期才真正改变频率

七、计数器时序

更新中断标志(UIF)需要我们在中断程序中手动清零 

1. 计数器无预装时序

2.计数器有预装时序

有预装就是启用了影子寄存器,作用与分频器的影子寄存器类似,不过这里对应的是重装值 

八、RCC时钟树

九、实例一(定时器定时中断)

1.开启内部时钟

2.设置为内部时钟模式

3.时基单元初始化

4.清除系统启动产生的中断标志位(不然一启动就会产生一个中断事件)

5.中断输出控制 

6.NVIC分组及初始化

7.运行控制(开启计数)

Timer.c 

#include "stm32f10x.h"                  // Device header

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 = 1000 - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	//清除系统启动产生的中断标志位
	TIM_ClearFlag(TIM2, TIM_IT_Update);
	
	//中断输出控制
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	
	//NVIC分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	//NVIC初始化
	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);
}

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

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

 十、实例二(定时器外部时钟)

思路与实例一基本相同

Timer.c 

#include "stm32f10x.h"                  // Device header

/**
  * @brief  定时器2初始化
  * @param  无
  * @retval 无
  */
void Timer_Init(void)
{
	//开启内部时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	//初始化GPIO
	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);
	
	//设置为外部时钟模式2
	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_IT_Update);
	
	//中断输出控制
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	
	//NVIC分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	//NVIC初始化
	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);
}

/**
  * @brief  获取TIM2的计数值
  * @param  无
  * @retval 计数值
  */
uint16_t Timer_GetCounter(void)
{
	return TIM_GetCounter(TIM2);
}

/**
  * @brief  定时器2中断函数
  * @param  无
  * @retval 无
  */
/*
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update)==SET)
	{
		
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}
*/

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

 


http://www.kler.cn/a/316429.html

相关文章:

  • OpenLinkSaas使用手册-Git工具
  • 经典150-数组/字符串
  • 嵌入式科普(25)Home Assistant米家集成意味着IOT的核心是智能设备
  • Java旅程(五)Spring 框架与微服务架构 了解 JVM 内部原理和调优
  • 施耐德变频器ATV320系列技术优势:创新与安全并重
  • upload-labs关卡记录12
  • 虚幻引擎解决构建问题
  • 通往AGI的皇冠:逻辑推理能力
  • [创业之路-151] :职能部门/非经营部门 VS 业务部门/经营部门划分与职责
  • 某准网爬虫逆向
  • 掌握Spring Boot数据库集成:用JPA和Hibernate构建高效数据交互与版本控制
  • TypeScript学习笔记2
  • Git rebase 的使用(结合图与案例)
  • 16.2 k8s容器基础资源指标讲解
  • java:word文件替换字段,word转pdf
  • 加密与安全_三种常见的注入攻击
  • 【通讯协议】S32K142芯片——LIN通信的学习和配置
  • 文档加密,如何设置?加密文档的10个小妙招值得参考!(电脑文件安全加密)
  • 【JavaSE】Java注解
  • 比亚迪技术面试(测试、测开)
  • STM32G474的SPI工作在从机模式
  • SpringCloud解读
  • 回归模型拟合效果的统计指标: 决定系数 R2 r2 r2_score
  • Jupyter的使用
  • 【RabbitMQ 项目】服务端:数据管理模块之虚拟机模块
  • Maven进阶-二、依赖