STM32第六课:定时器


需求

1.使用系统滴答定时器实现LED灯的翻转(0.5s翻转一次)。
2.实现定时器6的定时功能,让LED2以500ms一次的频率闪烁。
3.配置定时器2,实现一个1s的定时功能(到时间LED4翻转)。


一、系统定时器

STM32里面有几个定时器:
高级定时器:TIM1,8
通用定时器: TIM2,3,4,5
基本定时器:TIM6,7
系统定时器(滴答定时器):Systick

1.配置流程

由于系统定时器在内核中,所以想要配置系统定时器的相关寄存器,需要打开内核手册。
在这里插入图片描述
首先要打开时钟源和分频器
在这里插入图片描述
由内核手册可知该寄存器的0,1,2位均要置1。
代码如下:

	//系统滴答定时器定时 1ms
	//时钟源和分频器 72m  7	2000 000
	SysTick->CTRL |= 0x1<<2;
	//计数器 打开
	SysTick->CTRL |= 0x1<<0;
	//打开系统定时器中断
	SysTick->CTRL |= 0x1<<1;

配置完成后,还需要配置重载值
在这里插入图片描述
在这里插入图片描述
代码如下:

	SysTick->LOAD = 72000-1;//计数器计数从72000-1计数到0产生中断

或者直接使用内核写好的函数

SysTick_Config(72000);  //1ms中断进入一次

SysTick_Config(72000)代表:72000*(1/72MHz)=1/1000=1(ms)。即定时为1ms。

最后的NVIC可配可不配。

2.时间轴的实现

配置完系统定时器后,我们就可以实现一个类似事件轴的东西,比单纯使用delay函数更准确。
代码如下:
delay.c 里加入void SysTick_Handler(void)函数

void SysTick_Handler(void)		//1ms调用一次
{
		systicktime++;
	  led1_count++;
		led2_count++;
}

在main函数中外部声明一下 led1_count和led2_count。
这样我们就得到了一个1ms计数一次的时间轴,当我们需要时只需要在主函数中判断计数即可。

3.主函数需求实现

		if(led1_count>=500){//过去500ms
			led1_count=0;
			/***LED1闪烁任务***/
			Led_Toggle(1);
		}
		if(led2_count>=700){//过去500ms
			led2_count=0;
			/***LED2闪烁任务***/
			Led_Toggle(2);
		}

二、基本定时器

STM32中定时器分类以及相关作用
高级控制定时器:TIM1、TIM8 定时+输入捕获+输出比较+死区+互补PWM
通用定时器:TIM2、3、4、5 定时+输入捕获+输出比较
基本定时器:TIM6、7 定时

定时器配置的大致流程:
1、时钟源 RCC内部的时钟 APB1 36M APB1*2 = 72M
2、配置时需要打开APB1上TIM2、3、4、5、6、7或APB2上 TIM1、8的时钟(根据需求)
3、配置分频器:根据实际情况计算,不能超过65536 (TIMx_PSC)
4、配置重装载值:根据实际情况计算,不能超过65536(TIM_ARR)
5、打开计数器:
TIM_CR1(位0,位2) TIMx_DIER位0;
6、使能中断通道、配置中断优先级。
7、写一个中断服务函数。

1.TIM6定时器的配置

首先创建一个tim.c和tim.h文件
在.c中创建void TIM6_Config(uint16_t psc,uint16_t reload)函数
然后打开手册找到TIM6定时器

在这里插入图片描述
由图中可以看到,只要配置好分频器,计数器自动重装载寄存器即可。

1.时钟源使能

首先还是老规矩,先打开时钟源,顺着手册看TIM6的时钟源是在APB1还是APB2上。

在这里插入图片描述
在这里插入图片描述

从手册中得知该时钟源是在APB1总线上,所以将其RCC_APB1第四位置1即可。

RCC->APB1ENR |= 0x01<<4;

2.分频器

在这里插入图片描述
由于该分频器是自动+1,所以传参时应-1。

	//分频器
	TIM6->PSC = psc-1;

3.装载值

在这里插入图片描述
在这里插入图片描述
由于该寄存器是从0开始重载,所以需要初始值-1

	//装载值
	TIM6->ARR = reload-1;

4.计数器使能

直接找到手册里的TIM6控制寄存器
在这里插入图片描述在这里插入图片描述
可知将TIM6 和TIM7 控制寄存器1的第0位置1即可使该计数器使能。

	//计数器使能
	TIM6->CR1 |= 0x01<<0;

5.打开定时器中断并配NVIC

在这里插入图片描述
在这里插入图片描述
由手册可知,将TIM6 和TIM7 DMA/中断使能寄存器(TIMx_DIER)的第0位置1即可打开。
最后配置一下NVIC即可

	//打开定时器中断
	TIM6->DIER |= 0x01<<0;
	NVIC_SetPriority(TIM6_IRQn,5);//设置优先级0~15
	NVIC_EnableIRQ(TIM6_IRQn);//使能中断通道

6.中断函数的编写

在这里插入图片描述

先在.s文件中找到TIM6对应的中断函数复制,然后看TIM6的SR是如何判断的。
由图可知,当TIM6->SR的第0位为1时产生中断。

void TIM6_IRQHandler()
{
		//判断中断标志位
	if((TIM6->SR&(0x01<<0))!=0){

	//清理中断标志位
	TIM6->SR &= ~(0x01<<0);
	printf("定时器中断\r\n");
	}
}

2.需求编写

首先在主函数中调用 TIM6_Config();
由于需求是让LED2以500ms一次的频率闪烁,所以此时函数中应填写

	  TIM6_Config(7200,5000);

系统时钟是72Mhz,等于72000000hz。除于7200,等于0.1ms计数一次。
5000代表计数5000次定时器报警,也就是说500ms产生中断一次
最后,在产生中断时翻转LED2即可。

中断函数代码为:

void TIM6_IRQHandler()
{
		//判断中断标志位
	if((TIM6->SR&(0x01<<0))!=0){
	//翻转LED2
	Led_Toggle(2);
	//清理中断标志位
	TIM6->SR &= ~(0x01<<0);
	printf("定时器中断\r\n");
	}
}

三、通用定时器

TIM2

跟TIM6配置一样
照着流程走即可
需求实现代码如下:
main.c

#include "stm32f10x.h"
#include "usart.h"
#include "stdio.h"
#include "led.h"
#include "delay.h"
#include "tim.h"

int main()
{
		NVIC_SetPriorityGrouping(5);//两位抢占两位次级
	  TIM2_Config(7200,10000);	
    Usart1_Config(); 
    Led_Init();
    while(1)
    {	
    }
}

void TIM2_IRQHandler()
{
		//判断中断标志位
	if((TIM2->SR&(0x01<<0))!=0){
	//翻转LED2
	Led_Toggle(2);
	//清理中断标志位
	TIM2->SR &= ~(0x01<<0);
	printf("定时器中断\r\n");
	}
}

tim.c

#include "stm32f10x.h"

/*
配置定时器的基本功能
参数1psc:分频系数
参数2reload:装载值
*/

void TIM6_Config(uint16_t psc,uint16_t reload)
{
	//时钟源APB1*2=72MHz,时钟源使能
	RCC->APB1ENR |= 0x01<<4;
	//分频器
	TIM6->PSC = psc-1;	
	//装载值
	TIM6->ARR = reload-1;
	//计数器使能
	TIM6->CR1 |= 0x01<<0;
	//打开定时器中断
	TIM6->DIER |= 0x01<<0;
	NVIC_SetPriority(TIM6_IRQn,5);//设置优先级0~15
	NVIC_EnableIRQ(TIM6_IRQn);//使能中断通道
}

void TIM2_Config(uint16_t psc,uint16_t reload)
{
	//时钟源APB1*2=72MHz,时钟源使能
	RCC->APB1ENR |= 0x01<<0;
	//分频器
	TIM2->PSC = psc-1;	
	//装载值
	TIM2->ARR = reload-1;
	//计数器使能
	TIM2->CR1 |= 0x01<<0;
	//打开定时器中断
	TIM2->DIER = 0x01<<0;
	NVIC_SetPriority(TIM2_IRQn,3);//设置优先级0~15
	NVIC_EnableIRQ(TIM2_IRQn);//使能中断通道
}

tim.h

#ifndef _TIM_H_
#define _TIM_H_
#include "stm32f10x.h"

void TIM6_Config(uint16_t psc,uint16_t reload);
void TIM2_Config(uint16_t psc,uint16_t reload);
#endif
		

总结

1.了解了STM32中定时器的种类及作用。
2.学会了配置及使用系统定时器,基本定时器和通用计时器。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值