知不足而奋进 望远山而前行![](https://img-blog.csdnimg.cn/direct/00ceb251b30b4e6385e95685b3926f56.gif)
前言
在嵌入式系统开发中,定时器是一项关键功能,它能够在特定时间间隔内执行任务或者产生中断信号。了解定时器的原理和编程操作对于掌握嵌入式系统开发至关重要。本文将介绍定时器的基本概念、配置方法以及一个简单的定时器案例,帮助你理解和掌握定时器的使用。
目标
- 理解定时器
- 掌握定时器的编程操作
内容
定时器
定时器是一种计时装置,通常由一个晶体振荡器提供时钟信号,可以计时一定的时间后执行相应的操作。在单片机中,定时器一般是由计数器和时钟源组成的,可以用来产生一定时间间隔的中断信号,或者用于测量输入信号的周期和占空比等。定时器通常具有多种工作模式和计数方式,可以灵活地应用于各种场合。
STC8H内置了5个16位定时器:T0,T1,T2,T3,T4.
Timer案例
使用定时器,控制板载LED高低电平输出。
#include "Config.h"
#include "Timer.h"
#include "GPIO.h"
#include "NVIC.h"
void GPIO_config(void) {
GPIO_InitTypeDef GPIO_InitStructure; //结构定义
GPIO_InitStructure.Pin = GPIO_Pin_3; //指定要初始化的IO,
GPIO_InitStructure.Mode = GPIO_PullUp; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
GPIO_Inilize(GPIO_P5, &GPIO_InitStructure); //初始化
}
//int arr[];
//int counter = 3;
void TIMER_config(void) {
TIM_InitTypeDef TIM_InitStructure; //结构定义
//定时器0做16位自动重装, 中断频率为100000HZ,中断函数从P6.7取反输出50KHZ方波信号.
TIM_InitStructure.TIM_Mode = TIM_16BitAutoReload; //指定工作模式, TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T; //指定时钟源, TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
TIM_InitStructure.TIM_ClkOut = DISABLE; //是否输出高速脉冲, ENABLE或DISABLE
TIM_InitStructure.TIM_Value = 65536UL - (MAIN_Fosc / 1000UL); // 初值,指定Timer频率 1000hz (每秒执行1000次,每次1ms(周期))
// 不要小于367hz (2.7ms周期)
// 不要大于1 000 000hz 一百万 (1us周期)
TIM_InitStructure.TIM_Run = ENABLE; //是否初始化后启动定时器, ENABLE或DISABLE
Timer_Inilize(Timer0,&TIM_InitStructure); //初始化Timer0 Timer0,Timer1,Timer2,Timer3,Timer4
NVIC_Timer0_Init(ENABLE,Priority_0); //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}
void main(){
GPIO_config();
TIMER_config();
// 开启全局中断
EA = 1;
P53 = 0; // 熄灯
while(1);
}
//========================================================================
// 函数: Timer0_ISR_Handler
// 描述: Timer0中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-23
//========================================================================
void Timer0_ISR_Handler (void) interrupt TMR0_VECTOR //进中断时已经清除标志
{
// TODO: 在此处添加用户代码
P53 = ~P53;
}
定时器配置理解
工作模式
工作模式指的是计数方式,timer的计数是在主频计数的基础上,来进行数数的。timer有16位的计数器,通过计数器来计数来确定定时器运行的时长,在关键位置触发定时中断。
- 16位自动重装载模式:可以被设置成定时或者计数两种模式,每当定时器溢出时就会触发中断或者输出信号。
- 16位不可重装载模式:计数值达到设定值后,定时器就会停止计数,需要重新初始化才能继续计数。
- 8位自动重装载模式:8位计数器溢出时触发中断或输出信号。
- 不可屏蔽中断的16位自动重装载模式:16位计数器溢出时触发中断或输出信号,并且可以通过软件或硬件方式清除定时器计数器的值。
通常使用16位自动重装载模式.
中断配置
中断配置是为了打开中断开关的,从而可以触发中断回调的,如果不配置,将无法触发中断回调。
时钟源
可配置的是重要有两个:
- 1T: 跟随主频。
- 12T: 进行12分频。
是否输出高速脉冲
TIM_ClkOut
,可以配置DISABLE
或者ENABLE
如果配置ENABLE
,则P3.5
端口会同步输出时钟脉冲
时钟周期设置
时钟周期指的是1秒钟执行多少次timer中断。
TIM_InitStructure.TIM_Value = 65536UL - (MAIN_Fosc / 10000UL);
以上配置中,TIM_InitStructure.TIM_Value
最终会转化位寄存器配置。
其中,10000UL
表示的就是时钟周期,意思就是这个timer回调1秒钟要调用 10000
次。
注意时钟周期的取值范围,通过以上数学公式,(MAIN_Fosc / Timer频率)
不能大于65536UL
;理论上时钟周期可以无限大,经过测试,最大值为500000UL
,也就是2us
调用1次。但是,我们要考虑到,如果timer设置到这么高的频率,你在回调中执行的代码时长就不能超过这个值。如果是24M主频,1个时钟周期为 1/24MHz=41.67ns,但是一个指令通常由多个时钟周期组成,一段代码又由多个指令组成,这么一算,可做的操作就很少了。因此我们不要设置得那么大。
启动配置
配置定时器的启动
总结
通过本文的学习,你应该对定时器有了更深入的理解,并掌握了定时器的编程操作。我们学习了定时器的基本概念,包括工作模式、中断配置、时钟源以及时钟周期设置等内容。同时,我们也通过一个实际的案例学习了如何使用定时器来控制板载LED的高低电平输出。定时器作为嵌入式系统中常用的功能模块之一,在实际应用中具有广泛的用途,希望本文对你的学习有所帮助,为你在嵌入式系统开发领域的探索提供一定的指导。