51单片机:使用定时器与按键控制LED流水灯(附代码详解)

一、定时器的初始化

(来源于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控制寄存器

102019d7a1404754b4a8ba03cd867ad9.png

 

 

3.TMOD工作模式寄存器

fa8e0d998cf6461c94e9b31bdd95ef0d.png

 

 

4.定时器流程

327183fe2e2b46358e2791cbff64268f.png

 

5.中断系统

f3e444bc5d7e435697574d60bff0ede2.png

 

 

 

二、独立按键的初始化

#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循环右移动
	}

	
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值