一、定时器的初始化
(来源于STC89CXX中文参考手册)
1.代码详解
#include <REGX52.H>
/**
* @brief 定时器0初始化,1毫秒@11.0592MHz
* @param 无
* @param 无
* @retval 无
*/
//由软件生成的定时器计算,注意每次要重新配置参数
void Timer0_Init(void)
{
//AUXR &= 0x7F; //(89C52因为版本老没有这个寄存器)定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x66; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
//(下面的代码需要手动补上,参考中断系统的说明书,软件无法自动生成)
ET0=1;//允许中断
EA=1;//允许总中断
PT0=0;//中断优先级为0
}
/*
void Timer0_Init()//定时器+中断系统的初始化函数
{
//原理图在开发手册P190
//TMOD=0x01;
//0000 0001 from 开发手册P189-定时器工作模式
//TMOD是不可位寻址只能整体赋值
TMOD=TMOD&0xF0;//把TMOD的低四位清零,高四位保持不变
/*
假设TMOD为
1010 0011
1010 0011 & 1111 0000 = 1010 0000
TMOD=TMOD&0xF
低四位清零,高四位保持不变
TMOD=TMOD|0x01;//把TMOD的最低位改为1,高四位保持不变
1010 0000 | 0000 0001 =1010 0001
最低位改为1,高四位保持不变
TF0=0; //from 开发手册P188-定时器控制-中断
//TCOM是可位寻址可以对其中的每一位单独赋值,TF0就是其中一位
TR0=1; //from 开发手册P188-定时器控制-开始计数
0~65535
每隔一微秒计数加一
总共定时时间位65535微秒
如果赋初始值为64535,距离计数器计数器溢出差值1000
所以计时时间为1毫秒
P190原理图
TH0=64535/256;
TL0=64535%256;
16进制存储在两个寄存器,分高低位
如果以10进制为例子
123存储在两个寄存器内
123/100=1(高位)
123%100=23(低位)
//下面是中断系统的初始化,是老一代51单片机,现在单片机可以向下兼容的。
ET0=1;
EA=1;
PT0=0;
}
*/
2.TCON控制寄存器
3.TMOD工作模式寄存器
4.定时器流程
5.中断系统
二、独立按键的初始化
#include <REGX52.H>
#include "Delay.h"
/**
* @brief 获取独立按键的键码
* @param 无
* @param 无
* @retval 按下按键的键码,范围:1~4;无按键按下时为0
*/
unsigned char Key()
{
unsigned char Keynumber=0;
if(P3_1==0)//K1
{
Delay(20);
while(P3_1==0)
{
Delay(20);
}
Keynumber=1;
}
if(P3_0==0)//K2
{
Delay(20);
while(P3_0==0)
{
Delay(20);
}
Keynumber=2;
}
if(P3_2==0)//K3
{
Delay(20);
while(P3_2==0)
{
Delay(20);
}
Keynumber=3;
}
if(P3_3==0)//K4
{
Delay(20);
while(P3_3==0)
{
Delay(20);
}
Keynumber=4;
}
return Keynumber;
}
三、调用库函数<INTRINS.H>中的_cror_();循环右移函数;_crol_();循环左移函数
/*--------------------------------------------------------------------------
INTRINS.H
Intrinsic functions for C51.
Copyright (c) 1988-2010 Keil Elektronik GmbH and ARM Germany GmbH
All rights reserved.
--------------------------------------------------------------------------*/
#ifndef __INTRINS_H__
#define __INTRINS_H__
#pragma SAVE
#if defined (__CX2__)
#pragma FUNCTIONS(STATIC)
/* intrinsic functions are reentrant, but need static attribute */
#endif
extern void _nop_ (void);
extern bit _testbit_ (bit);
extern unsigned char _cror_ /*循环右移*/ (unsigned char, unsigned char);
extern unsigned int _iror_ (unsigned int, unsigned char);
extern unsigned long _lror_ (unsigned long, unsigned char);
extern unsigned char _crol_ /*循环左移动*/ (unsigned char, unsigned char);
extern unsigned int _irol_ (unsigned int, unsigned char);
extern unsigned long _lrol_ (unsigned long, unsigned char);
extern unsigned char _chkfloat_(float);
#if defined (__CX2__)
extern int abs /*取绝对值*/ (int);
extern void _illop_ (void);
#endif
#if !defined (__CX2__)
extern void _push_ (unsigned char _sfr);
extern void _pop_ (unsigned char _sfr);
#endif
#pragma RESTORE
#endif
四、延时函数
void Delay(unsigned int xms)
{
unsigned char data i, j;
while(xms--)
{
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
五、主函数
#include <REGX52.H>
#include "TIMER0.h"//定时器初始化,函数为Timer0_Init();
#include "Key.h"
#include <INTRINS.H>
/*
这个库中
_cror_();循环右移函数
_crol_();循环左移函数
例子:
unsigned char a=0x01;
a=_crol_(a,1);//0x02
unsigned char a=0x80;
a=_crol_(a,1);//0x01
*/
unsigned char KeyNum,LEDMode;
void main()
{
P2=0xFE;
Timer0_Init();
while(1)
{
KeyNum=Key();
if(KeyNum==1)
{
LEDMode++;//按下K1,改变LEDMode的状态,状态0/1决定
if(LEDMode>=2)LEDMode=0;
}
}
}
//定时器T0的中断号为1
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;//退出此程序后不刷新数据,保留数据,称为局内的静态数据
TL0 = 0x66;
TH0 = 0xFC;
//计时器溢出默认为0,下一次中断会变成65倍的时间
//将其设定为
T0Count++;
if(T0Count>=500)
{
T0Count=0;
if(LEDMode==0)
P2=_crol_(P2,1);//LED循环左移
if(LEDMode==1)
P2=_cror_(P2,1);//LED循环右移动
}
}