IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 定时器中断控制LED状态实验 -> 正文阅读

[嵌入式]定时器中断控制LED状态实验

一、 STM32 通用定时器简介
STM32F1 的通用定时器是一个通过可编程预分频器( PSC )驱动的 16 位自动装载计数(CNT )构成。 STM32 的通用定时器可以被用于:测量输入信号的脉冲长度 ( 输入捕获 ) 或者产生输出波( 输出比较和 PWM) 等。 使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。STM32 的每个通用定时器都是完全独立的, 没有互相共享的任何资源。
STM3F1 的通用 TIMx (TIM2 TIM3 TIM4 TIM5) 定时器功能包括:
1.16 位向上、向下、向上 / 向下自动装载计数器( TIMx_CNT )。
2.16 位可编程 ( 可以实时修改 ) 预分频器 (TIMx_PSC) ,计数器时钟频率的分频系数为 1 ~65535 之间的任意数值。
3. 4 个独立通道( TIMx_CH1~4 ),这些通道可以用来作为:
A .输入捕获
B .输出比较
C PWM 生成 ( 边缘或中间对齐模式 )
D .单脉冲模式输出
4. 可使用外部信号( TIMx_ETR )控制定时器和定时器互连(可以用 1 个定时器控制另外一个定时器)的同步电路。
5. 如下事件发生时产生中断 /DMA
A .更新:计数器向上溢出 / 向下溢出,计数器初始化 ( 通过软件或者内部 / 外部触发 )
B .触发事件 ( 计数器启动、停止、初始化或者由内部 / 外部触发计数 )
C .输入捕获
D .输出比较
E .支持针对定位的增量 ( 正交 ) 编码器和霍尔传感器电路
F .触发输入作为外部时钟或者按周期的电流管理
由于 STM32 通用定时器比较复杂,这里我们不再多介绍,详细请参考stm32中文参考手册。
二、相关寄存器的介绍
2.1.控制寄存器TIMx_CR1
????????

?

首先我们来看看 TIMx_CR1 的最低位,也就是计数器使能位,该位必须置 1 ,才能让定时器开始计数。从第 4 DIR 可以看出默认的计数方式是向上计数,同时也可以向下计数,第 5,6位是设置计数对齐方式的。从第 8 和第 9 位可以看出,我们还可以设置定时器的时钟分频因子为 1,2,4
2.2.DMA/中断使能寄存器(TIMx_DIER)
该寄存器是一个 16 位的寄存器,其各位描述如图 ? 所示:

?

这里我们同样仅关心它的第 0 位,该位是更新中断允许位,实验用到的是定时器的更新中断,所以该位要设置为 1 ,来允许由于更新事件所产生的中断。
2.3.预分频寄存器(TIMx_PSC
该寄存器用 设置对时钟进行分频,然后提供给计数器,作为计数器的时钟。该寄存器的各位描述如图 所示:

?

这里,定时器的时钟来源有 4 个:
2.3.1?.? 内部时钟( CK_INT
2.3.2?.? 外部时钟模式 1 :外部输入脚( TIx
2.3.3?.? 外部时钟模式 2 :外部触发输入( ETR
2.3.4.?? 内部触发输入( ITRx ):使用 A 定时器作为 B 定时器的预分频器( A B 提供时钟)。
这些时钟,具体选择哪个可以通过 TIMx_SMCR 寄存器的相关位来设置。这里的 CK_INT时钟是从 APB1 倍频的来的,除非 APB1 的时钟分频数设置为 1 ,否则通用定时器 TIMx 的时钟是 APB1 时钟的 2 倍,当 APB1 的时钟不分频的时候,通用定时器 TIMx 的时钟就等于 APB1的时钟。这里还要注意的就是高级定时器的时钟不是来自 APB1 ,而是来自 APB2 的。这里顺带介绍TIMx_CNT 寄存器,该寄存器是定时器的计数器,该寄存器存储了当前定时器的计数值。
2.4.自动重装载寄存器(TIMx_ARR
该寄存器在物理上实际对应着 2 个寄存器。 一个是程序员可以直接操作的,另外一个是程序员看不到的,这个看不到的寄存器在《STM32参考手册》里面被叫做影子寄存器。事实上真正起作用的是影子寄存器。根据 TIMx_CR1 寄存器中 APRE 位的设置: APRE=0 时,预装载寄存器的内容可以随时传送到影子寄存器,此时 2 者是连通的;而 APRE=1 时,在每一次更新事件( UEV 时才把预装在寄存器的内容传送到影子寄存器。
2.5.状态寄存器( TIMx_SR
该寄存器用来标记当前与定时器相关的各种事件/ 中断是否发生。该寄存器的各位描述如图 所示:

只要对以上几个寄存器进行简单的设置,我们就可以使用通用定时器了,并且可以产生中断。

我们将使用定时器产生中断,然后在中断服务函数里面翻转 DS1 上的电平,来指 示定时器中断的产生。接下来我们以通用定时器 TIM3 为实例,来说明要经过哪些步骤,才能达到这个要求,并产生中断。这里我们就对每个步骤通过库函数的实现方式来描述。
三、配置介绍
3.1.TIM3 时钟使能。
TIM3 是挂载在 APB1 之下,所以我们通过 APB1 总线下的使能使能函数来使能 TIM3 。调
用的函数是:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
3.2. 初始化定时器参数 , 设置自动重装值,分频系数,计数方式等。
在库函数中,定时器的初始化参数是通过初始化函数 TIM_TimeBaseInit 实现的:
voidTIM_TimeBaseInit(TIM_TypeDef*TIMx,
TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
第一个参数是确定是哪个定时器,这个比较容易理解。第二个参数是定时器初始化参数结
构体指针,结构体类型为 TIM_TimeBaseInitTypeDef ,下面我们看看这个结构体的定义:
typedef struct
{
 uint16_t TIM_Prescaler; 
 uint16_t TIM_CounterMode; 
 uint16_t TIM_Period; 
 uint16_t TIM_ClockDivision; 
 uint8_t TIM_RepetitionCounter; 
} TIM_TimeBaseInitTypeDef;
这个结构体一共有 5 个成员变量,要说明的是,对于通用定时器只有前面四个参数有用,
最后一个参数 TIM_RepetitionCounter 是高级定时器才有用的,这里不多解释。
第一个参数 TIM_Prescaler 是用来设置分频系数的,刚才上面有讲解。
第二个参数 TIM_CounterMode 是用来设置计数方式,上面讲解过,可以设置为向上计数,向下计数方式还有中央对齐计数方式,比较常用的是向上计数模式 TIM_CounterMode_Up 和向 下计数模式 TIM_CounterMode_Down
第三个参数是设置自动重载计数周期值,这在前面也已经讲解过。
第四个参数是用来设置时钟分频因子。
针对 TIM3 初始化范例代码格式:
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 5000;
TIM_TimeBaseStructure.TIM_Prescaler =7199; 
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
3.3. 设置 TIM3_DIER 允许更新中断。
因为我们要使用 TIM3 的更新中断,寄存器的相应位便可使能更新中断。在库函数里面定
时器中断使能是通过 TIM_ITConfig 函数来实现的:
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
第一个参数是选择定时器号,这个容易理解,取值为 TIM1~TIM17
第二个参数非常关键,是用来指明我们使能的定时器中断的类型,定时器中断的类型有很多种,包括更新中断 TIM_IT_Update ,触发中断 TIM_IT_Trigger ,以及输入捕获中断等等。
第三个参数就很简单了,就是失能还是使能。
例如我们要使能 TIM3 的更新中断,格式为:
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );
3.4.TIM3 中断优先级设置
在定时器中断使能之后,因为要产生中断,必不可少的要设置 NVIC 相关寄存器,设置中断优先级。之前多次讲解到用 NVIC_Init 函数实现中断优先级的设置,这里就不重复讲解。
3.5.允许 TIM3 工作,也就是使能 TIM3
光配置好定时器还不行,没有开启定时器,照样不能用。我们在配置完后要开启定时器,通过 TIM3_CR1 CEN 位来设置。在固件库里面使能定时器的函数是通过 TIM_Cmd 函数来实现的:
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
这个函数非常简单,比如我们要使能定时器 3 ,方法为:
TIM_Cmd(TIM3, ENABLE); //使能 TIMx 外设
3.6.编写中断服务函数。
在最后,还是要编写定时器中断服务函数,通过该函数来处理定时器产生的相关中断。在中断产生后,通过状态寄存器的值来判断此次产生的中断属于什么类型。然后执行相关的操作,我们这里使用的是更新(溢出)中断,所以在状态寄存器 SR 的最低位。在处理完中断之后应该向 TIM3_SR 的最低位写 0 ,来清除该中断标志。在固件库函数里面,用来读取中断状态寄存器的值判断中断类型的函数是:
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t)
该函数的作用是,判断定时器 TIMx 的中断类型 TIM_IT 是否发生中断。比如,我们要判断定时器 3 是否发生更新(溢出)中断,方法为:
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){}
固件库中清除中断标志位的函数是:
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
该函数的作用是,清除定时器 TIMx 的中断 TIM_IT 标志位。使用起来非常简单,比如我们在TIM3 的溢出中断发生后,我们要清除中断标志位,方法是:
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
通过以上几个步骤,我们就可以达到我们的目的了,使用通用定时器的更新中断,来控制
DS1 的亮灭。
四、主要代码
定时器3初始化:
void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
	
	//定时器3初始化
	TIM_TimeBaseStructure.TIM_Period = arr; //自动重装载值
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分割
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  // 向上计数
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //时钟基数单位
 
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能定时器3中断

	//中断优先级NVIC设置
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器


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

定时器3中断服务函数:

void TIM3_IRQHandler(void)   //TIM3中断
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
		{
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清楚中断标志位
		LED1=!LED1;
		}
}

主函数:

 int main(void)
 {		
 
	delay_init();	    	 //延时函数初始化
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断分组
	uart_init(115200);	 //串口初始化为115200
 	LED_Init();			     //LED灯初始化
	TIM3_Int_Init(4999,7199);//定时器初始化,设置为500ms进一次中断
   	while(1)
	{
	
	}	 

 
}

定时器中断时间计算:Touct=(ARR+1)(PSC+1)/TCLK(系统时钟默认为72M)

完整代码:定时器中断实验,每500ms进行一次中断-单片机文档类资源-CSDN文库

下载不需要积分,点赞加收藏评论区留邮箱也能获取完整代码

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-10-22 21:31:28  更:2022-10-22 21:33:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 21:38:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码