概述
清 0 则用作定时器(对内部系统时钟进行计数),置 1 用作计数器(对引脚 T0/P3.4 外部脉冲进行计数)。
定时功能:内部时钟的频率,再结合计数,就可以计算这段时间所用的时间。
寄存器
辅助寄存器 1(AUXR)
默认都是 12T。
中断与时钟输出控制寄存器(INTCLKO)
如果选择时钟输出,必须要将对应的 IO 口初始化。
单位
==1M 是 1 百万,就是 1000000。==
计数单位应包含整数部分和小数部分两大块,并按以下顺序排列:京、千兆、百兆、十兆、兆、千亿、百亿、十亿、亿、千万、百万、十万、万、千、百、十、个(一)、十分之一、百分之一、千分之一。
M 的英文全称是 million ,意思是百万,1M 就是 1 百万,就是 1000000,通常商业中说的 M 就是十进制的 M,即一百万。另外我们通常所说的流量中的 M 不是 1 百万,而是 1024KB,因为我们流量的计算用的是二进制。
- 1GHz=1000MHz,1MHz=1000kHz,1kHz=1000Hz
- 1s=1000ms,1 ms=1000μs,1μs=1000ns
- s(秒)、ms(毫秒)、μs(微秒)、ns(纳秒)---
时钟频率 时钟周期
- 5MHz 200ns
- 10MHz 100ns
- 20MHz 50ns
- 25MHz 40ns
- 33MHz 30ns
- 40MHz 25ns
- 50MHz 20ns
- 66MHz 15ns
- 80MHz 12ns
- 100MHz 10ns
- 120MHz 8.3ns
- 133MHz 7.5ns
时钟周期与时钟频率互为倒数, 我们可以找出以下关系:
- 时钟频率 时钟周期
- 1Hz 1s
- 1KHz 1ms
- 1MHz 1μs
- 1GHz 1ns---
知道这些,我们就能很快换算周期与频率.
-
比方 10KHz, 那么就是 1/10 = 0.1ms, 即 100μs.
-
比方 100ns, 那么就是 1/100 = 0.01GHz, 即 10MHz.
定时器初值计算
1、时钟周期,也称为振荡周期:定义为时钟脉冲的倒数,在单片机中也就等于晶振的倒数。
51 单片机中把一个时钟周期定义为一个节拍(用 P 表示),2 个节拍定义为状态周期(用 S 表示)
时钟周期是单片机中最小的时间单位。
eg:12M 晶振的单片机,时钟周期=振荡周期=1/12 us。2、机器周期:定义为完成一项基本操作所需要的时间,称为机器周期。
在计算机中,为了方便管理,把一条指令的执行过程分为若干个阶段,每个阶段去执行一项基本操作。
如:取指令,存储器读,存储器写等。
在 51 单片机中 1 个机器周期由 6 个状态周期组成,也就是 12 个时钟周期=12 x 1/12 us =1 us
定义机器周期是因为时钟周期时间太短,根本做不了什么。3、指令周期:定义为执行一条指令所需的时间。
通常,包含一个机器周期的指令称为单周期指令,比如 MOV 指令,CLR 指令等。
包含两个机器周期的指令称为双周期指令。
另外还有四周期指令。
相比于delay计时,delay是要直接让单片机做空循环,死等。而定时器则是利用定时器的溢出间隔,如果时间上不够,可以在溢出中断中配合软件计数器来实现。 前者浪费cpu,后者更高效
最大频率
如果是 24M 的晶振,最大值为 2M;
定时器(外部脉冲计数)
自动重新装载 VALUE 的值,当来了一个脉冲加一,溢出产生中断。
计算公式
定时器周期
定时器频率
定时计数
**12T:**65535-系统时钟/12/定时周期
程序
参考程序
#include "STC8A_Timer.h"
#include "STC8A_NVIC.h"
/******************** 主函数**************************/
void main(void)
{
Timer_config();
EA = 1;
while (1);
}
/************************ 定时器配置 ****************************/
void Timer_config(void)
{
TIM_InitTypeDef TIM_InitStructure; //结构定义
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 / 100000UL); //初值,
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
}
//========================================================================
// 函数: Timer0_ISR_Handler
// 描述: Timer0中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2020-09-23
//========================================================================
void Timer0_ISR_Handler (void) interrupt TIMER0_VECTOR //进中断时已经清除标志
{
P27 = ~P27;
}
测高电平脉宽
只有定时器 0 和定时器 1 可以设置 GATE 位。
- 配置辅助和控制寄存器,清空计数寄存器。
- 等待低电平结束,高电平触发时,开启计数
- 启用下降沿中断,进入中断程序,执行对应的功能
定时器做波特率发生器
串口和定时器解决方法
定时器 + 计数器
u8 timer_count=0; //定时器计数
u8 isFlag=0; //显示标志位
double ttl_count=0; //一秒钟有多少个周期数
double temp_freq=0; //暂时周期数
void main()
{
Timer_config();
EA = 1;
while(1)
{
if(isFlag == 1)
{
LCD_DISPLAY_NUM(0,0,temp_freq);
//temp_freq=0;
DigDisplayNum((long)(temp_freq));
isFlag=0;
}
}
}
void Timer_config(void)
{
//P34
TIM_InitTypeDef TIM_InitStructure; //结构定义
TIM_InitStructure.TIM_Mode = TIM_16BitAutoReload; //指定工作模式, TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_12T; //指定时钟源, TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
TIM_InitStructure.TIM_ClkOut = DISABLE; //是否输出高速脉冲, ENABLE或DISABLE
TIM_InitStructure.TIM_Value = 65536UL - (MAIN_Fosc / (50UL * 12 )); //初值,
TIM_InitStructure.TIM_Run = ENABLE; //是否初始化后启动定时器, ENABLE或DISABLE
Timer_Inilize(Timer0,&TIM_InitStructure); //初始化Timer0 Timer0,Timer1,Timer2,Timer3,Timer4
NVIC_Timer0_Init(ENABLE,Priority_2); //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
//P12
TIM_InitStructure.TIM_Mode = TIM_16BitAutoReload; //指定工作模式, TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_Ext; //指定时钟源, TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
TIM_InitStructure.TIM_ClkOut = DISABLE; //是否输出高速脉冲, ENABLE或DISABLE
TIM_InitStructure.TIM_Value = 0; //初值,
TIM_InitStructure.TIM_Run = ENABLE; //是否初始化后启动定时器, ENABLE或DISABLE
Timer_Inilize(Timer2,&TIM_InitStructure); //初始化Timer0 Timer0,Timer1,Timer2,Timer3,Timer4
NVIC_Timer2_Init(ENABLE,Priority_3); //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}
void Timer0_ISR_Handler (void) interrupt TIMER0_VECTOR //进中断时已经清除标志
{
timer_count ++;
if(timer_count == 50)
{
temp_freq = (long)(ttl_count*65536+TH2*256+TL2); //取出脉冲数
isFlag=1; //显示标志位
timer_count=0; //定时计数清0
ttl_count=0; //脉冲计数
//对值进行清零前,需要停止计数
Timer2_Stop();
TH2 =0;
TL2 =0;
//清完零之后继续计数
Timer2_Run(1);
T2_Load(0);
LCD_Clear();
}
}
void Timer2_ISR_Handler (void) interrupt TIMER2_VECTOR //进中断时已经清除标志
{
T2_Load(0);
ttl_count++;
}
注意事项
- 一定要记得==EA=1==
- 使用时钟输出时,要配置 IO 口。
- 修改定时器计数器的值的时候,需要关闭计数器,之后再重新装载初始值,开启计数器。
其他想法
- 定时器的输出口,可以连接 LED 灯,方便调试。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于