没有合适的资源?快使用搜索试试~ 我知道了~
从单片机菜鸟走向单片机工程师.doc
资源推荐
资源详情
资源评论
从单片机菜鸟走向单片机工程师
第一章节
从这一章开始,我们开始迈入单片机的世界。在我们开始这一章具体的学习之前,有必要给大家先说明一
下。在以后的系列文章中,我们将以 51 内核的单片机为载体,C 语言为编程语言,开发环境为 KEIL uv3。
至于为什么选用 C 语言开发,好处不言而喻,开发速度快,效率高,代码可复用率高,结构清晰,尤其是
在大型的程序中,而且随着编译器的不断升级,其编译后的代码大小与汇编语言的差距越来越小。而关于 C
语言和汇编之争,就像那个啥,每隔一段时间总会有人挑起这个话题,如果你感兴趣,可以到网上搜索相
关的帖子自行阅读。不是说汇编不重要,在很多对时序要求非常高的场合,需要利用汇编语言和 C 语言混
合编程才能够满足系统的需求。在我们学习掌握 C 语言的同时,也还需要利用闲余的时间去学习了解汇编
语言。
1.从点亮 LED(发光二极管)开始
在市面上众多的单片机学习资料中,最基础的实验无疑于点亮 LED 了,即控制单片机的 I/O 的电平的变化。
如同如下实例代码一般
void main(void)
{
LedInit() ;
While(1)
{
LED = ON ;
DelayMs(500) ;
LED = OFF ;
DelayMs(500) ;
}
}
程序很简单,从它的结构可以看出,LED 先点亮 500MS,然后熄灭 500MS,如此循环下去,形成的效
果就是 LED 以 1HZ 的频率进行闪烁。下面让我们分析上面的程序有没有什么问题。
看来看出,好像很正常的啊,能有什么问题呢?这个时候我们应该换一个思路去想了。试想,整个程序除
了控制 LED = ON ; LED = OFF; 这两条语句外,其余的时间,全消耗在了 DelayMs(500)这两个
函数上。而在实际应用系统中是没有哪个系统只闪烁一只 LED 就其它什么事情都不做了的。因此,在这里
我们要想办法,把 CPU 解放出来,让它不要白白浪费 500MS 的延时等待时间。宁可让它一遍又一遍的扫描
看有哪些任务需要执行,也不要让它停留在某个地方空转消耗 CPU 时间。
从上面我们可以总结出
(1) 无论什么时候我们都要以实际应用的角度去考虑程序的编写。
(2) 无论什么时候都不要让 CPU 白白浪费等待,尤其是延时(超过 1MS)这样的地方。
下面让我们从另外一个角度来考虑如何点亮一颗 LED。
先看看我们的硬件结构是什么样子的。
我手上的单片机板子是电子工程师之家的开发的学习板。就以它的实际硬件连接图来分析吧。如
下图所示
从单片机菜鸟走向单片机工程师
一般的 LED 的正常发光电流为 10~20MA 而低电流 LED 的工作电流在 2mA 以下(亮度与普通发光管
相同)。在上图中我们可知,当 Q1~Q8 引脚上面的电平为低电平时,LED 发光。通过 LED 的电流约为(VCC
- Vd)/ RA2 。其中 Vd 为 LED 导通后的压降,约为 1.7V 左右。这个导通压降根据 LED 颜色的不同,
以及工作电流的大小的不同,会有一定的差别。下面一些参数是网上有人测出来的,供大家参考。
红色的压降为 1.82-1.88V,电流 5-8mA,
绿色的压降为 1.75-1.82V,电流 3-5mA,
橙色的压降为 1.7-1.8V,电流 3-5mA
兰色的压降为 3.1-3.3V,电流 8-10mA,
白色的压降为 3-3.2V,电流 10-15mA,
(供电电压 5V,LED 直径为 5mm)
74HC573 真值表如下:
通过这个真值表我们可以看出。当 OutputEnable 引脚接低电平的时候,并且 LatchEnable 引脚为
高电平的时候,Q 端电平与 D 端电平相同。结合我们的 LED 硬件连接图可以知道 LED_CS 端为高电平时候,
P0 口电平的变化即 Q 端的电平的变化,进而引起 LED 的亮灭变化。由于单片机的驱动能力有限,在此,74HC5
73 的主要作用就是起一个输出驱动的作用。需要注意的是,通过 74HC573 的最大电流是有限制的,否则可
能会烧坏 74HC573 这个芯片。
从单片机菜鸟走向单片机工程师
上面这个图是从 74HC573 的 DATASHEET 中截取出来的,从上可以看出,每个引脚允许通过的最大电流为 35mA
整个芯片允许通过的最大电流为 75mA。在我们设计相应的驱动电路时候,这些参数是相当重要的,而且
是最容易被初学者所忽略的地方。同时在设计的时候,要留出一定量的余量出来,不能说单个引脚允许通
过的电流为 35mA,你就设计为 35mA,这个时候你应该把设计的上限值定在 20mA 左右才能保证能够稳定的
工作。
(设计相应驱动电路时候,应该仔细阅读芯片的数据手册,了解每个引脚的驱动能力,以及整个芯片的驱
动能力)
了解了相应的硬件后,我们再来编写驱动程序。
首先定义 LED 的接口
#define LED P0
然后为亮灭常数定义一个宏,由硬件连接图可以,当 P0 输出为低电平时候 LED 亮,P0
输出为高电平时,LED 熄灭。
#define LED_ON() LED = 0x00 //所有 LED 亮
#define LED_OFF() LED = 0xff //所有 LED 熄灭
下面到了重点了,究竟该如何释放 CPU,避免其做延时空等待这样的事情呢。很简单,我们为系
统产生一个 1MS 的时标。假定 LED 需要亮 500MS,熄灭 500MS,那么我们可以对这个 1MS 的时标进行计数,
当这个计数值达到 500 时候,清零该计数值,同时把 LED 的状态改变。
unsigned int g_u16LedTimeCount = 0 ; //LED 计数器
unsigned char g_u8LedState = 0 ; //LED 状态标志, 0 表示亮,1 表示熄灭
void LedProcess(void)
{
if(0 == g_u8LedState) //如果 LED 的状态为亮,则点亮 LED
{
LED_ON() ;
}
else //否则熄灭 LED
{
LED_OFF() ;
}
}
void LedStateChange(void)
{
if(g_bSystemTime1Ms) //系统 1MS 时标到
{
g_bSystemTime1Ms = 0 ;
g_u16LedTimeCount++ ; //LED 计数器加一
if(g_u16LedTimeCount >= 500) //计数达到 500,即 500MS 到了,改变 LED 的状态。
{
g_u16LedTimeCount = 0 ;
g_u8LedState = ! g_u8LedState ;
}
}
从单片机菜鸟走向单片机工程师
}
上面有一个变量没有提到,就是 g_bSystemTime1Ms 。这个变量可以定义为位变量或者是其它变量,在我
们的定时器中断函数中对其置位,其它函数使用该变量后,应该对其复位(清 0) 。
我们的主函数就可以写成如下形式(示意代码)
void main(void)
{
while(1)
{
LedProcess() ;
LedStateChange() ;
}
}
因为 LED 的亮或者灭依赖于 LED 状态变量(g_u8LedState)的改变,而状态变量的改变,又依赖于 LED 计数
器的计数值(g_u16LedTimeCount ,只有计数值达到一定后,状态变量才改变)所以,两个函数都没有堵塞
CPU 的地方。让我们来从头到尾分析一遍整个程序的流程。
程序首先执行 LedProcess() ;函数
因为 g_u8LedState 的初始值为 0 (见定义,对于全局变量,在定义的时候最好给其一个确定的值)所以 LE
D 被点亮,然后退出 LedStateChange()函数,执行下一个函数 LedStateChange()
在函数 LedStateChange()内部首先判断 1MS 的系统时标是否到了,如果没有到就直接退出函数,如果到了,
就把时标清 0 以便下一个时标消息的到来,同时对 LED 计数器加一,然后再判断 LED 计数器是否到达我们
预先想要的值 500,如果没有,则退出函数,如果有,对计数器清 0,以便下次重新计数,同时把 LED 状态
变量取反,然后退出函数。
由上面整个流程可以知道,CPU 所做的事情,就是对一些计数器加一,然后根据条件改变状态,再根据这
个状态来决定是否点亮 LED。这些函数执行所花的时间都是相当短的,如果主程序中还有其它函数,则 CPU
会顺次往下执行下去。对于其它的函数(如果有的话)也要采取同样的措施,保证其不堵塞 CPU,如果全部
基于这种方法设计,那么对于不是非常庞大的系统,我们的系统依旧可以保证多个任务(多个函数)同时执
行。系统的实时性得到了一定的保证,从宏观上看来,就是多个任务并发执行。
好了,这一章就到此为止,让我们总结一下,究竟有哪些需要注意的吧。
(1) 无论什么时候我们都要以实际应用的角度去考虑程序的编写。
(2) 无论什么时候都不要让 CPU 白白浪费等待,尤其是延时(超过 1MS)这样的地方。
(3) 设计相应驱动电路时候,应该仔细阅读芯片的数据手册,了解每个引脚的驱动能力,
以及整个芯片的驱动能力
(4) 最重要的是,如何去释放 CPU(参考本章的例子),这是写出合格程序的基础。
附完整程序代码(基于电子工程师之家的单片机开发板)
#include<reg52.h>
sbit LED_SEG = P1^4; //数码管段选
sbit LED_DIG = P1^5; //数码管位选
sbit LED_CS11 = P1^6; //led 控制位
sbit ir=P1^7;
#define LED P0 //定义 LED 接口
剩余19页未读,继续阅读
资源评论
是空空呀
- 粉丝: 171
- 资源: 3万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功