STM32定时器[直接用寄存器]

在之前我们讲到过滴答时钟,也就是滴答定时器,这节我们讲TIM定时器。

一、定时器分类

STM32有很多定时器,大家可能会搞混,这里简单讲解一下,定时器有两大类,第一类就是内核中的滴答定时器(SysTick),也叫系统滴答定时器,另一类就是STM32中的定时器,TIM定时器。

STM32定时器:1、滴答定时器(内核中)
            2、TIM定时器(内核外)
              (1):高级控制定时器(TIM1和TIM8)
              (2):通用定时器(TIM2——TIM5)
              (3):基本定时器(TIM6和TIM7)

二、定时器位置

在这里插入图片描述
可以看到,TIM1和TIM8在APB2高速总线上,而剩下的定时器都在APB1低速总线上。

三、定时器计数模式

1、向下计数模式

向下计数模式,就是计数器中填入一个自动加载值,这个值向下计数(倒数)至0,然后产生一个下溢事件,计数器重新装填。滴答定时器只有向下计数模式。
在这里插入图片描述

2、向上计数模式

同理,向上计数模式,就是计数器中填入一个自动加载值,计数器从0开始向上计数(正数)至填入的自动加载值,然后产生一个上溢事件,计数器重新装填。
在这里插入图片描述

3、向上向下双向计数模式(中央对齐模式)

理解了向下计数和向上计数,那么向上向下双向计数模式顾名思义,就是计数器从0计数到 自动装载值-1,产生一个上溢事件,然后向下计数到01,并且产生一个计数器下溢事件,然后再从0开始重新计数。
在这里插入图片描述

四、TIM定时器

1、高级控制定时器

高级控制定时器(TIM1和TIM8)由一个16位的自动装载计数器组成,它由一个可编程的预分频器驱动。
它适合多种用途,包含测量输入信号的脉冲宽度(输入捕获),或者产生输出波形(输出比较、PWM、嵌入死区时间的互补PWM等)。
使用定时器预分频器和RCC时钟控制预分频器,可以实现脉冲宽度和波形周期从几个微秒到几个毫秒的调节。
高级控制定时器(TIM1和TIM8)和通用定时器(TIMx)是完全独立的,它们不共享任何资源。它们可以同步操作。

2、通用定时器

通用定时器是一个通过可编程预分频器驱动的16位自动装载计数器构成。
它适用于多种场合,包括测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM)。
使用定时器预分频器和RCC时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。
每个定时器都是完全独立的,没有互相共享任何资源。它们可以一起同步操作,参

3、基本定时器

基本定时器TIM6和TIM7各包含一个16位自动装载计数器,由各自的可编程预分频器驱动。
它们可以作为通用定时器提供时间基准,特别地可以为数模转换器(DAC)提供时钟。实际上,它们在芯片内部直接连接到DAC并通过触发输出直接驱动DAC。
这2个定时器是互相独立的,不共享任何资源。

五、定时器寄存器

定时器的寄存器比较复杂,在这里只介绍有关任务的寄存器。剩下的寄存器,可以查阅数据手册进行更多的了解

1、TIMx_CR1(控制寄存器 1)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这个寄存器我们经常只使用这两位

  • 第4位:选择计数方式
  • 第0位:使能计数器

2、TIMx_DIER(DMA/中断使能寄存器)

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

这个寄存器只使用第0位

  • 第0位:更新中断

3、TIMx_SR(状态寄存器)

在这里插入图片描述

在这里插入图片描述
状态寄存器我们使用第0位

  • 第0位:用来更新中断标记

4、 TIMx_PSC(预分频器)

在这里插入图片描述
该寄存器用设置对时钟进行分频,然后提供给计数器,作为计数器的时钟,定时器的时钟源有4个:

  1. 内部时钟(CK_INT)
  2. 外部时钟模式1:外部输入脚(TIx)
  3. 外部时钟模式2:外部触发输入(ETR)
  4. 内部触发输入(ITRx):使用A定时器作为B定时器的预分频器
    如上四个时钟源由TIMx_SMCR寄存器设置。

4、 TIMx_ARR(自动重装载寄存器)

在这里插入图片描述

六、代码

一、TIM.c

#include "stm32f10x.h"
#include "led.h"
#include "stdio.h"
#include "tim.h"
int count=0;
//定时中断配置
void TIM4_NVIC(void)			//TIM4中断号为30
{
	SCB->AIRCR|=0x05FA0500; 	//写入钥匙和分组2
	NVIC->ISER[0]|=0x40000000;	//TIM4中断使能
	NVIC->IP[30]|=15<<4;		//TIM4 抢占3 次优先级3
}
//	ARR:重装载值
//	PSC:预分频数
//  定时器4初始化
void TIM4_Init(unsigned int ARR,unsigned int PSC)
{
	RCC->APB1ENR|=1<<2;			//TIM4时钟使能
	TIM4->ARR=ARR;				//重装载值
	TIM4->PSC=PSC;				//预分频数
	TIM4->DIER|=1<<0; 			//允许更新中断
	TIM4->CR1|=0x01; 			//使能定时器 4
	TIM4_NVIC();
}
//定时器4中断服务函数
void TIM4_IRQHandler(void)
{ 
	if(TIM4->SR&(1<<0)) //溢出中断
	{
		LED1=~(LED1);	//绿灯反转	
	} 
	TIM4->SR&=~(1<<0);  //清除中断标志位 
}

二、usart.c

#include "stm32f10x.h"
#include "tim.h"
#include "stdio.h"
#include "usart.h"
#include "delay.h"
//菜单配置
void menu(void)
{
	printf("\r\n请选择你要设置的定时,开启或改变LED:\r\n");
	printf("\r\n1、200ms闪烁一次\r\n");
	printf("\r\n2、500ms闪烁一次\r\n");	 
	printf("\r\n3、1000ms闪烁一次\r\n");	
}
//串口中断配置
void USART1_Init_NVIC(void)
{
	RCC->APB2ENR|=1<<0;			//开启复用时钟
	SCB->AIRCR|=0X05FA5000; 	//写入钥匙和分组2
	NVIC->ISER[1]|=0x0000020;	//USART1(37)中断使能
	NVIC->IP[1]|=0x0000F000;	//USART1 抢3 占3
}
//串口查询式发送
void  USART1_PUT(unsigned char C)
{
	while((!(USART1->SR&(1<<6)))&&(!(USART1->SR&(1<<7))));
	USART1->DR=C;
}
//重定向fputc函数
int fputc(int ch, FILE *f)
{ 
	USART1_PUT(ch);
	return ch;
}
//串口初始化
void USART1_Init(void)
{
	RCC->APB2ENR|=1<<2;			//PA使能
	RCC->APB2ENR|=1<<14;		//串口使能
	
	RCC->APB2RSTR|=1<<14;       //复位串口1
	RCC->APB2RSTR&=~(1<<14);	//停止复位	 
	
	GPIOA->CRH&=0xFFFFF00F;
	GPIOA->CRH|=0x00000490;		//PA9复推,PA10浮空
	
	USART1->BRR|=468<<4|12;		//9600
	USART1->CR1&=~(1<<12);		//8位数据位,1位停止位
	USART1->CR1&=~(1<<10);		//无校验
	
	USART1->CR1|=1<<3;			//发送
	USART1->CR1|=1<<2;			//接收
	
	USART1->CR1|=1<<5;			//使能接收中断
	USART1->CR1|=1<<13;		    //串口使能	
	USART1_Init_NVIC();         //串口中断配置
}
//串口中断服务函数
void USART1_IRQHandler()
{
	unsigned char num;
	num=USART1->DR;
	switch(num)
	{
		case 49:
			printf("\r\n当前为200ms闪烁一次\r\n");
			count=0;
			TIM4_Init(1999,7199);   //定时设置
			break;
		case 50:
			printf("\r\n当前为500ms闪烁一次\r\n");
			count=0;
			TIM4_Init(4999,7199);   //定时设置
			break;
		case 51:
			printf("\r\n当前为1000ms闪烁一次\r\n");
			count=0;
			TIM4_Init(9999,7199);   //定时设置
			break;
	}
}

三、main.c

#include "delay.h"
#include "led.h"
#include "usart.h"
#include "tim.h"
#include "pwm.h"
int main()
{
	System_clock(9);	//系统时钟初始化
	LED_Init();			//LED初始化
	USART1_Init();	    //串口初始化
	menu();				//调用菜单
	while(1)
	{
	    LED0=!LED0;
		SysTick_ms(1000); //红灯1s闪烁一次
	}
}

七、代码效果

在这里插入图片描述
下载程序后串口助手里会显示如图的菜单,我们通过发送对应序号来改变定时器的定时事件,红灯为参考灯,一秒闪烁一次,我们发送了2,也就是定时器为500ms,则绿灯会00ms闪烁一次。

  • 16
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值