
今天是单片机学习的第二次课程,上次课程我们已经学习了仿真软件的使用与联调,并且构造了一个LED闪烁的简单小项目。
没有基础的同学会对上次项目中的部分电路产生疑惑,不用担心,本次课程我们会就会解决这个问题。
本次的任务目标有:
1.了解51单片机的最小系统:晶振电路、电源电路以及复位电路
2.了解GPIO口的调用方式。
3.通过P0口设计由多个LED组成的流水灯
单片机最小系统
01
晶振电路
晶振电路的作用会产生固定频率的脉冲,单片机会将这个脉冲作为自己的时钟频率,在Proteus中名字为CRYSTAL。
一个稳定的晶振频率对于单片机的正常工作至关重要,所以,将晶振直接接入单片机晶振引脚的行为并不推荐,因为晶振起振的一瞬间会产生电感,对单片机工作产生干扰。因此,我们会在晶振两端分别接入两个电容(我这里选择30PF电容)来抵消电感带来的影响。
虽然晶振频率越大,单片机工作越快,但这个值并不是越大越好。为了精准延时,一般我们会选择12MHz的晶振,如果是为了串口通信,选择11.0592MHz的晶振则会更加方便。
02
电源电路
电源的作用无需赘述,这是所有电器工作的保证。
03
复位电路
即便是晶振完美运行,单片机也难免在工作中遇到这样那样的问题,所以我们需要一个复位电路(单片机的复位接口为RST )能够一键恢复单片机的起始状态,给它重生的机会。复位电路一般分为加电自动复位,或者按键复位,我们这里选择的是自动复位电路。
另外,在实际操作中,下载电路也是必不可少的,主要用于传输写好的hex二进制文件,但这并不属于单片机的最小电路。
GPIO端口的调用方式
AT89C51芯片共有40个引脚,其中除了电源,晶振等特殊功能的引脚之外,其余引脚都是I/O功能,负责输入/输出,并且多数都身兼数职,多功能复用。
其实当我们利用C51语言对单片机进行编程时,实际就是对寄存器进行操作,GPIO引脚也不例外,如P0口,其实就是P0寄存器组,其中每个引脚又有单独的寄存器相对应。AT89C51芯片中的寄存器组,有的支持位寻址,有只能作为一个整体进行赋值。而我们的GPIO引脚,非常方便的支持位寻址,我们可以对每一个引脚进行单独赋值。
一个跑马灯~灯~灯项目
Proteus中的原理图构建
本次所用到的元件如下:AT89C51、CAP、CAP-ELEC、CRYSTAL、LED-YELLOW、NPN、RES
连接完成后的原理图如下:

这里有几点需要格外注意:
1. Proteus中的AT89C51中只有38个引脚,隐藏了VCC与GND引脚,默认已经接通电源;
2. 比上次新加入了NPN(三极管)这个元件,作用像开关,当输入口接高电平时,电路导通,平时显示高阻态。之所以没有用I/O口直接驱动LED是因为I/O口引脚电流较小,不能正常驱动大部分模块。因此我们的一般原则是:I/O口只控制,不驱动;
3. 标号一致的引线代表着彼此之间连通,这是在Proteus中节约时间、简化线路的方法之一。
Keil中的代码~~~

#include
void delay(unsigned int c)//误差 0us 延时10ms 晶体振荡12HZ
{
unsigned char a, b;
for (;c>0;c--)//无需赋值,否则多一步会有误差
{
for (b=38;b>0;b--)
{
for (a=130;a>0;a--);
}
}
}
void main()
{
while(1)
{
P0 = 0x01;
delay(100);
P0 = 0x02;
delay(100);
P0 = 0x04;
delay(100);
P0 = 0x08;
delay(100);
P0 = 0x10;
delay(100);
P0 = 0x20;
delay(100);
P0 = 0x40;
delay(100);
P0 = 0x80;
delay(100);
}
}
说明如下:
1. 因为我们需要使用P0的所有端口,所以此处使用的是对寄存器组整体赋值的方法,各位读者可以自行尝试位寻址的方式实现该项目;
2. 该项目中多次重复对P0寄存器组赋值,其实具体效果与 左移 运算没差别,熟悉汇编的同学可以在头文件中引入intrins.h文件,利用汇编指令优化改写本程序。

观察到LED灯泡依次被点亮,间隔大约一秒,说明试验成功。