目录
51单片机
1.单片机基础
1-1.内部构成
1-2.51单片机
2.LED
2-1.点亮一个LED
2-2.LED闪烁
2-3.LED流水灯
2.独立按键控制LED
2-1 独立按键控制LED亮灭
2-2 按键的抖动
2-4独立按键控制LED状态
2-5独立按键控制LED展示二进制
3.数码管
3-1.静态数码管
假设数码管连接方式为 共阴极连接,如果上数码管显示 数字6 ?
3-2.动态数码管
CPU、RAM、ROM、定时器、中断系统、通讯接口等
相当于袖珍版计算机,一个芯片能构成完整的计算机系统
公司:STC公司
位数:8位
RAM:512字节 第二天丢失 相当于电脑内存条
ROM:8k(Flash) 长期储存 相当于电脑硬盘
ROM是read only memory;RAM是random access memory;
工作频率:12MHz
LED:
中;发光二极管
英:Light Emitting Diode
图像如下:
2-1-1.电阻
电阻表示方式:
102 = 1K => 10 00
473 => 47*10^3
电阻作用:
限流
2-1-2.点亮方式
原理:
改变每个二极管输出的高低电频
(高电频亮,低不亮)
方式;
通过CPU控制寄存器来控制硬件电路,由此控制电频
2-1-3.程序
注意:在C语言中不能直接输入二进制,必须进制转换——二转十六
例:
想让第一个灯亮的话,寄存器对应的是
void main()
{
P2=0xFE;
}
但编译不会成功,因为缺少头文件。
注:当延时函数中出现 nop() 时;
函数头加上 #include
所以:
#include
void main()
{
P2=0xFE;
}
这时编译就成功了!
eg:在用STC-ISP时,需要在编译后下载一个hex file
随后在STC-ISP上下载编程就可以啦
(注意:需要重新启动单片机LED才会亮)
因为需要LED闪烁,我们只需让程序进入一个亮灭的循环——while循环就行了。
#include
void main()
{
while(1)
{
P2 = 0xFE;
P2 = 0xFF;
}
}
其余方法见“点亮一个LED”。
但是你执行完之后发现灯一直在亮,一看程序又没什么问题。
那么,问题出在哪里呢?
答案是单片机的速度问题。其实单片机上的LED灯在闪,但是由于速度太快,肉眼无法观测到。
由此可知,我们需要每执行完一行后延时500ms,这个可以在STC-ISP内执行。
执行方式:
在STC-ISP中找到软件延时计算器,然后选择需要延迟的时间(注意:需要根据自己单片机的型号和频率更改所涉频率以及指令集)。设定完后会出现一段代码,将这段代码复制至刚刚所写的程序中即可。
到这儿就结束了吗?显然没有。复制完代码段后,还要写一个它所属的头文件,这样才能进行编译,到这里程序才完全结束。
普通方案,复制粘贴,在上述LED闪烁的while循环中设置八个灯依次闪烁的程序,内容如下。
#include
#include
void Delay500ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
i = 4;
j = 205;
k = 187;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
while(1)
{
P2=0xFE;
Delay500ms();
P2=0xFD;
Delay500ms();
P2=0xFB;
Delay500ms();
P2=0xF7;
Delay500ms();
P2=0xEF;
Delay500ms();
P2=0xDF;
Delay500ms();
P2=0xBF;
Delay500ms();
P2=0x7F;
Delay500ms();
}
}
但这种方案仍有弊端——每次只能设置一次闪烁的时间间隔。但如果我们给一个函数,只需要在程序中给一个参数就可以修改间隔时间,那将会更加简便。
我们还是将延时函数复制下来,区别是,我们需要设置一个变量,例如:
void Delay1ms(unsigned int xms)
这时我们就有一个可以定义时间的参数。
下一步时修改程序,我们应该设置一个循环,没换一次时间它都能执行:
unsigned char i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
随后函数写入使用即可。
单片机的按键可以改变电频,不按下是高电频,按下后是低电频。按键的按下与松开由寄存器来识别
#include
void main()
{
while(1)
{
if(P3_1==0)
{
P2_0=0;
}
else
{
P2_0=1;
}
}
}
C51数据运算
0001 1110>>1 -> 0000 1111
0011 1100<<1 -> 0111 1000
按位异与(或):
0001 1000 & 0010 1010 -> 0000 1000
0001 1000 | 0010 1010 -> 0011 1010
按位异或:
0001 1000 ^ 0010 1010 -> 0011 0010(一样是0,不一样是1)
按位取反:
~0001 1000 -> 1110 0111
按键按下时会有抖动,大概在10-15ms,为了规避这个对按键按下的影响,所以定义了一个Delay函数,并对其进行调用。
Delay(20);
while(P3_1==0);
Delay(20);
按键消抖一般分为4步:
1、判断按键是否按下
2、消抖
3、再次判断按键是否按下
4、等待按键松开
### 2-3独立按键控制LED二进制显示
```c
#include
#include
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms){
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
void main(){
unsigned char LEDnum=0; //引入变量
while(1){
if(P3_1==0){
Delay(20); //通过delay去抖
while(P3_1==0); //while作用:
//按键启动if循环,松手走出while循环,运行下一步代码
Delay(20);
LEDnum++; //16进制0,1,2,3,4
P2=~LEDnum; //取反
}
}
#include
void Delay(unsigned int xms) //@12.000MHz
{
while(xms)
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
void main()
{
while (1)
{
if (P3_1 == 0)
{
Delay(20);
while (P3_1 == 0)
{
}
Delay(20);
P2_0 = ~P2_0;
}
}
}
此程序表现为按一次亮,再按一次灭。(运用按位取反来实现)
#include
#include
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms){
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
void main(){
unsigned char LEDnum=0;
while(1){
if(P3_1==0){
Delay(20);
while(P3_1==0);
Delay(20);
if(LEDnum>=8){
LEDnum=0;
}
//LEDnum=1 0000 0001---0000 0010 取反1111 1101
P2=~(0x01<
此处主要运用移位运算方式。
3-1-1.一位数码管
上图为 一位数码管,数码管有两种连接方式(对应 右边上下两幅图);
右上图的原理图,8个LED的阴极都连在一个引脚上,称为共阴极连接;
右下图的原理图,8个LED的阳极都连在一个引脚上,称为共阳极连接;
左下角的 左边图片 ,定义了8个LED的名称;
左下角的 右边图片 ,定义了引脚的名称,与右图的引脚名称一一对应
假设数码管连接方式为 共阳极连接,观察可以发现,数码管中的 LED 的引脚引出,使用的是就近原则;
要让数码管显示 数字6,让要 LED-A、C、D、E、F、G亮起;
共阴极的公共端 要接地(给数据‘0’,或者是低电平);
阳极(称为位选端)根据LED的亮灭需求给 数据0或1(1亮、0灭) ,称为 段码(阳码) (1011 1110 即为段码);
如果 共阳极连接,共阳极端 要接到 VCC(高电平),阴极给 数据0或1 (1灭,0亮),称为 段码(阴码),和共阴极正好是相反关系;
共阳极连接→共阳极端接VCC并选中→阴极(位选端)传递(阴码)段码(1亮、0灭)→数码管显示共阴极连接→共阴极端接GND并选中→阳极(位选端)传递(阳码)段码(1灭、0亮)→数码管显示
3-1-2.四位一体数码管
开发板上即为 四位一体的数码管,且有两个,正好组成了 八位数码管;
2.四位数码管,(每位的公共端 单独引出来,位选端全部连在一起(所有A段连在一起、所有B段连在一起……),总共有12个引脚;
代码:让数码管第三位显示6
#include
void main()
{
P2_4=1;
P2_3=0;
P2_2=1;
P0=0x7D;
while(1)
{
}
}
发现这样一个现象,数码管无法在同一时间显示多个数字,其在同一时刻下只能有一个显示,
只有一个数码管能被点亮,即使有多个被选中的数码管,显示的数字也是相同的;
那么如何让数码管多位显示不同数字(动态数码管显示)?
利用人眼视觉的暂留 和 数码管显示的余辉 的原理
先让第一位数码管显示1,然后很快地让第二位数码管显示2,再很快地让第三位数码管显示3,
让它不断地扫描,重复显示1、2、3的过程,这样三个数字就“同时”显示了;
如图,数码管连接方式为 共阴极连接,这样传输数据,就能让第三位显示 数字1 了;
而上面的 LED1 ~ 8,其实接在了138译码器的输出端,138译码器正好可以实现让LED1 ~ 8输出 0或1.