电子说
2.3 LED小灯
LED(light-emitting diode),即发光二极管,俗称LED小灯,它的种类很多,参数也不尽相同,Kingst51开发板上用的是普通的贴片发光二极管。这种二极管通常的正向导通电压是1.8V到2.2V之间,工作电流一般在1mA~20mA之间。其中,当电流在1mA~5mA之间变化时,随着通过LED的电流越来越大,肉眼会明显感觉到这个小灯越来越亮,而当电流从5mA~20mA之间变化时,看到的发光二极管的亮度变化就不太明显了。当电流超过20mA时,LED就会有烧坏的危险了,电流越大,烧坏的速度也就越快。所以在使用过程中应该特别注意它在电流参数上的设计要求。
下面来看一下发光二极管在Kingst51开发板上的设计应用。USB供电接口图以及电源开关图如图2-3所示。

图2-3 USB接口电路和电源开关电路
图2-3是Kingst51开发板上的USB接口电路。通过USB线,电脑给开发板供电和下载程序以及实现电脑和开发板之间的通信。这是一个标准16引脚的type-C的USB接口,从图上可以看出,其中A6脚和A7脚是数据通信引脚,+5IN为USB电源正极,GND为电源负极。
将电源开关左边的LED部分的电路单独摘出来分析,如图2-4所示。

图2-4 LED小灯电路(一)
发光二极管是二极管中的一种,因此和普通二极管一样,这个二极管也有阴极和阳极,习惯上也称之为负极和正极,方向必须接对了才会有电流通过让LED小灯发光。刚才提到接入的VCC电压是5V,发光二极管自身压降大概是2V,那么在右边R34这个电阻上承受的电压就是3V。现在要求电流范围是1~20mA的话,就可以根据欧姆定律R=U/I,把这个电阻的上限和下限值求出来。
U=3V,当电流是1mA的时候,电阻值是3K;当电流是20mA的时候,电阻值是150欧,也就是R34的取值范围是150~3K欧姆。这个电阻值大小的变化,直接可以限制整条通路的电流的大小,因此这个电阻通常称之为“限流电阻”。在图2-3中用的电阻是1K,这条支路电流的大小可以计算出来了,而这个发光二极管在这里的作用,是作为电源指示灯的,使用USB线将开发板和电脑连起来,这个灯就会亮了。
同理,在电源开关后级控制的位置,又添加了一个LED10发光二极管,当打开开关时,这个二极管才会亮起,如图2-5所示。

图2-5 电源开关电路
把图2-4进行一下变化,把右侧的GND去掉,改成一个单片机的I/O口,如图2-6所示。

图2-6 LED小灯电路(二)
图2-4由于电源从正极到负极有电压差,并且电路是导通的,所以就会有电流通过,LED小灯因为有了电流通过,就会发光。把右侧的原GND处接到单片机P0.0引脚上,那么如果单片机输出一个低电平,也就是跟GND一样的0V电压,就可以让LED小灯和图2-4一样发光了。
因为单片机是可以编程控制的,可以让P0.0这个引脚输出一个高电平,就是跟VCC一样的5V电压,那么这个时候,左侧VCC电压和右侧的P0.0的电压是一致的,那就没有电压差,没有电压差就不会产生电流,没有电流LED小灯就不会亮,也就是会处于熄灭状态。下面,就用编程软件来实现控制小灯的亮和灭。
2.4程序代码编写
这是第一个实验程序,编程之前,需要先来了解一些51单片机特有的程序语法以及Keil软件的基本操作步骤。
1.2.1 特殊功能寄存器和位定义
不同厂家的单片机除了采用通用的C语言编程外,有的厂家的单片机会有那么几条很特殊的独有的编程语句,51单片机就有,先介绍2条。
第一条语句是:sfr P0 = 0x80;
sfr这个关键字,是51单片机特有的,它的作用是定义一个单片机特殊功能寄存器(special function register)。51单片机内部有很多个小模块,每个模块居住在拥有唯一房间号的房间内,同时每个模块都有8个控制开关。P0就是一个功能模块,就住在了0x80这个房间里,用户就是通过设置P0内部这个模块的8个开关,来让单片机的P0这8个I/O口输出高电平或者低电平的。而51单片机内部有很多寄存器,如果想使用必须提前进行sfr声明。不过Keil软件已经把所有这些声明都预先写好并保存到一个专门的文件中去了,用户只需要文件开头添加一行#include即可,这个在后边有用法详解。
第二条语句是:sbit LED = P0^0;
这个sbit,就是对刚才的SFR里边的8个开关其中的一个进行定义。经过上边第二条语句后,以后只要在程序里写LED,就代表了P0.0口(“^”这个符号在数字键6上边),注意这个P必须大写,也就是说给P0.0又取了一个更形象的名字叫做LED。
了解了这两个语句后,再来看一下单片机的特殊功能寄存器。请注意,每个型号的单片机都会配有生产厂商所编写的数据手册(Datasheet),STC89C52的数据手册从21页到24页,全部是对特殊功能寄存器的介绍以及地址映射列表。用户在使用这个寄存器之前,必须对这个寄存器的地址进行说明。是不是花花绿绿的太多了记不住,这个没关系的,不需要记住,后边大部分都会解释,少部分需要用到的时候过来查手册就可以,再次强调做技术不是为了应付考试,可以随时翻阅手册查找需要的资料。
如图2-7,是截取的手册中第22页最下边的一个表格。

图2-7 I/O口特殊功能寄存器
来看一下这个表,其中STC89C52RC的P4口对标准51的扩展,先忽略它,只看前边的P0、P1、P2、P3这4个,每个P口本身又有8个控制端口。可以结合Kingst51开发板原理图或者图2-1来看,那么这样就确定了单片机一共有32个I/O口(I/O,Input和Output,分别是输入和输出)。
其中P0口所在的地址是0x80,一共有从7到0这8个I/O口控制位,后边有个Reset Value(复位值),这个很重要,是看寄存器必看的一个参数,8个控制位复位值全部都是1。这就是告诉用户,每当单片机上电复位的时候,所有的引脚的值默认是都是1,即高电平,在设计电路的时候也要充分的考虑这个问题。
前边那2条语句写sfr的时候,必须根据手册里的这个地址(Add)去写,写sbit的时候,就可以直接将一个字节其中某一位取出来。编程的时候,也有现成的写好寄存器地址的头文件,直接包含该头文件就可以了,不需要逐一去写了。
2.4.2 新建一个工程
对于单片机程序来说,每个功能程序都必须要有一个配套的工程(Project),即使是点亮LED这样简单的功能程序也不例外。因此首先要新建一个工程,打开Keil软件后,点击:Project-->New uVision Project...然后会出现一个新建工程的界面,如图2-8所示。

图2-8 新建一个工程
在计算机硬盘上建立一个lesson2的目录,然后把LED这个工程的路径指定到这里,这样方便今后管理程序,不同的功能程序放到不同的文件夹下,并且给这个工程起一个名字叫做LED,软件会自动添加扩展名.uvproj,如图2-9所示。

图2-9 保存工程
点击“保存”按钮,工程会自动保存成LED.uvproj文件,下次要打开LED这个工程时,可以直接找到文件夹,双击这个.uvproj文件就可以直接打开。
保存之后会弹出一个对话框,这个对话框让用户选择单片机型号。因为Keil软件是外国人开发的,所以国内的STC89C52并没有上榜,但是只要选择同类型号就可以了。因为51内核是由Intel公司创造的,所以这里直接选择Intel公司名下的80/87C52来代替,这个选项的选择对于后边的编程没有任何的不良影响。如图2-10所示

图2-10 单片机型号选择
点击OK之后,会弹出一个对话框,如图2-11所示,每个工程都需要一段启动代码,如果点“否”按钮,编译器会自动处理这个问题,如果点“是”按钮,这部分代码会提供给用户,用户就可以按需要自己去处理这部分代码,那这部分代码在初学51的这段时间内,一般是不需要去修改的,但是随着技术的提高和知识的扩展,就有可能会需要了解这块内容,因此这个地方单击“是”按钮,让这段代码出现,但是暂时不需要修改它,大家知道这么回事就可以了。

图2-11 启动代码选择
这样工程就建立好了,如图2-12所示,如果点击Target 1左边的加号,会出现刚才加入的初始化文件STARTUP.A51,这个先不管。

图2-12 工程文件
工程有了之后,要建立编写代码的文件,点击File-->New,如图2-13所示,新建一个文件,也就是编写程序的平台。然后点File-->Save或者直接点击Save的快捷键,可以保存文件,保存时把它命名为LED.c,这个地方必须加上.c,如果写汇编语言,这个地方的扩展名是.asm,头文件就是.h等等,这里编写的是C语言程序,这个地方必须自己添加文件的扩展名.c,如图2-14所示。

图2-13 新建文件

图2-14 保存文件
现在就可以在已经建立好的文件中输入程序代码了,在编写之前还有个工作要做,每做一个功能程序,必须要新建一个工程,一个工程代表了单片机要实现的一个功能。但是一个工程有时可以把程序分多个文件写,所以每写一个文件,都要添加到所建立的工程中去,右键点Source Group 1,点Add Files to Group ‘Source Group 1’...,如图2-15所示。

图2-15 添加文件(一)
在弹出的对话框中,单击LED.c选中它,然后点Add,或者直接双击LED.c都可以将文件加入到这个工程下,然后单击Close,关闭添加。这个时候会看到在Source Group 1下边又多了一个LED.c文件。

图2-16 添加文件(二)
2.4.3 编写点亮小灯的程序
准备工作做了那么多,终于要编写程序代码了。如果学过C语言,应该很轻松的编程,如果没学过C语言也没关系,先照着抄,后边有针对一些C语言语法的讲解,多看几遍就懂了。
#include //包含特殊功能寄存器定义的头文件
sbit LED = P0^0; //位地址声明,注意:sbit必须小写、P大写!
void main() //任何一个C程序都必须有且仅有一个main函数
{ //{}是成对存在的,在这里表示函数的起始和结束
LED = 0; //分号表示一条语句结束
}
先从程序语法上来分析一下。
1、main是主函数的函数名字,每一个C程序都必须有且仅有一个main函数。
2、void是函数的返回值类型,本程序没有返回值,用void表示。
3、{}在这里是函数开始和结束的标志,不可省略。
4、每条C语言语句以;结束的。
逻辑上来看,程序这样写就可以了,但是在单片机实际应用中存在一个问题。比如程序空间可以容纳100行代码,但是实际的程序只用了50行代码,当运行完了50行,再继续运行时,第51行的程序不是用户的程序,而是不确定的未知内容,一旦执行下去程序就会出错从而可能导致单片机自动复位,所以通常在程序中加入一个死循环,让程序停留在所希望的这个状态下,不要乱运行,有以下两种写法可以参考:
参考程序一: 参考程序二:
#include #include
sbit LED = P0^0; sbit LED = P0^0;
void main() void main()
{ {
while(1) LED = 0;
{ while(1);
LED = 0; }
}
}
程序一的功能是程序在反复不断的无限次执行LED = 0;这条语句,而程序二的功能是执行一次,然后程序直接停留下来等待,相对程序一来说程序二更加简洁一些。针对于图2-6,这个程序能够把小灯点亮,但是这个程序却点不亮Kingst51开发板上的小灯,这是为什么呢?
这里就要培养一个意识,单片机编程实际上算是硬件底层驱动程序开发,这种程序的开发是离不开电路图的,必须根据电路图来进行程序的编写。如果电路板的电路图和图2-6一样的话,程序可以成功点亮小灯,但是如果不一样,就可能点不亮。
开发板上还有一个74HC138作为8个LED小灯的总开关,而P0.0仅仅是个分开关。如同家里有一个供电总闸,然后每个电灯又有一个专门的分支开关。刚才的程序仅仅打开了那个电灯的分支开关,但是没有打开那个总电闸。所以程序需要加上这部分代码。因为这节课要介绍的内容比较多,所以74HC138的原理以及为什么要加额外的代码在下节课统一介绍,这节课直接加上这部分代码做一下功能演示。
#include //包含特殊功能寄存器定义的头文件
sbit LED = P0^0; //位地址声明,注意:sbit必须小写、P大写!
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
void main()
{
ENLED = 0;
ADDR3 = 1;
ADDR2 = 1;
ADDR1 = 1;
ADDR0 = 0;
LED = 0; //点亮小灯
while (1); //程序停止在这里
}
为什么有的书上程序很简单就可以点亮小灯,这里却要麻烦一些呢?Kingst51开发板虽然仅仅提供给大家简单学习使用,但是也是按照实际产品的开发模式去设计,所以综合考虑因素很多,学到后边就会明白它的设计价值了,这里只要跟着去做就可以,后续章节会慢慢理解其中的价值。
程序编好了,要对程序进行编译,生成可以下载到单片机里的文件,在编译之前要勾选一个选项,Project-->Options for Target ‘Target1’...,或者直接点图2-17中红框内的快捷图标。

图2-17 工程选项图标
在弹出的对话框中,点击Output选项页,勾选其中的“Create HEX File”复选框,然后点OK,如图2-18所示。

图2-18 创建HEX文件
设置好以后,点击“Project-->rebuild all target files”,或者点击图2-19中红框内的快捷图标,就可以对程序进行编译了。

图2-19 编译程序
编译完成后,在Keil下方的Output窗口会出现相应的提示,如图2-20,这个窗口提供了编译完成后的信息,data=9.0,xdata=0指的是本程序使用了单片机内部的data区域RAM资源中的9个字节,xdata区域的RAM使用为0,data和xdata是51单片机特定的内存区域划分,这两部分都属于51单片机的内存;code=29的意思是使用了8K代码Flash资源中的29个字节。当提示“0 Error(s), 0 warning(s)”表示程序没有错误和警告,就会出现“creating hex file from “LED”...,意思是从当前工程生成了一个HEX文件,要下载到单片机的就是这个HEX文件。如果出现有错误和警告提示的话,Error和warning不是0,那么就要对程序进行检查,找出问题,解决好了再重新编译产生HEX才可以。

图2-20 编译输出信息
到此为止,程序就编译好了,下边就要把编译好的程序文件下载到单片机里了。
审核编辑 黄宇
全部0条评论
快来发表一下你的评论吧 !