在芯片的学习中,51可以说是入门级的芯片,它易学好用,可以为以后的学习打下良好的基础。在51单片机的学习中。我们应当一步一步慢慢来,不要好高骛远。
首先我们第一个开始学习的应当是各种元器件的认识,电容电阻电位器等的辨别与功能。接下来就是学习如何写程序,来控制单片机做一些应用。点亮一颗led灯,我们首先要看原理图

在这张图中我们就可以看到每一个led灯的链接引脚,利用引脚产生高低电平来点亮led灯(我们需要知道它们是共阴极VCA还是共阳极VCC),当时共阴极,接高电平(1)产生电位差,形成电流流动,可以点亮,同理共阳极接低电平(0)来点亮led灯。然后就可以据此来写程序。
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
sbit led=P2^0; //将单片机的P2.0端口定义为led
void main()
{
while(1)
{
led=0; //P2.0端口设置为低电平
}
}
然后我们就可以根据这个代码改变让led灯变得闪烁,只要加一个眼石函式delay来控制亮的时间和灭的时间,由此就可以达到闪烁的效果,delay函数的编写是非常简单的:
void delay(unsigned int i)//我们需要定义无字符类型的数据
{
while(i--); //只需要进行数的循环使延时单片机的数据时间
}
接下来我们就可以先让灯亮,延时之后再让灯灭了,让后无限循环就可以了。
然后上一个代码就可以改成:
led = 0;
delay(10);//可以增大或减小来控制它的闪烁速度;
led = 1;
也就可以控制每一个灯的亮灭来做一个流水灯,他们的原理都是一样的,我们就可以重复写他们的亮灭及其间隔时间来控制。
当led灯学的差不多之后就可以使用数码管了,数码管和led灯的原理都一样,只是位数多一点,我们要经过位选,再用段选控制每一个数码管中某个或几个led灯的亮与灭来显示数字。

从这张图片我们就可以直观的看到每一个数码管中每一个led灯的引脚的选择,我们就可以控制他的亮与灭来显示数字了,首先进行位置的选择,总共8位,在进行灯的选择。现在多数单片机都用到了138译码器来控制位选,我们可以用原理图来看怎样控制。

由此我们就可以对138译码器有着3个引脚控制8个位置的能力有了认识。然后我们就可以开写代码了:
#include
typedef unsigned int u16;
typedef unsigned char u8;
sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;
u8 code duan[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//从0——f,单片机多数都用16进制
u8 DisplayData[8];
void delay(u16 sum)//延时函数
{
while(sum--);
}
void DigDisplay()
{
u8 i;
for(i=0;i<8;i++)
{
switch(i)
{
case(0):
LSA=0;LSB=0;LSC=0; break;//显示第0位
case(1):
LSA=1;LSB=0;LSC=0; break;//显示第1位
case(2):
LSA=0;LSB=1;LSC=0; break;//显示第2位
case(3):
LSA=1;LSB=1;LSC=0; break;//显示第3位
case(4):
LSA=0;LSB=0;LSC=1; break;//显示第4位
case(5):
LSA=1;LSB=0;LSC=1; break;//显示第5位
case(6):
LSA=0;LSB=1;LSC=1; break;//显示第6位
case(7):
LSA=1;LSB=1;LSC=1; break;//显示第7位
}
P0=DisplayData[i];//发送段码
delay(10); //间隔一段时间扫描
P0=0x00;//消隐
}
}
void main()
{ u16 i;
while(1)
{
DigDisplay();
for(i=0;i<8;i++)//循环位选
{
DisplayData[i] = duan[i];//进行段选
}
}
}
经过了单片机的循环,就可以开始我们独立按键,及矩阵的学习。用独立按键去控制led灯,用点阵在数码管显示点阵的键值。


独立按键已经连接了高低电平,只是高低电平并未接通,我们按下之后高低电平接通,高电平由于接了低电平变成低电平,我们就可以写判断语句:
if(K1 == 0)
{
led = 1;
}
else
{
led = 0;
}
这样就可以在按键按下的时候熄灭led灯,松开的时候点亮led灯。在按键的使用中,我们还需要用到消抖和松键检测。也就可以把这个程序改为
if(k1==0) //检测按键K1是否按下
delay(1000); //消除抖动 一般大约10ms
if(k1==0) //再次判断按键是否按下
{
led=~led; //led状态取反
}
while(!k1); //检测按键是否松开
而在矩阵中,我们需要将每个键赋值(0——f),然后按键后在数码管显示数值。
#include
typedef unsigned int u16;
typedef unsigned char u8;
sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;
#define GIFO P1
#define GG P0
u16 Key;
u8 code duan[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //0--z
void delay(u16 sum)
{
while(sum--);
}
void anjian() //判断按下的按键,并且将对应的键值赋给Key
{
GIFO = 0x0f;
if(GIFO!=0x0f)
{
delay(10);
if(GIFO!=0x0f)
{
switch(GIFO)
{
case(0X07): Key=0;break;//键值的判断
case(0X0b): Key=1;break;
case(0X0d): Key=2;break;
case(0X0e): Key=3;break;
}
GIFO=0xf0;
switch(GIFO)
{
case(0X70): Key=Key;break;
case(0Xb0): Key=Key+4;break;
case(0Xd0): Key=Key+8;break;
case(0Xe0): Key=Key+12;break;
}
while(GIFO!=0xf0)
delay(10);
}
}
}
void main()
{
LSA=0; //给一个数码管提供位选
LSB=0;
LSC=0;
while(1)
{
anjian();
GG = duan[Key]; //将键值应显示数字赋给数码管
}
}
然后就可以学习点阵显示数字字符字母,点阵一般是由8*8或者16*16的led灯阵组成,由一组引脚或两组引脚控制。我们在学习时候一定要看一下原理图,经过自己缜密的思考后在进行学习,我们要明白单片机的学习离不开看原理图,这是非常重要的,我们可以从原理图看出,这是共阴极还是共阳极,他的引脚都接在了那里,我们应当怎样控制它的亮与灭。


我们就可以看到,我们这个单片机是由74HC595来控制的,由3个引脚和P0组的引脚来发送数据来进行点亮点阵中的某一个led灯,然后我们就可以看一下74HC595的原理
74HC595是具有8位移位寄存器和一个存储器,三态输出功能。
移位寄存器和存储器是分别的时钟。 数据在SHcp(移位寄存器时钟输入)的上升沿输入到移位寄存器中,在STcp(存储器时钟输入)的上升沿输入到存储寄存器中去。如果两个时钟连在一起,则移位寄存器总是比存储寄存器早一个脉冲。 移位寄存器有一个串行移位输入(Ds),和一个串行输出(Q7’),和一个异步的低电平复位,存储寄存器有一个并行8位的,具备三态的总线输出,当使能OE时(为低电平),存储寄存器的数据输出到总线。
8位串行输入/输出或者并行输出移位寄存器,具有高阻关断状态。三态。
然后明白原理我们就可以点亮点阵了
#include
#include//移位的头文件
#define GG P0
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit SRCLK=P3^6;
sbit LCLK=P3^5;
sbit SER=P3^4;
u8 code duan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
u8 code wei[8]= {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
u8 code CHARCODE[1][8]={0x00,0x66,0xff,0xff,0xff,0x7e,0x3c,0x18};//在我的单片机是个心形,单片机 //的不同可能有所不同
void delay(u8 sum)
{
while(sum--);
}
void HC595(u8 dat)
{
u8 a;
SRCLK = 0;
LCLK = 0;
for(a=0;a<8;a++)
{
SER = dat>>7;//右移7位
dat<<=1;//左移一位
SRCLK=1;
_nop_();
_nop_();
SRCLK=0;
}
LCLK=1;
_nop_();
_nop_();
LCLK=0;
}
void main()
{
u8 tab;
while(1)
{
for(tab=0;tab<8;tab++)
{
HC595(0x00); //消隐
GG = wei[tab]; //输出字码
HC595(CHARCODE[0][tab]);
delay(2);
}
}
}