//首先定时器根据时钟的输出信号每隔一段时间对计数单元进行加1
//当计数单元加1到设定提醒时间就进行中断申请,使程序跳转到中断函数中执行
//1.工作模式寄存器TMOD,不可位寻址
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
//配置上述的每隔一段时间进行加1计数操作
TL0 = 0x66; //设置定时初值
TH0 = 0xFC; //设置定时初值
//2.控制寄存器TCON,可位寻址,可以单独赋值
TF0 = 0;//清除TF0.标志,TF0 = 1时溢出,可以不配置,硬件即可自动配置
TR0 = 1; //定时器0开始计时
//3.中断
//3.1中断允许控制寄存器IE
EA = 1;//CPU的总中断允许控制位,EA = 1,CPU开放中断
ET0 = 1;//定时器0中断允许控制寄存器
//3.2中断优先级控制寄存器IP,针对普通的89c52
//stc89c52有四个优先级选择,还需配置寄存器IPH
PT0 = 0;//设置中断优先级
#include
#include "Delay.h"
#incldue "LCD1602.h"
#include "Timer0.h"
//unsigned char Sec = 0;//秒
//unsigned char Min = 0;//分
//unsigned char Hour = 0;//时
//unsigned char Day = 0;//天
//验证代码能不能进位
unsigned char Sec = 50;
unsigned char Min = 59;
unsigned char Hour = 23;
unsigned int Day = 363;
void LCD_Init();
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void main()
{
//初始化
LCD_Init();
Timer0_Init();
//lcd显示
//LCD_ShowString(1,1,"Clock:");
LCD_ShowString(1,1,"Hour:Min:Sec");
LCD_ShowString(1,14,"Day");
while(1)
{
LCD_ShowNum(2,7,Sec,2);
LCD_ShowChar(2,6,':');
LCD_ShowNum(2,4,Min,2);
LCD_ShowChar(2,3,':');
LCD_ShowNum(2,1,Hour,2);
LCD_ShowNum(2,14,Day,3);
}
}
void Timer0_Rountine() interrupt 1
{
static unsigned int T0count;
//局部变量,static子函数结束后依然保留占据空间
//每次运行中断都重新赋初值保证不溢出和计数间隔
//重新赋初值
TL0 = 0x66; //设置定时初值,由stc生成
TH0 = 0xFC; //设置定时初值
T0count++;//计数
if(T0count>=1000)//1000*1ms = 1s
{
T0count = 0;
Sec++;
if(Sec>=60)
{
Sec = 0;
Min++;
if(Min>=60)
{
Min = 0;
Hour++;
if(Hour>=24)
{
Hour = 0;
Day++;
}
}
}
}
}
#include
/**
*@brief 定时器0初始化 [email protected]
*@param 无
*@retval 无
*/
void Timer0_Init()
{
//TMOD不可位寻址,所以其必须八位直接赋值
//如果同时使用定时器0和定时器1的时候,会刷新中断配置
//TMOD = 0x01;
//模式1,就是M1 = 0,M0 = 1,即0000 0001
//0-65535,每隔1us计数+1,所以需要设置初始值
//16位定时器最大时间间隔 = 2^16 = 65.536ms
//TMOD = TMOD&0xF0;//与同1才为1,其余均为0,所以低4位清零,高4位保持不变
//TMOD = TMOD|0x01;
//只要有1就是1,同0才为0.所以除了最后一位均不变,最后一位置1
//这样就是高4位依然不变,改变的只是低4位,即定时器0
//TF0 = 0;//TF是溢出标志,表明没有溢出
//TR0 = 1;//定时器0的运行控制位
//设置每次计数时间
//TH0使用8位,TL0使用8位,
//虽然我们合在一起成了16位定时器,但是我们写的时候得分开写
//TH0 = 64535/256;//(65535-1000)/256,1000us等于1ms,
//TL0 = 64535%256;//为刚好1ms//定时器设置,每隔1ms发起一次中断
//比如64535离计数器溢出差值是1000,所以计时时间是1ms
//比如65535/256 = 255,刚好是1111 1111,高八位
//65535%256 = 0,刚好是0000 0000,低八位
//对于以上的/与%有1us的延迟,为什么
//TL0 = 64535%256,计算出来是0x17,stc配置出来时0x18,相差1us
//因为65535并没有溢出,离计数器溢出差值应该是1001us
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x66; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
//中断
EA = 1;//CPU的总中断允许控制位,EA = 1,CPU开放中断
ET0 = 1;//定时器0中断允许控制寄存器
PT0 = 0;//设置中断优先级
}
89c51单片机内部有两个16位的定时/计数器,即定时器T0和定时器T1,单片机的定时功能其实就是通过计数来实现的,当单片机每一个机器周期产生一个脉冲时,计数器就加一。
一个16位的定时器,它所能计数的范围是0~65535,如果单片机采用的是12M的晶振,那么定时器单次最长的时间为65535*((1/12)*12),因为一个一个机器周期等于12个振荡周期,那么定时器加一所用的时间是1/12M*12是1us,也就是一个12MHz晶振的51单片机单次最长时间约为65ms.
即普通的51单片机所能配置中断的最长时间是65ms,正常情况下,0-65535,每隔1us计数+1,所以需要配置定时初值。
定时器模式可见下图:
具体代码由stc-isp生成:
//首先定时器根据时钟的输出信号每隔一段时间对计数单元进行加1
//当计数单元加1到设定提醒时间就进行中断申请,使程序跳转到中断函数中执行
//1.工作模式寄存器TMOD
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x66; //设置定时初值
TH0 = 0xFC; //设置定时初值
//2.控制寄存器TCON
TF0 = 0;//清除TF0.标志,TF0 = 1时溢出,可以不配置,硬件即可自动配置
TR0 = 1; //定时器0开始计时
//3.中断
//3.1中断允许控制寄存器IE
EA = 1;//CPU的总中断允许控制位,EA = 1,CPU开放中断
ET0 = 1;//定时器0中断允许控制寄存器
//3.2中断优先级控制寄存器IP,针对普通的89c52
//stc89c52有四个优先级选择,还需配置寄存器IPH
PT0 = 0;//设置中断优先级
89c51单片机内部有两个16位的定时/计数器,即定时器T0和定时器T1,单片机的定时功能其实就是通过计数来实现的,当单片机每一个机器周期产生一个脉冲时,计数器就加一。
如,一个16位的定时器,它所能计数的范围是0~65535,如果单片机采用的是12M的晶振,那么定时器单次最长的时间为65535*((1/12)*12),因为一个一个机器周期等于12个振荡周期,那么定时器加一所用的时间是1/12M*12是1us,也就是一个12MHz晶振的51单片机单次最长时间约为65ms.
当GATE = 1开门,定时器开启与关闭由外部与内部一起控制,对于定时器1来说,GATE = 1,当INT1引脚为高且TR1 = 1时才开启定时器。
当C/T位为1时工作在定时器模式,当M1与M0取值不同代表不同的计数模式,当M1 = 0,M0=1是16位定时器,最多可以存放2^16=65536个计数值,51单片机每计数一个值的时间是一个机器周期,也就是12个时钟周期,T = 12t = 12*(1/12000000)= 1us,所以可以知道最大的计数时间为65.536ms.
M1=1,M0=0时,是一个8位具有重载初值功能的定时器,自动重载初值就是在计数器里面的值计满后,单片机会产生一个溢出中断,自动将计数值清0,因此每次在中断服务程中都需要进行重新赋计数值,而这种模式就省去了重新幅值这一步,由单片机自动进行赋值。