打印

猴子教你学单片机 点亮一盏LED灯 while(1)为什么放末尾

[复制链接]
4305|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
symmetry|  楼主 | 2012-7-24 21:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 symmetry 于 2012-8-1 23:23 编辑

配套教学视频http://v.youku.com/v_show/id_XNDE3ODcwMzIw.html
项目需求(点亮一盏LED)项目需求(对应学校课程实验中的实验目的,描述项目所需要完成的功能,这些功能所需要达到的指标):点亮一盏LED灯,LED灯的亮度适中。
这里点亮LED灯是所需要完成的功能,LED灯亮度适中是这一功能所需要达到的具体指标。www.027mcu.cn
1.1.2 背景知识(LED)
发光二极管(LED,Light Emitting Diode), 是一种能够将电能转化为可见光的固态的半导体器件,它可以直接把电转化为光。在日常生活中应用广泛,如LED照明、数码显示管、建筑景观、广告灯、大型显示屏等。
下图为常见的发光二极管实物图。左图为直插形式封装,右图为贴片形式。


图1-1:发光二极管实物图

如何点亮发光二极管呢?很简单!我们知道,二极管是单向导通的,即在发光二极管的两端加上正向电压,就会亮起来。
常用的普通发光二极管通过0~20mA的电流即可正常工作,一般取10mA。在单片机系统中,一般应该串接限流电阻。对于初学者来讲,对于元件参数的选择可能比较头疼。电阻的阻值可按下式估算:R=(VCC-VLED)/ILED, 51系列单片机一般用+5V电源供电,LED压降取0.7V,电流可取10mA,电阻就应该选择430Ω左右。当然,电子市场上不一定能买到这么准确的阻值,可以参考电阻的标称值来近似选择,一般可取470Ω。当然,阻值选大一点或小点也可,不过是发光二极管亮一点或暗一点罢了。
1.1.1 方案设计
有了客户需求之后,我们开始方案设计给出两个方案 :方案一是拨码开关控制,然后接LED 。
方案二利用单片机IO口控制LED。
这时候要选择一个适合项目的方案。首先,方案必须满足客户的需求,考虑成本,采购 ,器件的供货周期,是否适合目前的焊接工艺(直插或表贴封装的选取)。
如选方案一,如果客户需求更改,要求LED会自动闪烁,需要重新选择分立器件(电阻电容)即硬件电路需要更改。
方案二,只需要更改单片机程序即可,硬件不需要更改,只需要软件更改。
硬件更改代价大,周期长,成本高(重新生产),软件更改,周期短(只是软件更改的时间),成本低(只需要软件升级即可)
因此选用方案二。下面开始详细设计。
1.1.2 详细设计
1.1.2.1 硬件设计
首先是硬件设计,因为硬件需要生产周期,PCB制板需要时间,PCB焊接需要时间。软件设计可以在硬件生产的时间内开发,这样就合理安排了开发进度。
硬件设计首先是根据确定的方案进行元器件选型,之前确定的单片机控制LED灯的方案,需要选择用什么型号的单片机,和什么型号的LED灯。单片机选择目前市面上应用最广泛的8051单片机,具体型号为STC公司的89C52型单片机。LED灯有直插和表贴两种。为节省PCB面积,我们选择表贴的LED灯。主要元器件选择好以后,开始原理图设计
设计好的原理图如图所示

硬件设计主要分两部分,一部分电路为单片机要正常运行所必须的电路,包括电源电路,晶振电路,RESET电路。
另一部分为IO口控制电路完成控制功能(即控制LED灯亮灭)
单片机工作首先需要5V的电源,这个可以由外接电源提供,电路板上只需提供一个插头即可。
然后需要晶振提供恒定的时钟,如下图所示

单片机的能正常工作必须有一个时钟信号,单片机所有的操作都是基于这个时钟的,就像现实生活中,我们每个人会以统一的北京时间为基准,来安排我们的工作生活,如果每个人的表所显示的时间不是统一的,你的表是3点的时候我的表是1点,那么我们的工作生活就会乱套。 单片机内部的各个部分,如存储器,计数器,ALU都会以这个输入的时钟信号为基准来进行工作,如果没有这个时钟信号,各个部分就会错乱。

振荡周期
即单片机输入的时钟信号的周期
机器周期:一个机器周期是指CPU访问存储器一次所需要的时间,例如取指令、读存储器、写存储器等等。
8051单片机的一个机器周期为12个振荡周期
指令周期:即单片机执行一条指令所消耗的时间,它以机器周期为单位。通常8051单片机执行一条指令,如加,减等会需要1个或2个机器周期,少数指令,如乘除指令会消耗4个机器周期
最后需要一个复位电路,供初始化和单片机死机时能够恢复运行状态。8051单片机的复位(RESET)引脚在高电平持续24个振荡周期后即进行复位操作,即RESET引脚接逻辑高电平约0.002ms以上即进行复位。但一般为了系统的可靠性,我们在要执行复位操作时,给单片机RESET引脚逻辑高电平的时间为
100ms左右,即在RESET引脚输入一个这样的波形为达到这样的设计效果设计啊电路,这是一个典型的阻容复位电路,其中上电复位的电路部分如下图所示:

图中的电路在系统没有上电时,VCC为0V,电容C6完全放电。当系统上电时,电容C6开始充电,电容两端电压为0,因此A点电压为VCC,为逻辑高电平,然后,随着电容C6的充电,电容两端的电压逐渐上升,直至为VCC,此时A点的电压为0V,即逻辑低电平。
在实际系统中,微控制器输入电压阈值大约为1.1~1.3V,低于这个阈值的电压被认为是逻辑0,超过这个阈值被认为是逻辑1。也就是说,A点电压在上电时的VCC到下降至1.2V的这个时间t,就是单片机复位引脚逻辑高电平持续的时间。
而逻辑高电平持续的时间t取决于电阻R5的阻值和电容C6的容值。具体按如下公式计算

=2V,VCC=5V,当R=10k,C=10uF时,t约为100ms
即逻辑高电平持续时间为100ms,满足先前我们对复位操作所提出的要求。
在次电路基础之上,我们附加一个硬件复位按钮,如下图所示

按钮按下时,将A点电压拉到VCC,并对电容C6放电,在按钮释放时将执行上面所说的复位流程。





点亮发光二极管的电路如图所示

图中可以看出,当单片机IO口输出低电平时,二极管导通,电流由单片机片外“灌”入单片机片内,这种方式称为“灌电流”方式。有人会问,能不能把发光二极管反过来接呢?答案是可以的,反过来二极管负端接地,当单片机IO口输出高电平时,二极管导通。不过最好不这样接。因为51单片机的I/O口线输出低电平时的灌电流能力较强,可达20mA,而输出高电平时的拉电流能力要弱些,图中接法可以充分利用口线的灌电流能力。
硬件原理比较简单,前面已经讲得很清楚了,原理图设计完后,就开始PCB设计,由于我们已经提供了单片机开发板,故先将PCB设计跳过,在最后一章作详细介绍。下面开始软件设计
1.1.1.1 软件设计
单片机软件编程和编译现在普遍使用KeilC软件,该软件最新版是KEIL4,下面以Keil4为例,怎样建立一个名为tutorial的工程。
//Tips:建议大家使用Keil软件时,尽量使用英文文件名,避免软件对中文支持得不好导致的各种各样不确定的问题。

建立一个新工程,单击Project 菜单New uVision Project,如下图所示




新建tutorial文件夹,命名工程文件名也为tutorial,保存



选择工程文件保存路径,该工程的所有相关文件如.c .hex.h等文件都保存在该路径下,我们一般一个工程对应一个文件夹,便于管理。现在要新建一个名为tutorial的工程,因此存放路径的文件夹也命名为tutorial


点击保存后,会弹出如下对话框,让你选择单片机型号,STC单片机为国产单片机,未加入KEILC型号库中,可以选择配置与其相同的SST SST89C54单片机,ATMEL单片机直接选择相应型号即可


弹出加入引导文件,点确定


此时,新的名为 tutorial的Project就已经建立,Source Group 1 下没有.C文件。需要将写好的C代码保存为.C文件加入这个工程


在,写单片机C语言程序之前我们还要做一些基本的配置,配置单片机晶振频率,右键单击Target 1 在弹出的菜单中选择Options for Target‘Target 1


在新弹出的对话框中Xtal(MHz)选项后填单片机所使用的晶振的频率,开发板核心板选用11.0592MHz。




在Output选项卡中,勾选Create Hex File 选项,是编译软件输出Hex文件供程序烧录



设置完成后点击OK,
下面新建.C文件并加入Project。所有的程序代码都存成.C
格式。点击File –》New


会新生成一个Text文件,在此文件中输入C程序代码


File->Save As


文件名tutorial.c 点击保存



此时文本文件保存为.C格式


将.C文件加入Projct 右键单击Source Group 1 ,在弹出菜单中选择Add Files to Group’ Source Group1’


在弹出的对话框中选择先前保存的tutorial.c文件 点击Add


发现tutorial.c文件加入到Source Group 1下



接下来在tutorial.c文件中输入C代码 正式开始编程
TIPS工程技巧 输入法需要切换到英文输入法,标点符号切换到半角状态
C代码:
#include<reg52.h> //52系列单片机头文件 工程经验 :程序注释是非常必要的
sbit led1 = P1^1; //声明单片机的P1.1 IO口 为bit 名称为led1

void main() //主函数声明
{

led1 = 0; //单片机的P1.1IO口电平为低,
//即点亮了与此IO口相连的LED
}
编程输入完后 保存文件 然后编译 注意保存备份.c文件

工程经验:注意编译前的文件保存, 调试某个模块成功后 记得保存文件 这是一个很好的工程习惯
TIPS编译常见错误
;号忘记打 是初学者的常见错误




1 Error 即1个编译错误,具体是什么错误,可以看


Syntax error near ‘}’ 即在 ‘}’附近有语法错误,其中c(8)的意思是错误在程序的第8行 可自行到第8行程序检查程序语法错误,也可以双击 Syntax error near ‘}’ 光标即自动跳到报错的‘}’ 附近 你可以检查‘}’ 附近的语法错误, 这里我们的语法错误就是漏掉了;加上 再次编译 编译成功
到此为止,软件的设计工作完成,下面就要开始进行调试测试,验证我们的硬件和软件设计是否能完成设计所期望的功能。
1.1.1 调试测试
要对产品进行调试和测试,需要产品硬件生产完后,将单片机程序烧写进单片机,然后观察运行的结果。这里我们已经有配套的HC-1型单片机开发板,所以硬件生产部分已经完成,可以在单片机开发板上进行调试和测试。在实际的工作中,我们要等待硬件PCB生产装配完成后,才可以进行软件的调试和整体测试。
接下来生成hex文件 烧写进单片机
在此加入ISP软件烧HEX文件方法
首先,双击ISP软件,进入软件界面,选择单片机型号,使用什么型号的单片机就选择型号,开发板选用STC89C52RC单片机,因此我们做相应选择。


选择串口号,此时USB线连接PC和核心板开发板,在PC机的任务管理器中查看串口号为COM?,并在COM选择中选择对应的串口号,选择COM4


打开需要烧录的程序文件,点击 打开程序文件 按钮,选择你需要烧录的hex文件,hex文件由Keil软件编译生成,默认保存在工程文件夹内


Hex文件导入之后,如图所示


此时关闭单片机开发板开关,使单片机断电,然后点击 Download/下载 按钮 然后开启单片机开发板,使单片机上电。这是可以看到程序烧录进单片机的提示信息
Add pic here
程序烧录进单片机之后,接通单片机电源,观察运行情况,开发板第一盏led在不停的闪烁,而不是一直亮 为什么?

我们回过头来看看编译软件keil C,编译软件所做的事情就是把C语言程序编译成对应的汇编程序以至于机器码 然后烧到程序
我们来看看keil 讲我们这个程序编译成的汇编语句


点击红圈圈住的按钮
进入界面


看红圈圈住的Disassembly窗口
程序最后一行 22 RET 22为机器码 对应汇编语句为RET
代表 reset复位,即keil C 在编译汇编语句后自动在程序最后加了一句 复位语句,每当程序执行完后 单片机复位 复位所进行的操作是单片机所有寄存器的值赋初值,p1^1口的初值是1,复位后程序重新开始从第一句执行,又开始执行main函数 p1^1口又被置0 如此循环 就造成了led灯在闪烁而不是常亮
解决方法,while(1);加入程序结尾
重新下载程序到开发板,led常亮
Keil C为什么自作主张的加一条我们并没有写的语句呢?是为了避免程序跑飞,不加while(1)语句 而又不加复位语句 有可能PC指针继续往下运行,
大家可以看汇编语句后面的语句都是
C:0×0013 00 NOP
C:0×0014 00 NOP
C:0×0015 00 NOP
C:0×0016 00 NOP
C:0×0017 00 NOP
一直到
C:0xFFFF 00 NOP
NOP就是空的意思 即程序存储器里面没有指令,但是PC指针仍然会往下执行一直到0xFFFF,如果程序存储器后半段中有遗留的数据,程序就会跑飞,如果这样的话 问题很难定位与查找
加While(1)后C:0×0011 80FE SJMP C:0011 80FE是机器码 对应的汇编语句是SJMP C:0011 即程序指针不停在这个地址循环
更改后的代码如下所示
#include<reg52.h> //52系列单片机头文件 工程经验 :程序注释是非常必要的
sbit led1 = P1^1; //声明单片机的P1.1 IO口 为bit 名称为led1

void main() //主函数声明
{

led1 = 0; //单片机的P1.1IO口电平为低,
//即点亮了与此IO口相连的LED
While(1);
}
到此为止,产品调试成功。
进入测试,我们把开发板上电,工作一段时间,LED恒定常亮
1.1.1 文档整理
调试成功之后,将原理图(.sch文件),PCB,软件代码(.c文件)进行整理保存。便于生产部门进行批量生产。
这样整个产品开发的过程完毕。

如果作为一个教学实验,现在就是一个完整的实验。那么作为产品开发来讲,客户也许会提出对产品的修改意见,要求进行产品升级。

相关帖子

沙发
eyesmall| | 2012-7-25 10:14 | 只看该作者
学习

使用特权

评论回复
板凳
sedatefire| | 2012-7-25 15:50 | 只看该作者
你这个帖子让我震惊了,图文并茂洋洋洒洒三百篇,就是为了问最后一小段程序里面的
while(1)为什么放末尾?

唉,不管你问的是真是假

该语句为了防止pc指针越界,可能会导致程序复位

使用特权

评论回复
地板
sedatefire| | 2012-7-25 15:50 | 只看该作者
我很怀疑这是广告贴啊:L
这是一个有技术含量的广告帖

使用特权

评论回复
5
symmetry|  楼主 | 2012-7-25 22:25 | 只看该作者
3# sedatefire

。。。  我没问问题  我帖子最后已经解答这个问题了  你没仔细看帖子

使用特权

评论回复
6
andrew.xu| | 2012-7-26 15:34 | 只看该作者
虽然很简单的事情,但是楼主说的很详细,对于新手很有帮助,几乎是手把手的带你入门,关键还是从项目的角度阐述的,很好

使用特权

评论回复
7
ifezix| | 2012-7-26 16:35 | 只看该作者
强悍

使用特权

评论回复
8
symmetry|  楼主 | 2012-7-26 19:23 | 只看该作者
6# andrew.xu
呵呵 多谢夸奖

使用特权

评论回复
9
symmetry|  楼主 | 2012-7-26 19:23 | 只看该作者
7# ifezix
:)

使用特权

评论回复
10
O寥艺O| | 2012-7-27 07:23 | 只看该作者
学习了

使用特权

评论回复
11
hp34401a| | 2012-7-27 12:59 | 只看该作者
初学还是不错!任何单片机大师都从点亮一盏LED开始!:)

使用特权

评论回复
12
lastnight1034| | 2012-7-27 15:47 | 只看该作者
按我的理解RET应该是return的意思,不是RESET的意思吧?

使用特权

评论回复
13
symmetry|  楼主 | 2012-7-27 23:44 | 只看该作者
12# lastnight1034

RET的确是return的意思  不过单片机中return到程序最开始的0000  相当于是RESET

使用特权

评论回复
14
symmetry|  楼主 | 2012-8-1 23:24 | 只看该作者

使用特权

评论回复
15
eyesmall| | 2012-8-2 11:29 | 只看该作者
我来学习的

使用特权

评论回复
16
冰冷幽默| | 2012-9-6 17:00 | 只看该作者
写的很多,很长我要慢慢看

使用特权

评论回复
17
NE5532| | 2012-9-6 17:12 | 只看该作者
本来想给你条裤子,结果总电路图忘画LED限流电阻,后面图里限流电阻的值乱给,只有算了。

使用特权

评论回复
18
秋风式街球| | 2012-9-11 00:45 | 只看该作者
牛X啊

使用特权

评论回复
19
engineertky| | 2012-10-6 20:52 | 只看该作者
过程好像有点长哦!不过很详细,也顶个。

使用特权

评论回复
20
blhxsm| | 2013-10-24 09:47 | 只看该作者
坐下来慢慢看~~

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

32

帖子

1

粉丝