一、简介
定时器和计数器是两个名字,但是原理上来说是一样的,都是对脉冲进行计数,区别在于时钟来源,如果来自内部时钟信号,由于内部时钟通常是比较准确的,所以是定时器,如果来自外部引脚,而外部引脚的信号并一定准确,则只对其进行计数,所以是计数器。接下来主要以定时器为主进行简单介绍,计数器类同。
二、时间计算
顾名思义,定时器肯定是和时间有关系的,那么时间是怎么计算的呢,我们以普通51内核为例。如下图(图片来自百度,我觉得他和51不符,所以改了下),通常一个指令周期=2X机器周期=12X时钟周期。而时钟周期又来自晶振。因此晶振频率确定后,那么各个时间也就确定了。
1. 计算内部指令周期
假设晶振频率是12MHz,那么机器周期=1/12MHz=1/12us,指令周期=12*机器周期=1us,也就是说单片机每执行一条指令,最小时间是1us。
2. 计算定时器初值
大多数定时器都可以工作在两种模式,一种是8位(最大计数256次)自动重装模式,一种是16位(最大计数65536次)自动重装模式,由于16位很显然计数或定时的范围是要远远大于8位的,因此,我们以16位模式应用为例,讲解计算方法。定时器在进行计数时是采用向上的方式,也就是说每一个系统信号过来以后,定时器设置的值进行+1,这里就有两个方式:
给定时器设置结束的值,从0开始不断+1,直到达到设置值溢出结束
给定时器设置初始值,从初始值不断+1,直到达到65536溢出结束
我们的51单片机采用了第二种方式,所以给定时器设置值时,我们说设置的是初值。计算公式如下:
初值=65536-定时时长指令周期=65536-定时时长(12*机器周期)
当晶振取值12MHz时,指令周期最小时间就是1us,因此上式也可以写成 初值=65536-定时时长 定时时长取值范围:1~65536us或1~65.536ms
3. STC-12T系列单片机初值
STC单片机很多系列现在都做到了12T,也就是说指令周期最小可以做到等于机器周期,不需要再除以12。因此除了单片机运行速度加快以外,定时精度也更高,计算公式如下:
初值=65536-定时时长指令周期=65536-定时时长机器周期
当晶振取值12MHz时,指令周期最小时间就是1/12us 初值=65536-定时时长/12 定时时长取值范围:1/12~65536/12us或1/12~65.536/12ms
由于12不能整除,所以计算时会有小数点,精度上比普通51会高一个数量级
三、寄存器设置
举个例子,以定时器0、16位自动重装实现1秒定时,STC的C51定时器,需要使用到的寄存器有如下几个:
AUXR:辅助寄存器
TCON:定时器/计数器中断控制寄存器,很多中断的控制寄存器都在这里,定时器中断允许等操作在这里
TMOD:定时器/计数器工作设置寄存器
TH0:定时器初值高8位 除以上寄存器以外,还有两个隐藏寄存器RLTH0和RLTL0,这两个寄存器和TL0、TH0两个寄存器使用同一个地址,设置初值时会自动给这两个寄存器设置值,也就是溢出后,会将这两个隐藏值重新装入TL0、TH0。
四、代码示例
/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC15F4K60S4 系列 定时器0的16位自动重装载模式举例---------------*/
/* --- Mobile: (86)13922805190 -------------- -------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966-------------------------*/
/* --- Web: www.STCMCU.com --------------------------------------------*/
/* --- Web: www.GXWMCU.com --------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序 */
/* 如果要在文章中应用此代码,请在文章中注明使用了STC的资料及程序 */
/*---------------------------------------------------------------------*/
//本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
//若无特别说明,工作频率一般为11.0592MHz
#include "reg51.h"
typedef unsigned char BYTE;
typedef unsigned int WORD;
//-----------------------------------------------
#define FOSC 11059200L
#define T1MS (65536-FOSC/1000) //1T模式
//#define T1MS (65536-FOSC/12/1000) //12T模式
sfr AUXR = 0x8e; //Auxiliary register
sbit P10 = P1^0;
//-----------------------------------------------
/* Timer0 interrupt routine */
void tm0_isr() interrupt 1
{
P10 = ! P10; //将测试口取反
}
void main()
{
AUXR |= 0x80; //定时器0为1T模式
// AUXR &= 0x7f; //定时器0为12T模式
TMOD = 0x00; //设置定时器为模式0(16位自动重装载)
TL0 = T1MS; //初始化计时值
TH0 = T1MS >> 8;
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
EA = 1; //使能全部中断
while (1);
}
五、Proteus仿真
由于Proteus只能仿真普通51内核的单片机,所以上述代码还需要进行简单修改,改成普通51代码。示例:led灯隔一秒亮灭一次,GIF录得有问题
//设晶振为12MHz
#include "reg52.h"
sbit P20 = P2^0;
unsigned char count = 0;
void tm0_isr() interrupt 1
{
//定时器设置为10ms,1s=100*10ms
//这里使用count进行计数,100次即1s
count++;
if(count > 100)
{
P20 = ! P20; //将测试口取反
count = 0; //count清零,进行下次计数
}
}
void main()
{
TMOD &= 0xF1; //设置定时器模式,普通51和stc的不一样,模式不同
TL0 = 0xF0; //设置定时初值
TH0 = 0xD8; //设置定时初值
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
EA = 1;
while (1);
}
上一篇:C51流水灯 running water lamp
下一篇:C51-定时器/计数器
推荐阅读最新更新时间:2024-11-12 17:06
设计资源 培训 开发板 精华推荐
- DC499A,用于 LTC5100EUF 激光驱动器套件的演示板,包括 DC636A 和 DC669A
- LT3460ES5 5V 至 36V 升压转换器的典型应用电路
- 用于汽车EMS的L9788多功能IC评估板
- NUCLEO-L496ZG,STM32 Nucleo-144开发板,带STM32L496ZGT6 MCU,支持Arduino、ST Zio和Morpho
- LT3990EMSE-5 3.3V 降压转换器的典型应用
- 【立创开发板】麦克纳姆轮小车
- LTC3850、2 通道、15A/400kHz 稳压器
- LTM8052AMPY 36Vin、3.3Vout 降压型 CVCC 转换器的典型应用
- A_27_V10基于IPS2电机换向传感器的设计
- LT1533,一款低噪声 24V 至 5V 转换器