基本定时器TIM6实现精确延时

发布时间 2023-12-03 11:20:25作者: 一蓑烟雨任平生&wf

1、基本定时器的特点

(1)、16位自动重装载累加计数器
(2)、16位可编程(可实时修改)预分频器,用于对输入的时钟按系数为1~65536之间的任意数值
image
!!!注意基本定时器只有向上计数模式,不要被框图和数据手册上的一些描述误导,基本定时器寄存器中根本没有计数模式的配置相关位。

2、基本定时器的配置

①TIMx_CR1寄存器bit0: CEN 用于关闭或开启定时器
image

②TIMx_CNT寄存器:bit15-0:计数器数值
③TIMx_PSC寄存器:bit15-0:预分频器数值
④TIMx_ARR寄存器:bit15-0: 自动重装载数值

3、基本定时器实现精确延时的原理

image
实现时要注意以下两点:
①不要使用库函数,全部使用寄存器实现。原因——效率。
②可对ts进行适当的校正(毕竟程序的执行是要耗费时间的),实现更加精准的延时。
通过示波器测试,ts校正之后固有误差为0.68us,基本满足1us内误差的需求

4、最后附上代码

timer6_delay.h

点击查看代码
/*******************************************
	*文件名 :  timer6_delay.h
	*作   者:  WF
	*修改时间: 2021.12.21
	*版   本:  v2.0
    *说   明:  定时器6延时函数头文件
*******************************************/

#ifndef _TIMER6_DELAY_H
#define _TIMER6_DELAY_H

#include "stm32f10x.h"

void Timer6_Delay_Init(void);
void Timer6_Delay_Us(u16 us);
void Timer6_Delay_Ms(u16 ms);
void Timer6_Delay_Sec(u16 sec);

#endif

timer6_delay.c

点击查看代码
/*******************************************
	*文件名 :  timer6_delay.c
	*作   者:  WF
	*修改时间: 2021.12.21
	*版   本:  v2.0
    *说   明:  定时器6延时函数配置源文件
*******************************************/

#include "timer6_delay.h"

/* 预分频系数 */
#define PSC (2)
/* us倍乘因子 */
#define FAC_US (72 / PSC)

/*
	*函数名: Timer6_Delay_Init()
	*功  能: 定时器6延时初始化函数
	*参  数: 无
	*返回值: 无
	*作  者: WF
	*日  期: 2021.08.13
*/
void Timer6_Delay_Init(void)
{

	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); //使能定时器2时钟

	/* 配置定时器2 */
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置为向上计数模式
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;			//不分频
	TIM_TimeBaseInitStructure.TIM_Period = 0xffff;									//自动装载初值
	TIM_TimeBaseInitStructure.TIM_Prescaler = PSC - 1;							//预分频系数
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;						//高级定时器必须配置
	TIM_TimeBaseInit(TIM6, &TIM_TimeBaseInitStructure);							//初始化定时器
}

/*
	*函数名: Timer6_Delay_Us()
	*功  能: 定时器6微秒级延时函数
	*参  数: us:微秒数
	*返回值: 无
	*作  者: WF
	*日  期: 2021.08.13
*/
void Timer6_Delay_Us(u16 us)
{
	u16 temp = 0;
	u16 ts = us * FAC_US; /* 时钟数 = us数 * us倍乘因子 */
	ts -= 25;             /* 时钟数校正 */

	TIM6->ARR = 0xffff;   /* 设置ARR为0xffff防止溢出 */
	TIM6->CNT = 0;			  /* 清零计数器 */

	/* 开启定时器6 */
	TIM6->CR1 |= TIM_CR1_CEN;

	/* 延时等待 */
	while (ts > temp)
	{
		temp = TIM6->CNT;
	}

	/* 关闭定时器6 */
	TIM6->CR1 &= ~TIM_CR1_CEN;
}

/*
	*函数名: Timer6_Delay_Ms()
	*功  能: 定时器6毫秒级延时函数
	*参  数: ms:毫秒数
	*返回值: 无
	*作  者: WF
	*日  期: 2021.08.13
*/
void Timer6_Delay_Ms(u16 ms)
{
	while(ms--)
	{
		Timer6_Delay_Us(1000);
	}
}


/*
	*函数名: Timer6_Delay_Sec()
	*功  能: 定时器6秒级延时函数
	*参  数: sec:秒数
	*返回值: 无
	*作  者: WF
	*日  期: 2021.08.13
*/
void Timer6_Delay_Sec(u16 sec)
{
	while(sec--)
	{
		Timer6_Delay_Ms(1000);
	}
}