Autoleaders控制组——51单片机LED与数码管相关内容

一、单片机介绍

 

1、单片机,英文Micro Controller Unit,简称MCU

2、内部集成了CPURAMROM、定时器、中断系统、通讯接口等一系列电脑的常用硬件功能

3、单片机的任务是信息采集(依靠传感器)、处理(依靠CPU)和硬件设备(例如电机,LED等)的控制

4、单片机跟计算机相比,单片机算是一个袖珍版计算机,一个芯片就能构成完整的计算机系统。但在性能上,与计算机相差甚远,但单片机成本低、体积小、结构简单,在生活和工业控制领域大有所用

5、51单片机详细内容介绍:

所属系列:51单片机系列

公司:STC公司

位数:8

RAM:512字节

ROM:8KFlash

工作频率:12MHz(本开发板使用)

 (寄存器中,用十六进制表示各口状态。如P2=0xEF;表示1111 1110)

(电路中排阻的读书:102——10 00;473——47 000即末尾数字表示倍率)

6、编程基本框架:

#include<>

void main()

{}

二、点亮LED 

1、LED闪烁:

(先看代码:LED闪烁)

#include <REGX52.H>
void Delay100ms(unsigned int xms)
{
	unsigned char i, j;
	while(xms--){
		i = 180;
		j = 73;
		do
		{
			while (--j);
		} while (--i);
	}
	
}



void main()
{
	while(1){
		P2=0xFE;
		Delay100ms(10);
		P2=0xFF;
		Delay100ms(10);
	}
}

(1)该段代码有三个部分组成,头文件、Delay100ms函数、main主函数。

(2)头文件:#include <REGX52.H>为单片机的外设定义文件,可以在其中查询外设

(3)Delay100ms函数:(在stc软件界面右上角工具栏中有“软件延时计算器”,选择好延时后,选好指令集——stc-Y1)复制粘贴在void main()前。其起的作用是让单片机执行完任务后停顿xms。注意的是,该函数是修改后的函数,原函数只能停顿固定的时间,而我们为这个函数添加了变量(unsigned int xms),然后再添加一个循环,该循环以xms为条件,非零继续进行,变至零停止(x--),例如主函数中的Delay100ms(10);原本只能停顿100ms,加入变量10后,该函数会进行10次,即为1000ms,也就是1s。

(4)main主函数:while(1){}的括号内为非零数1,表示含义为“真”,因此该循环会一直进行下去不会停止。{}内的P2表示的是八个LED灯,P2有八位数,根据十六进制,P2=0xFE表示1111 1110,我们知道LED在低电频状态下才能工作,也就是L1会工作,其他关闭。后面Delay100ms(10);是引用Delay100ms函数,进行停顿。紧接着P2=0xFF表示1111 1111,即为全部LED关闭。如此循环下去,实现了LED的重复闪烁。

2、独立按键控制LED

(1)轻触按键,相当于电子开关,通过内部金属弹片来实现接触断开

 (注意:RXD为3_1口,TXD为3_0口,下面两个分别为3_2口,3_3口)

(按下按键即为低电频)

(先看代码:独立按键控制LED)

#include <REGX52.H>
void Delay100ms(unsigned int xms)
{
	unsigned char i, j;
	while(xms)
	{
		i = 180;
		j = 73;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}

void main()
{
	while(1)
	{
		if(P3_1==0)
		{
			Delay100ms(2);
			while(P3_1==0);
			Delay100ms(2);
			P2_0=~P2_0;
		}
	}
}

(2)要想通过按键实现控制LED,原理就是编写一个判断语句if语句来以按键为条件,达到条件后执行LED亮起的任务

(3)值得注意的事if和while括号里应该是==,表示两个值是否相等的意思

(4)也许会奇怪为什么要在if里添加Delay100ms(2);这里就要讲到按键抖动

 (为了防止抖动产生的影响,我们会在按下按键,和松开按键后,选择停顿20ms左右)

(5)if函数内还有个while语句,括号内是P3_1==0,表达的意思是K1键一直被按着(其实就是想你一直按着K1不工作,直到你松开)。为什么while没有{}?因为程序只想让其不工作,不需要其他任务,所以括号内为空内容,可不添加{}。

(6)P2_0=~P2_0;其中~为取反符号。如下是数据运算的其他符号

 

 而P2_0一开始为暗——0,而~P2_0变为1——亮,并将该值赋给了P2_0。后面再按,执行程序P2_0——1变为~P2_0——0。(注意的是P2有八位,控制八盏LED。P2_0有一位,只控制一盏)

 3、按键控制LED二进制亮起

(先看代码:按键控制LED二进制亮起)

#include <REGX52.H>
void Delay100ms(unsigned int xms)		//@11.0592MHz
{
	unsigned char i, j;
	while(xms)
	{
		i = 180;
		j = 73;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}

void main()
{
	unsigned char num=0;//¸ÃÀàÐÍΪ°Ëλһ¿ªÊ¼±íʾ0000 0000
	while(1)
	{
		if(P3_1==0)
		{
			Delay100ms(2);
			while(P3_1==0);
			Delay100ms(2);
			num++;//¸ÃÀàÐÍ´Ó0000 0000¿ªÊ¼²»¶Ï½øÐжþ½øÖƵؼÓÒ»
			//±ä³É0000 0001->0000 0010->0000 0011->0000 0100
			P2=~num;//¸ÃÈ¡·´²½ÖèʹÁãÈ«±äΪһ¼
			//¼´Îª1111 1110->1111 1101->1111 1100->1111 1011
		}
	}
}

(1)相对于上一个代码,这里多了unsigned char num=0;num++;从之前C语言学习中我们知道unsigned char是定义字符,其定义的是一位八位字符。且看下面其他的定义以及他们对应的位数

 (2)unsigned char num=0;表示的是num这个字符表示0000 0000

(3)num++;表示的是num=num+1。根据二进制的加减法:

0000 0000->0000 0001->0000 0010->0000 0011->0000 0100.......

(4)最后的P2=~num;一下子把八位数给取反,十分方便,实现了LED二进制式地亮起

4、PLUS:K1和K2按键控制LED左右移动

(先看代码:K1和K2按键控制LED左右移动)

#include <REGX52.H>
void Delay100ms(unsigned int xms)		//@11.0592MHz
{
	unsigned char i, j;
	while(xms)
	{
		i = 180;
		j = 73;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}

void main()
{
	unsigned char num=0;//¶¨Òå±äÁ¿Òª·ÅÔÚ×îÇ°Ãæ
	P2=~0x01;
	while(1)
	{
		if(P3_0==0)
		{
			Delay100ms(2);
			while(P3_0==0);
			Delay100ms(2);
			num++;
			if(num>=8)
			{
				num=0;
			}
			P2=~(0x01<<num);//0000 0001->0000 0010
		}
		if(P3_1==0)
		{
			Delay100ms(2);
			while(P3_1==0);
			Delay100ms(2);
			if(num==0)
			{
				num=7;
			}
			else
			{
				num--;
			}
			P2=~(0x01<<num);
		}
	}
}

(1)首先初始化LED的状态P2=~0x01;
(2)我们设想K1控制LED向左走,K2控制LED向右走。所以需要设立两种条件,两个if来判断按的是那个按键。

(3)先看K2键(P3_0):点击一次K2,进行num++,num从0000 0000二进制式加1,但是我们看最后P2=~(0x01<<num);表达的是0000 0001向左移动num格,因为num在十进制中为1,所以变为0000 0010。如果再点击一次K2,num++,num在十进制中变为了2,P2=~(0x01<<num);表达得是0000 0001向左移动2格0000 0100。(注意1111 1110亮的是第一盏LED,也就是左边第一盏D1)

(4)if语句内还有个if语句,是用来处理满格的情况,也就是当num=8,LED无法进八格,所以就干脆重新开始,num=0,直接P2=~0x01。

(5)再看K1键(P3_1):点击一次K1,这里先是判断了num的数值,若num=0,也就是说LED灯仍处在第一位,那么点击K1,没有位置让LED向左移动,那就让他变为最右边的位置P2=~(0x01<<num);如果num为其他值,那么为了让LED向右移动,就将num减一,让P2=(0x01<<num);退后一格。


三、数码管

1、LED数码管:

(1)显示器,有多个发光二极管组成

(2)数码管引脚定义:

(值得关注的是单个数码管八个LED的字母代号(包括小数点DP) 

再看单个数码管的连接方式,共有十个连接口,其中3,8口已经用来连接阴极,还剩下八个口来连接剩下的LED,都是以就近原则来连接的。 )

(3)单个数码位的连接方式 :

该连接方式为共阴极连接(阴极连到一个口)。该连接方式为共阳极连接(阳极连到一个口)

(很简单的理解:有电流流过,LED才能亮,电流从高电频流向低电频,就拿共阴极连接来举例:对于数码管,我们要点亮A号LED灯,需要在7号位给高电频,才能使电流流过LED灯。注意区分LED与数码管的区别)

(4)四位一体数码管

(为什么四位数码管的口只比一位多了两位?且看他们的连接方式:相同字母序号的LED连接在一条管上,而各位的共阴极分别连在了剩下的四个口 

 (5)了解完数码管的构造和接线原理,还需要了解控制他的其他外设。

译码器

 右上角的ABC,是用来选定LED灯的,C为高位,A为低位,按照CBA的顺序赋给它0、1的值,根据二进制来选择右边Y0~Y7的LED灯。由于我们的LED灯是四位一体的,LED的连接线路有些事重复的,因此我们需要通过译码器来选择需要发光的LED灯(看下图演示)

 

 双向数据缓冲器

 ·在译码器和数码管中间下方的外设为双向数据缓冲器。

·我们通过译码器选择好LED灯后,要通过该外设来控制大LED灯中的八位小LED灯的亮暗(即显示出数字)

·可以看到从数码管下方连接出来的线路abcdefg,刚出来的数字是连接的线路号码,接入双向数据缓冲器后需要注意的是A0-B0,A1-B1.....。再看左边的LE的P0_0,P0_1,P0_2.....。通过双向缓冲器,我们可以控制abcdefg的亮灭(由于是共阴极连接,所以1为亮,0为灭)来展示我们想要的数字。(看下图演示)

 ·由此,我们可以定义一个数组来显示各个数字

int shuzi[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,};

· 0在第一位即shuzi[0],1在第二位即shuzi[1].......

(6)数码管显示数字的过程

·位选-段选  位选-段选  位选-段选  位选-段选......

·但是由于过程很快,所以有时候段选还未结束时,下一段位选已经开始了,这时候就会导致产生重影,LED灯模糊难辨

·因此需要在段选和位选之间加一段延迟——位选-段选 Delay100ms(0.1)  位选-段选,就可以解决这一问题。

(看代码:在四位一体显示数字5201314)

#include <REGX52.H>
void Delay100ms(unsigned int xms)
{
	unsigned char i, j;
	while(xms--){
		i = 180;
	j = 73;
	do
	{
		while (--j);
	} while (--i);
	}
	
}
void num(int location,int number);
int shuzi[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,};


void main()
{
	int i=3;
	while(1)
	{
		while(1)
		{
			num(2,5);
			num(3,2);
			num(4,0);
			num(5,1);
			num(6,3);
			num(7,1);
			num(8,4);

		}
//		break;
	}
}



void num(int location,int number)
{
	switch(location)
	{
		case 1:P2_4=1;P2_3=1;P2_2=1;break;
		case 3:P2_4=1;P2_3=0;P2_2=1;break;
		case 4:P2_4=1;P2_3=0;P2_2=0;break;
		case 5:P2_4=0;P2_3=1;P2_2=1;break;
		case 6:P2_4=0;P2_3=1;P2_2=0;break;
		case 7:P2_4=0;P2_3=0;P2_2=1;break;
		case 8:P2_4=0;P2_3=0;P2_2=0;break;
	}
	P0=shuzi[number];
	Delay100ms(0.1);
	P0=0x00;
}

1、该段代码有三部分组成其一为void Delay100ms(unsigned int xms)函数,其二为void num(int location,int number)函数,其三为void main()主函数。

2、void Delay100ms(unsigned int xms)前面介绍过,在这就不做过多赘述。

3、void num(int location,int number)函数中有两个变量location和number,都是int类型

        (1)location用作Switch case语句变量。输入location的值,与case对应的值进行配对,如果按顺序来如果符合,就进行case里的程序。注意:记得带case最后添加break。否则会导致整排数码管全部显示出数字。举例:当我们给location的值是2,对应着case 2,进行的操作是P2_4=1;P2_3=1;P2_2=0;break;根据二进制110转化为十进制6,数码管从右开始数六位,我们习惯是从左往右看,所以我们的第二位相当于从右往左的第六位

         (2)number用作shuzi[]的变量,即shuzi[number],当我们赋给number的值是0是,数组就位shuzi[0],按照我们前面设立的数组:

int shuzi[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,};可知shuzi[0]就是0x3F,点亮的LED灯就组成0。

        (3)接着是进行Delay100ms(0.1);的操作即停顿10ms

        (4)最后一步将P0=0x00进行全部清零,这一步很关键,否则就会出现重影现象!

        (其实我们LED灯的循环很快,我们眼睛看到LED灯其实是不停以很快的速度闪烁的,由于我们的视觉暂留,所以我们看到的是完整的数字)

4、 void main()主函数,看到while函数内运用了多个num函数,num(2,5)表达的意思就是,从左往右数第2个格的位置显示出数字5,后面以此类推。(由于第二个while已经在第一个while函数内,所以break跳出循环后继续该循环,break加不加无所谓。)

(看最后呈现效果)

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值