一、定时器以一秒为单位计数
上篇文章写到:12.00MHz的晶振分频之后,就是1MHz振动一百万次,也就是1ms.
如果使用STC-ISP进行操作,可以直接从软件里面获取想要的定时器配置:
那么我们怎么样才能知道单片机定时器是否以1s钟为单位进行计数?我们只需要在中断里面加入一个判断,脉冲信号以1MHz为单位发出,也就是1ms,那么我们只需要接受1000次,就是1s。如何进行检测是不是成功了?
——通过实现定时器控制LED灯1s闪烁一次进行观察
代码如下:
#include <REGX52.H>
void time0_init(void)
{
TMOD|=0X01;//选择为定时器0模式,工作方式1
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
}
void main()
{
Timer0_Init();
while(1)
{
}
}
void Timer0_Routine() interrupt 1
{
static unsigned int T0count = 0;
T0count++; //进入一次中断就+1,意味着过了1ms
TH0=0XFC; //重新开始,就像一个沙漏一样,这个沙漏流完刚好是1ms,我得给它倒过来,重新开始1ms
TL0=0X18;
if(T0count == 1000) //当T0count数量达到1000次,也就是1ms过去了1000次(即1s)
{
P1_0 =~ P1_0; //我就开始闪烁一次
T0count = 0; //然后再把1s归0,重新开始计数,这样子循环,灯就实现了以1s为周期闪烁
}
}
在实现这个功能的时候遇到了以下问题:原先的代码运行后,出现灯常亮的情况
后面经过调试,修改了if语句里面的命令,让一个灯灭和另外一个灯亮,结果发现两个灯都保持常亮,也就是说无论我给高电平还是低电平我的灯都亮,如果把LCD1602拔下才能正常实现功能。
也就是说:我们在运行的时候,要注意其他外设所用到的I/O口和你所设置的I/O口是否冲突,否则就会出现我这样的情况。
二、定时器0控制LED流水灯方向调转
我想要实现:
LED正常流水灯的情况下,按下按键1,调转方向,如果再次按下键1就再次调转方向
代码如下:
1、首先先看流水灯如何实现
#include "TIMER0.H"
#include "Key.h"
#include <INTRINS.H>
unsigned char KeyNumber,LEDMODE; //均默认为0
void main()
{
P3 = 0xFE; //1111 1110 先让第一个小灯点亮
Timer0_Init(); //定时器0初始化
while(1)
{
KeyNumber = Key();
if(KeyNumber != 0) //如果有按键按下(我们先讲不按下按键流水灯怎么实现,忽略不看)
{
if(KeyNumber == 1)
{
LEDMODE++;
if(LEDMODE >= 2)
{
LEDMODE = 0;
}
}
}
}
}
void Timer0_Routine() interrupt 1 //因为没有按键按下,所以我们来到中断系统
{
static unsigned int T0count = 0;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC;
T0count++; //T0count计数
if(T0count >= 1000) // 达到1s后
{
T0count = 0;
if(LEDMODE == 0) //如果LEDMODE等于0
{
P3 =_crol_(P3,1) ; //P3口左移一位,也就是第二个灯点亮,一开始的第一个灯熄灭,就是这样子实现流水灯
}
}
}
2、通过按键控制:(完整代码)
#include "TIMER0.H"
#include "Key.h"
#include <INTRINS.H>
unsigned char KeyNumber,LEDMODE;
void main()
{
P3 = 0xFE;
Timer0_Init();
while(1)
{
KeyNumber = Key();
if(KeyNumber != 0) //如果按键按下
{
if(KeyNumber == 1) //且按下按键1
{
LEDMODE++; //LEDMODE = 1;
if(LEDMODE >= 2) //如大于等于2,就为0,也就是说我确保LEDMODE只能为0或1
{
LEDMODE = 0;
}
}
}
}
}
void Timer0_Routine() interrupt 1
{
static unsigned int T0count = 0;
TL0 = 0x18;
TH0 = 0xFC;
T0count++;
if(T0count >= 1000)
{
T0count = 0;
if(LEDMODE == 0) //LEDMODE是0,就左移
{
P3 =_crol_(P3,1) ;
}
if(LEDMODE == 1) //LEDMODE是1,就右移
{
P3 = _cror_(P3,1);
}
}
}
三、定时器时钟
理解了上面两个程序,这个就更好理解了
想要实现下面这样:
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "Timer0.h"
unsigned char Sec,Min,Hour;
void main()
{
LCD_Init();
Timer0Init();
LCD_ShowString(1,1,"Clock:"); //上电显示静态字符串
LCD_ShowString(2,1," : :");
while(1)
{
LCD_ShowNum(2,1,Hour,2); //显示时分秒
LCD_ShowNum(2,4,Min,2);
LCD_ShowNum(2,7,Sec,2);
}
}
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=1000) //定时器分频,1s
{
T0Count=0;
Sec++; //1秒到,Sec自增
if(Sec>=60)
{
Sec=0; //60秒到,Sec清0,Min自增
Min++;
if(Min>=60)
{
Min=0; //60分钟到,Min清0,Hour自增
Hour++;
if(Hour>=24)
{
Hour=0; //24小时到,Hour清0
}
}
}
}
}