51单片机学习笔记(一)
我所使用的51单片机概况
下图为我所使用的单片机:
其中的外设及相关部件为:
1:独立按键;
2:一个向下凹陷的小槽:标志单片机的正极接口所在方向;
3:NRF24L01:无线通信模块;
4:红外接收头;
5:DS18B20:温度传感器;
6:矩阵键盘;
7:74HC595:用于拓展I/O口;
8:LED;
9:LED点阵屏;
10:LCD12864的接口;
11:LCD1602的接口;
12:调节LCD的清晰度;
13:晶振11.0592MHz;
14:数码管;
15:74HC138:控制数码管位选;
16:74HC245:控制数码管段选;
17:步进电机的接口和控制模块;
18:DS1302:一个时钟芯片,用于计时;
19:蜂鸣器;
20:变阻器;
21:热敏电阻;
22:光敏电阻;
23:外接其他传感器的接口;
24:冷启动按键;
25:复位按键;
1:复位电路;
2:晶振电路;
3:中断允许控制寄存器引脚;
单片机工作电压:3.5V到5.5V
定时器:3个
中断源:8个
中断优先级:4个
最多I/O口数量:39个
控制LED
点亮LED
由此图可知,LED的一端接的都是高电平。于是,只要引脚端是低电平,就能使LED点亮P。
注意:在上图中P2_7是高位,而P2_0是低位。
P2口是可位寻址,因此在对P2口进行赋值时,既可以对每一位进行逐一赋值。当P2口没有被赋值0时,所有的LED都是灭的,也就是所有引脚的初始值都是1.
如果想要点亮第二个灯和第七个灯,有以下两种赋值方法:
逐一赋值:
#include <REGX52.H>
void main()
{
while(1)
{
P2_1=0;
P2_6=0;
}
}
整体赋值:
#include <REGX52.H>
void main()
{
while(1)
{
P2=0xbd;
}
}
由于在单片机对程序的执行中,单片机会反复地执行代码,不断地从头开始循环。所以,为了使程序的执行限制在主函数内,通常我们需要在主函数中加入一个死循环。
使LED闪烁
为了实现LED的闪烁,需要让单片机每隔一段时间,改变LED的状态。由于目前单片机只需要执行改变LED状态的指令,不需要同时执行其他指令,所以,可以使用Delay函数让单片机在不需要改变LED状态期间处于停滞状态。于是,使LED闪烁的代码如下
#include <REGX52.H>
void Delay(int a)
{
unsigned char i, j;
while(a--){
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void main()
{
P2_0=0;
while(1)
{
Delay(1000);
P2_0=~P2_0;
}
}
Delay函数可在STC-ISP中的软件延时计算器获得,将其中的配置设置为“1毫秒”,“STC-Y1"获得函数Delay1ms后再在进行更改。将其更改成上述代码中的Delay函数。
LED流水灯
代码如下:
#include <REGX52.H>
void Delay(int a)
{
unsigned char i, j;
while(a--){
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void main()
{
unsigned char a=1;//定义8个字节的变量a,来表示每一次”1“的位置。
while(1)
{
if(a==0)//一旦超出定义范围,重置a=1。
a=1;
P2=~a;//P2等于a的取反。
a=a*2;
Delay(250);
}
}
控制独立按键
由上图知:独立按键的公共端都接在低电平,而另一端都是单片机的引脚,单片机的引脚出来一般都是高电平。因此,当按键按下时,开关接通,相对应的,其引脚也将变成低电平。独立按键从左至右四个开关分别对应引脚为P3_1,P3_0,P3_2,P3_3。
消抖与检测松手
消抖:在按键按下的瞬间和松开的瞬间,由于机械触点的弹性作用,一个开关在闭合时不会马上接通,而是会抖动一会。于是开关处的电位会发生短时间的抖动变化,而为了使这一部分抖动不影响单片机的运行,所以一般会使用Delay函数使单片机不处理这部分抖动。
检测松手:由于在按下按键时,引脚处持续为低电平。因此,要检测按下按键的次数,只需要检测松手的次数。于是,可以循环让按下按键的瞬间的前一刻的按键状态,当前一刻为0后一刻为1时,说明按键发生了松手;当前一刻为1后一刻为0时,说明按键发生了按下。
检测独立按键的代码如下:
#include <REGX52.H>
void Delay(int a)
{
unsigned char i, j;
while(a--){
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void main()
{
P2_0=0;
while(1)
{
if(P3_1==0)
{
Delay(20);
while(P3_1==0);
Delay(20);
P2_0=~P2_0;
}
}
}
独立按键控制LED显示二进制
代码如下:
#include <REGX52.H>
void Delay(int a)
{
unsigned char i, j;
while(a--){
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void main()
{
unsigned char a=0;
while(1)
{
if(P3_1==0)
{
Delay(20);
while(P3_1==0);
Delay(20);
a++;
}
P2=~a;
}
}
独立按键控制LED移位
代码如下:
#include <REGX52.H>
void Delay(int a)
{
unsigned char i, j;
while(a--){
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void main()
{
unsigned char a=1;
while(1)
{
if(P3_1==0)
{
Delay(20);
while(P3_1==0);
Delay(20);
a=a*2;
if(a==0)
a=1;
}
P2=~a;
}
}
控制数码管
数码管的显示是以一种扫描的方式显示的,即程序会重复地询问控制数码管的引脚的值,并决定LED的亮灭。因此数码管的显示需要长时间占用单片机的运行。
静态数码管显示
要使数码管显示,需要先确定显示内容所在的位置,然后还有显示的内容,这就关系到位选和段选。
位选:
74HC138译码器:
该译码器所能复制三个引脚用于控制右边8个LED的接口,对P2_2,P2_3,P2_4进行赋值能够选中右边的LED的位置:
第一个LED: P2_4=1;P2_3=1;P2_2=1;
第二个LED: P2_4=1;P2_3=1;P2_2=0;
第三个LED: P2_4=1;P2_3=0;P2_2=1;
第四个LED: P2_4=1;P2_3=0;P2_2=0;
第五个LED: P2_4=0;P2_3=1;P2_2=1;
第六个LED: P2_4=0;P2_3=1;P2_2=0;
第七个LED: P2_4=0;P2_3=0;P2_2=1;
第八个LED: P2_4=0;P2_3=0;P2_2=0;
使用该译码器进行位选时,需要注意以下几点:
1、位选中,每次只能选择一个LED;
2、P2_2口为低位,P2_4口为高位;
3、记忆方法:每一个代表LED的位置位选其实是LED的位置减一再取其二进制,把每一位分离,并按高低位赋值给P2_4,P2_3,P2_2这三个引脚。
4、当没有对位选进行赋值时,P2_4,P2_3,P2_2这三个引脚的初始值均为1,所以数码管默认初始位置为的一个LED
段选:
由上图可知:
在数码管中,其连接方式为共阴极的连接方式。因此,想要点亮数码管,就应该使对应的想点亮的LED连接的引脚为1。由上图可知,一个LED有10个灯,这是个灯的控制引脚从高位到低位依次分别为P0_7,P0_6,P0_5,P0_4,P0_3,P0_2,P0_1,P0_0。
进行段选时,需要注意以下几点:
1、当没有对段选进行赋值时,所有引脚的初始值均为1,所以数码管默认初始显示为点亮所有LED。
2、段选中,P0口可以位寻址。因此,在赋值时,既可以整体赋值,也可以对P0_0等进行单独赋值。
使数码管静态显示的代码如下:
#include <REGX52.H>
void main ()
{
while(1)
{
P2_2=0;
P2_3=1;
P2_4=0;
P0=0x7d;
}
}
动态数码管显示
由于数码管的位选每次只能选中一个LED。因此,想要实现数码管上出现多个LED同时显示不同的内容,就需要利用数码管扫描显示的原理,让数码管显示一个LED后马上显示下一个LED,由于数码管的扫描速度很快加上人眼的暂留效应,就能使数码管看起来能够多个LED同时显示不同的内容。
消影:
由于在单片机中,是先选中位选,再执行段选。在没有延时和清零情况下,直接进入下一个位选,会导致上一个段选残留进入到下一个位选,直到下一个段选执行才结束。这样,就会导致LED中的内容出现串位,使显示效果变差。
所以,要在一个段选执行之后,将段选清零。这样,才不会是上一个段选影响到下一个位选。
同时,要在段选和清零之间延时一点点时间,这样能是数码管的亮度更好。(由于延时期间,单片机不执行程序。所以,延时时间不能太长,否则数码管的亮度会下降甚至出现闪烁)
使数码管动态显示各个LED位置的代码如下:
#include <REGX52.H>
void Delay(int a) //@11.0592MHz
{
unsigned char i, j;
while(a--){
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void light(unsigned char postion,unsigned char value)
{
unsigned char x[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
switch(postion)
{
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 8:P2_4=0;P2_3=0;P2_2=0;break;
}
P0=x[value];
Delay(1);
P0=0x00;
}
void main ()
{
while(1)
{
light(1,1);
light(2,2);
light(3,3);
light(4,4);
light(5,5);
light(6,6);
light(7,7);
light(8,8);
}
}
我的学习笔记(1)到此为止,谢谢阅读!