51单片机入门学习小结(流水灯与数码管)

51单片机入门学习小结(流水灯与数码管)

对原理图的分析

以下是我所用单片机的原理图
在这里插入图片描述
这块51单片机一共有4个I/O口(意思为input/output),也代表着如果我们后续都要用到这四个的话那么功能会比较单一,所以单片机上会有很多模块,如74HC245可以用来控制数码管,减轻单片机核心上的负担。
在这里插入图片描述
这是LED模块,VCC代表高电位+5V,所以说想让这LED发光,就要在另一端接低电位0V。
在图中我们可以看到可以把LED右端的接口与核心上的P2端相接,一一对应。

LED的点亮与流水灯

1.先来说一下如何点亮LED灯

#include "reg52.h"//调用52单片机的头文件,写51也可以// 
sbit LED=P2^0;//sbit 是用来确定地址,这里是把LED定义为P2的0号接口//
void main()
{
	LED=0;//代表着P2口出低电位使发光二极管前后产生电位差而发光//
}

所以以此类推我们可以使开发板上的多个发光二极管点亮,但是如果一个一个接口定义过去会比较麻烦,所以我们可以对整个P2口进行操作。

#include "reg52.h" 
#define LED P2
void main()
{
	LED=0;
}	

这样就能实现LED灯全部点亮。
那么我们要如何使LED灯实现流水灯的样子呢?

流水灯实现

首先我们要知道8个LED灯每一个灯都代表二进制位上的一位,也就是说8个灯在一开始都为1111 1111(顺序从LED1到8),这样两边高电位所以不会亮,我们把他写为十六进制数为0xff(0x是为了告诉电脑这是16进制)
所以我们想要把灯点亮,就可以把各个位置变为0出低电位,这样就可以实现点亮LED灯。
那么我们要怎么样才能使LED灯逐个点亮呢?
我们可以用到C语言中的"<<“与”>>"来实现位的左移右移。也就是说我们可以这样写

#include "reg52.h" 
#define LED P2
#define ui unsigned int
#define uc unsigned char


void delayms(ui del) //延时语句,延时时长为(del*10)ms	
{
	ui i,j;
	for(i=0; i<del; i++)
	for(j=0; j<1827; j++)  ;
}
	
void main(){
	int i;
	
	while(1){
	for(i=1;i<8;i++){
	LED=(0xff<<i);//把0的那一位不断左移使二极管导通
	delayms(15);//此处延时是为了展现视觉效果,不延时会太快人眼看不出流水效果
		}
	}	
}

但这样的流水灯又有点单调了,我们还可以实现使流水灯从左到右再从右到左,只需要在while里在写一个右移即可,代码如下:

#include "reg52.h" 
#define LED P2
#define ui unsigned int
#define uc unsigned char


void delayms(ui del) 	
{
	ui i,j;
	for(i=0; i<del; i++)
	for(j=0; j<1827; j++)  ;
}
	
void main(){
	int i;
	
	while(1){

	for(i=1;i<8;i++){
	LED=(0xff<<i);
	delayms(15);
	}
	LED=0x00;//让所有灯熄灭准备待会反着来亮
	delayms(10);//这就是待会……
	 for(i=1;i<8;i++){
	LED=(0xff>>i);//右移!
	delayms(15);
	}	
}
}

这样就让流水灯更加好看,还有更多形式的流水灯,如从中间散开的波纹,也有从两侧聚拢等,这里不一一例举,大家可以试着自己打出代码实践一下!

数码管的显示

原理图展示

在这里插入图片描述
这是一个八位数码管原理图,我们可以看到这个动态数码管可以靠74HC245来实现亮灭。
这里先介绍一下什么叫位选和段选:
位选是控制每一位数码管的控制信号线。
段选是控制一位数码管上8个发光管(段)的亮灭控制信号线。
位选决定着一位数码管是否显示内容。
段选决定着每一个段(发光管)的亮灭。一位数码管就相当于8个LED灯,数码管分为共阴极和共阳极型,共阴极型的,段选为1时段点亮;共阳极型的,段选为0时点亮。
下图左为共阴,左(2)图共阳。
在这里插入图片描述
而右图abcdefg对应各个发光管的引脚依次顺序展现为二进制数,a对应20,b对应21 ,以此类推出完整的二进制数再转换为16进制数。另外图中dp为小数点。以下为最简单的让数码管显示一个’0’的代码:

#include<reg52.h>
void main()
{
	P0=0X3F;//显示字符‘0’
}

但我们想要实现让数码管多个显示数字该怎么办?为了方便我先定义一个共阴数码管的数组其中包含了0~9数字的十六位进制码。

uc code gmoon[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uc code gsun[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

这样就方便我们来采集所需要的数字。
让多个数码管显示称为动态显示,其实就是多个数码管,不断交替显示,通过极短的延时利用人的视觉暂停作用,使人看到多个数码管同时显示的效果。在这之中我要先来说一下位选和段选。
首先看到这个74HC245的说明:
在这里插入图片描述
其中L代表LOW低电位,H代表HIGH高电位,D就是输入,而Q则是输出,X代表任意一个电位,Q0表示保持原先状态。从中我们可以看到,保存原先状态就是能把之前输入的保存下来也就是说【锁存】。只要先将段选打开(段选=1)来输入所要数字的十六进制,再关闭段选(段选=0)就能够使其锁存住。
我的这块开发板上使用的是74HC138来控制位选也就是接在P22 P23 P24口上在这里插入图片描述
这里在放一张这个芯片的真值表:
在这里插入图片描述
A0 A1 A2接口分别对应上述P22 P23 P24,在这之中的第四行开始我们就能得出一个规律,L看做0 H看做1的话,那么A0 A1 A2所一一对应的二进制,整合起来的值就是右边Y哪一个口出低电位的位置。
通过以上所述就可以来进行动态显示,代码如下:

#include "reg52.h"
typedef unsigned char u8;
typedef unsigned int u16;
sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;
u8 code smgduan[16]= {0x3f, 0x06, 0x5b, 0x4f,
                    0x66, 0x6d, 0x7d, 0x07,
					0x7f, 0x6f, 0x77, 0x7c,
					0x39, 0x5e, 0x79, 0x71}; //0~F数码
void delay(u16 i) //延时函数
{
    while(i--);
}
	
void DigDisplay() //数码管显示函数
{
	u8 i;
	for(i=0;i<8;i++)
	{ 
	  switch(i)
	  {
		case 0:
	  		LSC = 0;LSB = 0;LSA = 0;break; //显示第1个数码管
		case 1:
	  		LSC = 0;LSB = 0;LSA = 1;break; //显示第2个数码管
		case 2:
	 		LSC = 0;LSB = 1;LSA = 0;break; //显示第3个数码管
		case 3:
			LSC = 0;LSB = 1;LSA = 1;break; //显示第4个数码管
		case 4:
			LSC = 1;LSB = 0;LSA = 0;break; //显示第5个数码管
		case 5:
	  		LSC = 1;LSB = 0;LSA = 1;break; //显示第6个数码管
		case 6:
	  		LSC = 1;LSB = 1;LSA = 0;break; //显示第7个数码管
		case 7:
	 		LSC = 1;LSB = 1;LSA = 1;break; //显示第8个数码管
	  }
	  P0 = smgduan[i+1];//显示1~8的数值
	  delay(100); //延时,造成视觉暂留现象
	  P0 = 0x00; //数码管消隐
	}
}	
 
void main()
{
   while(1)
   {
   DigDisplay();
   }
}

这样就能实现八位数码管显示1~8。
还有更多效果实现,让管子出现各种样式!
这是本人第一次编辑,如果有纰漏欢迎指出与我讨论共同进步!
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值