基于AT89C52单片机的原理运用

1.1LED的点亮

首先我们通过原理图看到LED1-----LED8 8个LED灯的I/O接口分别连接到了P1总串口端,分别对应P1_0----P1_7

所以我们可以通过分别给总串口赋值和单独串口赋值从而来控制LED灯的点亮,由于vcc接电源正极,所以LED灯赋予低电平共阴极,具体代码如下:

 /*点亮第一个LED灯*/
#include <REGX52.H>  //引入头文件
void main()
{
	while(1)
	{
		P1=0xfe;  //1111 1110 0x为16进制后缀转换成二进制,表示点亮第一个LED
		P1_3=0xf7;  //1111 0111  点亮第4个LED灯
	}
}

 2.2 LED灯的流水

顾名思义就是给LED灯增加延迟函数,从而达到流水灯的作用,
1.通过给整个LED灯赋值实现流水灯 2.通过内置库函数实现LED灯的流水
_crol_ 循环左移 _cror_ 循环右移 所属库 <intrins.h>  ,具体代码如下:

#include <REGX52.H> 
#include<intrins.h>  

/*引入延迟500毫秒函数*/
//函数的调用

void Delay500ms(void)	//@12.000MHz
{
	unsigned char data i, j, k;

	_nop_();  //可有可无,建议去掉,有些编译器可能没有此头文件  <intrins.h>  
	i = 4;
	j = 205;
	k = 187;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void main()
{
	while(1)
	{
		P1=0xfe;   //1111 1110
		Delay500ms();
		P1=0xfD;  //1111 1101
		Delay500ms(); 
		P1=0xfb ; //1111 1011
		Delay500ms(); 
		P1=0xf7;  //1111 0111
		Delay500ms();
		P1=0xef;  //1110 1111
		Delay500ms();
		P1=0xdf;  //1101 1111
	    Delay500ms(); 
		P1=0xbf;  //1011 1111
		Delay500ms();
		P1=0x7f; //0111 1111  
		Delay500ms();
	}
}
#include <REGX52.H> 
#include<intrins.h>  

/*引入延迟500毫秒函数*/
//函数的调用

void Delay500ms(void)	//@12.000MHz
{
	unsigned char data i, j, k;

	_nop_();  //可有可无,建议去掉,有些编译器可能没有此头文件  <intrins.h>  
	i = 4;
	j = 205;
	k = 187;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void main()
{
	unsigned char LED=0xfe; //变量的初始化
	while(1)
	{
		P1=LED;  //点亮第一个LED灯
		Delay500ms();
		LED=_crol_(P1,1);  //每次向左移一个LED灯;
	}
}  

对于函数的调用我们也可以引入自定义参数变量

#include <REGX52.H> 
#include <intrins.h>
//函数的调用也可引用自定义参数
void Delay500ms(unsigned char x)	//@12.000MHz   无符号非负整形
{
	unsigned char data i, j, k;
while(x--)
{
	i = 4;
	j = 205;
	k = 187;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
}
void main()
{
	while(1)
	{
		unsigned char LED=0xfe; //变量的初始化
	    unsigned char time=500;
		P1=LED;  //点亮第一个LED灯
		Delay1ms(500);
		LED=_crol_(P1,1);  //每次向左移一个LED灯;
		time=time-100;  //led流水循环每次时间减少100ms;可以控制流水灯速度
	}
}

3.3 Key按键

首先我们观看S2——S5 四个key按键的原理图,发现其引脚所对应的位置分别为P3_4——P3_7.

 对于独立按键去控制任何一个LED灯,我们首先要用到一个按键读取函数unsigned char Key_Read( )来读取我们的按键值,又自定义一个函数  unsigned char temp=0; 用来返回我们的键码值,具体代码如下所示:

unsigned char Key_Read()  //按键读取函数,接受到返回值Temp;
{
	unsigned char temp=0;  //函数初始化
	if(P3_4==0) temp=1;    //假如P3_0按键按下则为低电平0;
    if(P3_5==0) temp=2;
	if(P3_6==0) temp=3;
	if(P3_7==0) temp=4;
	return temp;  //把得到的Temp值返回到按键读取函数
}

接下来我们编写程序还要运用四行按键变量声明函数如下所示:

  Key_Val=Key_Read();  //读取键码值;
  Key_Val=Key_Val&(Key_Val^Key_Old);  //检测下降沿;
  Key_Up=~Key_Val&(Key_Val^Key_Old);  //检测上升沿;
  Key_Old=Key_Val;  //扫描辅助变量;

我们还需要运用一个Switch循环语句来进行函数的判断从而达到我们的目的代码如下:

#include <REGX52.H> 
//子函数
unsigned char Key_Read()  //按键读取函数,接受到返回值Temp;
{
	unsigned char temp=0;  //函数初始化,必须要赋予初始值
	if(P3_4==0) temp=1;    //假如P3_0按键按下则为低电平0;
    if(P3_5==0) temp=2;
	if(P3_6==0) temp=3;
	if(P3_7==0) temp=4;
	return temp;  //把得到的Temp值返回到按键读取函数
}

// 按下按键然后执行相应的程序 开/关;
 void main()
 {		
	 //变量声明区域;
	 unsigned char Key_Val,Key_DOwn,Key_Up,Key_Old;
	 
	 while (1)
	 {    
  Key_Val=Key_Read();  //读取键码值;
  Key_Val=Key_Val&(Key_Val^Key_Old);  //检测下降沿;
  Key_Up=~Key_Val&(Key_Val^Key_Old);  //检测上升沿;
  Key_Old=Key_Val;  //扫描辅助变量;
    switch(Key_DOwn)   //类似于if语句  读取Temp值
	{
		case 1:
	  P1_4=0;
	 break;    //结果为真,结束整个后面的程序;
		case 2:
	  P1_5=0;
	break;           
		case 3:
	  P1_6=0;
	break;
		case 4:
	  P1_7=0;
	break;
}
	 }
 }   

除了Delay延迟函数外,我们也可以引入一个bit flang 开始暂停标志位函数通过任意一个独立按键来控制流水灯作业:

#include <REGX52.H> 
#include<intrins.h>  
void Delay1ms(unsigned char x)	//@12.000MHz   无符号非负整形
{
	unsigned char data i, j;
while(x--)
{
	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
}
}
unsigned char Key_Read()  //按键读取函数,接受到返回值Temp;  子函数
{
	unsigned char temp=0;  //函数初始化,必须要赋予初始值
	if(P3_4==0) temp=1;    //假如P3_0按键按下则为低电平0;
    if(P3_5==0) temp=2;
	if(P3_6==0) temp=3;
	if(P3_7==0) temp=4;
	return temp;  //把得到的Temp值返回到按键读取函数
}

// 按下按键然后执行相应的程序 开/关;
 void main()
 {		
	 //变量声明区域;
	 unsigned char Key_Val,Key_DOwn,Key_Up,Key_Old;
	 unsigned char Led=0xfe;  //1111 1110
	 unsigned int time =500;
	 bit Flag; //开始暂停标志位;
	 while (1)
	 {    
  Key_Val=Key_Read();  //读取键码值;
  Key_Val=Key_Val&(Key_Val^Key_Old);  //检测下降沿;
  Key_Up=~Key_Val&(Key_Val^Key_Old);  //检测上升沿;
  Key_Old=Key_Val;  //扫描辅助变量;
    switch(Key_DOwn)   //类似于if语句  读取Temp值
	{
 
	 P1=Led;      //按下独立按键第一个灯点亮
	 if(Flag==1)   //共阳极   
	 {	
         Delay1ms(time);	  //延迟函数
		 Led=_crol_(P1,1);    //按下第一个独立按键开始每次向左移
        
	 }

	 switch(Key_DOwn)
	 {
		 case 1:
         Flag=1;   //按下第一个独立按键开始流水灯作业
		 break;
		 case 2:    
		 Flag=0;       //按下第二个独立按键则Flag=0,不执行流水灯作用;
		 break;  
		 case 3:
			 time=time-100;  
		 break;
		 case 4:
			 time=time-300;  //控制流水的速度
		 break;
	 }
 }
}

4.4矩阵按键

矩阵按键和独立按键有相同的原理,此单片机介于4x4的矩阵按键,P3_4--P3_7每一个独立按键对应每4个矩阵按键的行,因此我们可以通过独立按键来控制矩阵按键,与独立按键原理类似

 //矩阵按键
  //子函数
unsigned char Key_Read_Pro()  //按键读取函数,接受到返回值Temp;
{
	unsigned char temp=0;  //函数初始化,必须要赋予初始值
	//通过观察原理图,一排矩阵按键有四个按键,四排统称为P3_0,P3_1,P3_2,P3_3,
	P3_0=0; P3_1=1;P3_2=1;P3_3=1;  //打开第一排矩阵按键
	if(P3_4==0) temp=1;    //if相当于独立按键判断,1-4则为第一排的1-4
    if(P3_5==0) temp=2;
	if(P3_6==0) temp=3;
	if(P3_7==0) temp=4;
	
	P3_0=1; P3_1=0;P3_2=1;P3_3=1;  //打开第二排矩阵按键
	if(P3_4==0) temp=5;    //if相当于独立按键判断,5-8则为第二排的5-8
    if(P3_5==0) temp=6;
	if(P3_6==0) temp=7;
	if(P3_7==0) temp=8;
	
	P3_0=1; P3_1=1;P3_2=0;P3_3=1;  
	if(P3_4==0) temp=9;    
    if(P3_5==0) temp=10;
	if(P3_6==0) temp=11;
	if(P3_7==0) temp=12;
	
	P3_0=1; P3_1=1;P3_2=1;P3_3=0;  
	if(P3_4==0) temp=13;    
    if(P3_5==0) temp=14;
	if(P3_6==0) temp=15;
	if(P3_7==0) temp=16;
	
	return temp;  //把得到的Temp值返回到按键读取函数
}
//后面的变量声明区域和变量读取区域类似于独立按键
5.5 SEG(数码管)

首先我们来认识seg的原理图:

位码:{0xfe,0xfd,0xfb,0xf7,0xef,0xdf};

段码:{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};

数码管显示函数(Seg_Disp):

入口参数:数码管位选(哪个数码管亮)+ 数码管段选(亮什么数字)

程序逻辑:

1、消影

2、位选赋值

3、段选赋值

动态数码管:

每位数码管显示不同的数字,若直接重复调用一个数码管显示的函数,会因为程序执行逻辑是由上至下依次执行,会造成后面的数据影响前面的显示效果

定时器生成步骤:

1、打开STC-ISP烧录软件,找到定时器计算器

2、系统频率 12MHz  定时长度 1毫秒  定时器模式 十六位  定时器时钟 12T

3、复制C代码到工程中

4、删除AUXR &= 0x7F;

中断配置方法:

1、在生成的定时器初始化函数内增加中断打开命令   ET0=1EA=1

2、书写中断服务函数(Timer0Server

3、在服务函数内初始化计数值

4、在主程序内添加定时器0初始化函数

动态数码管显示逻辑:

1、定义一个数组,将每一个数码管要显示的数据放到数组对应的位置

2、将每一个数码管显示的函数放入中断内

//数码管的显示
#include <REGX52.H> 
//显示单独的数码管:1.首先选择哪个数码管(位选Wele)2.进行数字执行程序(段选 Dele)
 /*void main()
{
while(1)
{
	//位选;
    P0=0xfe;  //数据从数码管寄存器进入,准备数据  点亮第一个数码管,和LED同理
	P2_7=1; //打开寄存器
	P2_7=0; //锁上寄存器;
	
	//段选
	P0=0xa4;
	P2_6=1;
	P2_6=0;
	
}
  }
*/

/*变量声明区域*/
unsigned char Seg_Wela[6]={0xfe, 0xfd, 0xfb, 0xf7,0xef, 0xdf} ;
unsigned char Seg_Dula[11]={0x3f,0x06,0x5b,0x66,0x6d,0x7d,0x7f,0x6f,0x00};
unsigned char Seg_Pos; //Wela(位选)服务扫描函数
unsigned char Seg_Buf[6] = {1,2, 3, 4, 5, 6} ;    //若使最后几位熄灭则为 unsigned char Seg_Buf[6] = {1,2, 10, 10, 10, 10} ;  

/*程序逻辑:
1、消影
2、位选赋值
3、段选赋值
*/
/* void Seg_Disp(unsigned char wela, dula)  //函数的声明;
{
   P0=0x00;    //消影,段选每个数码管数字显示为零
   P2_6 = 1;
   P2_6 =0;
	
   P0=Seg_Wela[wela];   //位选赋值
	 P2_7=1;
	 P2_7=0;
	
	 P0=Seg_Dula[dula];    //段选赋值;
	 P2_6=1;
	 P2_6=0;
	
}
*/  
/* 1、在生成的定时器初始化函数内增加中断打开命令ETO=1、EA=1
2、书写中断服务函数(TimerOServer)
3、在服务函数内初始化计数值
4、在主程序内添加定时器0初始化函数

动态数码管显示逻辑:
1、定义一个数组,将每一个数码管要显示的数据放到数组对应的位置
2、将每一个数码管显示的函数放入中断内程序例程:
简易it时在重在服务函数内重新初始化数值  */


//定时器初始化函数
void Timer0_Init(void)		//1毫秒@12.000MHz
{
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0x18;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	ET0=1;       //中断打开命令
	EA=1;       //中断打开命令
}

//中段服务函数
void Timer0Server() interrupt 1  //打断函数
{
  TL0 = 0x18;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
  Seg_Pos++;      //初始化计数值
	if(Seg_Pos==6)  Seg_Pos=0;
	Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos]);    //函数的嵌套,在0-5之间循环; 数码管显示的数字为1-6;每一位数码管显示一毫秒
}                 //若需要亮不同的数字,则改变Seg_Buf数组值





 void main()
{
	Timer0_Init(); 函数的调用
	while(1)
	{
		Seg_Disp(3,6);  //数码管显示第4个数码管显示数字7;  函数的调用
		Seg_Disp(4,5);  //可以显示多个数码管
	}
}

  • 27
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值