06:HAL----定时器

本文详细介绍了STM32F103C8T6定时器的工作原理,包括TIM的分类、计数器的三种计数模式、预分频器的应用以及如何利用HAL库配置和处理中断。还探讨了高级定时器和通用定时器的区别,以及基本定时器控制LED的实例。
摘要由CSDN通过智能技术生成

 前言:

        每来一个TIM 时钟CNT计数器就记一个数,记到某一个程度就会产生溢出。然后ARR就会装载到CNT计数器里面

一:TIM

1:介绍

        TIM(Timer)定时器

        定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断

        16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时 (计数器、预分频器、自动重装寄存器构成时基单元)

        不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能

         根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型

时间计算:频率 = CK_PSC (72MHZ) / (PSC+1) / (arr+1)     周期= 1 / 频率

最大计数时间:72000 000/65536/65536=0.0167638063430786-----频率

周期:1/0.0167638063430786=59.6523235555556-------最大计数周期

PSC和ARR都为16 位  2^16-1

2:定时器的分类

 STM32F103C8T6定时器资源:TIM1、TIM2、TIM3、TIM4

我们STM32F1C8T6系列中的定时器全部都是16位的,也就以为着最大计数位2^16-1=65535


高级定时器比通用定时器多了一个重复次数寄存器;

        每个定时器都会有4个通道;定时器1和定时器2多了一个ETR通道;高级定时器1有3个互补通道:1,2,3。都涉及了MDA操作

3:计数器

计数器分为3种计数方式

         自动重装载寄存器=自动重装载寄存器+1  可以看到了自动重装载的值(ARR) 加到36,再加一个数(实际就是加到了37);才溢出

自动重装载寄存器=自动重装载寄存器+1  可以看到了自动重装载的值(ARR) 减到0,再减一个数;才溢出           和上面的 递增计数模式一样

        自动重装载寄存器=自动重装载寄存器; 和上面的2种计数方法不同,少了一个1;arr写多少就会在多少溢出 

        当计数器配置为中央对齐模式或编码器模式时,DIR位为只读。

3:基本定时器

A:介绍

        注意我们使用的STM32F103C8T6这个型号的版主没有基本定时器,我们使用其他型号的STM32板子,来完成我们基本定时器的实验

1 :  预分频器+CNT计数器+自动重装载寄存器=时基单元

2 : 基本定时器只能选择内部时钟;他们都为16位的

预分频器 : 可以对72MHZ的计数时钟进行预分频处理; 对输入的基准频率提前进行一个分频的操作

eg : 预分频器写0,那就是不分频,或者说是1分频 ; 输出频率=输入频率=72MHz

预分频器写1,那就是2分频,输出频率(实际分频系数)=输入频率/2=36MHz

预分频器写2,那就是3分频,输出频率(实际分频系数)=输入频率/3= 24MHz

所以预分频器的值和实际的分频系数相差了1;  实际分频系数=预分频器的值+1

递增计数器 : 计数器可以对预分频后的计数时钟进行计数,预分频器每来一个上升沿计数器就+1

        所以计数器的值在计时过程中会不断地自增运行,直到达到目标值(自动重装载寄存器)然后产生中断,然后在重新开始计数

自动重装载寄存器(固定值) : 储存的是我们的计数目标,产生中断的目标值,(当计数器达到目标值就产生中断)                                                自动重装载寄存器=自动重装载寄存器+1

流程: 基准时钟------->预分频器------>计数器<--------->自动重装载计数器

计数器不断自增,会和自动重装载寄存器比较,当两个的值相同时,产生更新事件中断和DMA请求;

cpu会响应更新中断

B:时间计算

溢出时间其实实际上就是周期

C:HAL库配置 

 要使能定时器定时的话,就必须打开中断使能也就是3,CNT==ARR溢出产生的中断

D:HAL库函数

UEV:只有一种事件引起中断或者DMA请求,即计数器上溢的更新事件(UEV),就是CNT=ARR是发生的溢出事件。

中断ISR:就是中断号,在汇编语言中写,比如下面的:

void TIM2_IRQHandler()
{}

4:通用定时器

A:介绍

外部时钟模式:常用情况-->A:对外部电平高低的变换进行一个计数 

B:选择计数器时钟源

 

5:高级定时器

6:定时器的基本结构

7:HAL函数总结

其他通用操作函数

        自动重装载值(AutoReloadPreload):        X.Init.AutoReloadPreload,如果我们中间需要改变ARR的值需要写这个:

1:DISABLE(失能,关闭缓存区):如果我们中途需要改变ARR的值,关闭缓存区,ARR会直接变为改的数据,并CNT==改的数据时发生更新中断。

2:ENABLE(使能,打开缓存区):打开缓存区,ARR值不会立即改变,而是在下次把新的ARR值写入,当CNT=ARR时发生溢出

在代码总结事件中验证


中断处理

中断事件类型


HAL_TIM_IRQHandler和中断回调函数

二:定时中断功能

定时器有很多功能:07:HAL------定时器功能(输出比较PWM)

CSDNicon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/137024445


08:HAL---定时器功能(输入捕获功能)

CSDNicon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/137085008

三:代码

A:基本定时器

使用基本定时器控制LED,注意我们STM32C8T6这个板子没有基本定时器,需要使用其他的板子

这个是直接计算的周期

 使用的是内部时钟源

TIM_HandleTypeDef g_timx_handle;

/* 定时器中断初始化函数 */
void btim_timx_int_init(uint16_t arr, uint16_t psc)
{
    g_timx_handle.Instance = TIM6;
    g_timx_handle.Init.Prescaler = psc;
    g_timx_handle.Init.Period = arr;
    HAL_TIM_Base_Init(&g_timx_handle);
    //CNT==ARR溢出产生的中断
    HAL_TIM_Base_Start_IT(&g_timx_handle);
}

/* 定时器基础MSP初始化函数 */
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM6)
    {
        __HAL_RCC_TIM6_CLK_ENABLE();
        HAL_NVIC_SetPriority(TIM6_IRQn, 1, 3);
        HAL_NVIC_EnableIRQ(TIM6_IRQn);
    }
}

/* 定时器6中断服务函数 */
void TIM6_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&g_timx_handle);
}

/* 定时器溢出中断中断回调函数 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM6)
    {
        LED0_TOGGLE();
    }
}

ETR刹车清除

A:ETR刹车

#include "stm32f1xx_hal.h"
#include "rcc.h"
#include "led.h"
#include "delay.h"
#include "OLED.h"
#include "wwdg.h"
#include "key.h"
#include "IC.h"
#include <stdarg.h>
#include "stdio.h"
#include "UART.h"

uint16_t num=0;
uint16_t zone_bit=1;
int main(void)
{
	HAL_Init();                         /* 初始化HAL库 */
  sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
  delay_init(72);                     /* 延时初始化 */

	Uart_Init(115200);
	Timer1_Init(2000-1,36000-1);      // 0.5
	

	 while (1)
    {
			
			
	
				
    }
}
#include "stm32f1xx_hal.h"
#include "OLED.h"

#include <stdarg.h>
#include "stdio.h"
#include "UART.h"


TIM_HandleTypeDef TIM1_Handle;


	TIM_OC_InitTypeDef TIM_OC_Init={0};
	TIM_OC_InitTypeDef TIM_OC_Init4={0};

void Timer1_Init(uint16_t arr, uint16_t psc, uint8_t rep)
{
	
	TIM_ClearInputConfigTypeDef TIM_ClearInputConfig={0};
	TIM1_Handle.Instance = TIM1;
	TIM1_Handle.Init.Prescaler = psc;
	TIM1_Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
	TIM1_Handle.Init.Period = arr;
	TIM1_Handle.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;    
	TIM1_Handle.Init.RepetitionCounter = rep;   //重复计数器
	TIM1_Handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; //自动重装载值

	HAL_TIM_PWM_Init(&TIM1_Handle);	
	__HAL_TIM_CLEAR_FLAG(&TIM1_Handle, TIM_FLAG_UPDATE);
	
	
	
	
	
	//PWM1 --CNT <CCRX  :输出有效电平
	TIM_OC_Init.OCMode=TIM_OCMODE_PWM1;    //输出比较的模式
	TIM_OC_Init.Pulse=400;                   //比较值(CCR)
	TIM_OC_Init.OCPolarity=TIM_OCPOLARITY_HIGH;    //输出极性 (高电平有效)
	TIM_OC_Init.OCFastMode=TIM_OCFAST_DISABLE;     //快速模式
	HAL_TIM_OC_ConfigChannel(&TIM1_Handle,&TIM_OC_Init,TIM_CHANNEL_1);
	//HAL_TIM_PWM_ConfigChannel(&TIM1_Handle,&TIM_OC_Init,TIM_CHANNEL_1);
	
		//PWM1 --CNT <CCRX  :输出有效电平
	TIM_OC_Init4.OCMode=TIM_OCMODE_PWM1;    //输出比较的模式
	TIM_OC_Init4.Pulse=400;                   //比较值(CCR)
	TIM_OC_Init4.OCPolarity=TIM_OCPOLARITY_HIGH;    //输出极性 (高电平有效)
	TIM_OC_Init4.OCFastMode=TIM_OCFAST_DISABLE;     //快速模式
	HAL_TIM_PWM_ConfigChannel(&TIM1_Handle,&TIM_OC_Init4,TIM_CHANNEL_4);

	
	
	TIM_ClearInputConfig.ClearInputState=ENABLE;   //RTC清除的状态
	TIM_ClearInputConfig.ClearInputSource=TIM_CLEARINPUTSOURCE_ETR;    //选择清除源
	TIM_ClearInputConfig.ClearInputPolarity=TIM_CLEARINPUTPOLARITY_INVERTED;  //极性:不反向低电平触发
	TIM_ClearInputConfig.ClearInputPrescaler=0;    //分频因子:只能为0
	TIM_ClearInputConfig.ClearInputFilter=0x8;     //滤波器
	HAL_TIM_ConfigOCrefClear(&TIM1_Handle,&TIM_ClearInputConfig,TIM_CHANNEL_1);
	
	HAL_TIM_PWM_Start(&TIM1_Handle,TIM_CHANNEL_1);	
	HAL_TIM_PWM_Start(&TIM1_Handle,TIM_CHANNEL_4);	
	
	
	

}

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{		
	if(htim->Instance==TIM1)
	{
		__HAL_RCC_TIM1_CLK_ENABLE(); 

		__HAL_RCC_GPIOA_CLK_ENABLE() ;
	
		

		GPIO_InitTypeDef GPIO_InitType;
		GPIO_InitType.Pin = GPIO_PIN_8|GPIO_PIN_11;;
		GPIO_InitType.Mode = GPIO_MODE_AF_PP;  
		GPIO_InitType.Speed = GPIO_SPEED_FREQ_LOW;
		HAL_GPIO_Init(GPIOA,&GPIO_InitType);	
		
		GPIO_InitType.Pin = GPIO_PIN_12;
		GPIO_InitType.Mode = GPIO_MODE_AF_INPUT;  
		GPIO_InitType.Pull = GPIO_PULLUP;
		HAL_GPIO_Init(GPIOA,&GPIO_InitType);
				
	}	
}

按下为低电平 

定时器ETR清除

可以和我们的高级定时器做下对比:

高级定时器:

10:HAL---高级定时器_高级定时器重复计数器-CSDN博客

  • 10
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值