51单片机-LED控制
一、点亮一个LED
实现原理:
代码实现:
1 2 3 4
| #include<reg52.h> void main(){ P2 = 0xfe; }
|
现象:
二、点亮多个LED
代码实现:
1 2 3 4
| #include<reg52.h> void main(){ P2 = 0xaa; }
|
现象:
三、流水灯
3.1 案例1
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <reg52.h>
void main(){ while(1){ P2 = 0xfe; P2 = 0xfd; P2 = 0xfb; P2 = 0xf7; P2 = 0xef; P2 = 0xdf; P2 = 0xbf; P2 = 0x7f; } }
|
现象:
分析:
为什么,所有灯都亮了,因为单片机的运行速度是非常快的,24MHz,每条语句没有进行延迟,也就是每个LED以24MHz的速度在闪烁,人眼分辨不出,但是每盏灯的亮度下降了。
为什么要加while循环,因为单片机在执行完main函数后,会再次从main函数开头执行,反反复复。
利用stc-isp生成延时函数:
频率可以通过查看开发版上晶振上面的数字。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| void Delay500ms() { unsigned char i, j, k;
_nop_(); i = 4; j = 129; k = 119; do { do { while (--k); } while (--j); } while (--i); }
|
为什么使用循环可以实现延时?在计算机组成原理中知道,cpu每执行一条语句是需要一定时间的。所以可以通过不停的执行空语句来实现延迟,但这种方法,降低了CPU的工作效率。
延时方法:软件延时和硬件延时。
- 软件延时:空循环,通过for,while延时。
- 硬件延时:通过定时器、nop();函数实现延时。
3.2 案例2
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #include <reg52.h> void Delay500ms();
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 Delay500ms() { unsigned char i, j, k;
_nop_(); i = 4; j = 129; k = 119; do { do { while (--k); } while (--j); } while (--i); }
|
现象:
注意:需要包含_nop_
函数的头文件intrins.h
,此函数作用为延迟一个指令周期。
四、独立按键控制LED的亮灭
4.1 独立按键
4.2 案例
通过开发板原理图可以查看到,K1连接的是P31。
sfr与sbit的区别:在8位单片机C语言编程中,sfr用来定义特殊功能寄存器,一般占一个字节,8位;sbit用来定义特殊功能寄存器中可以位寻址的位,占1位。
在51单片机中,特殊功能寄存器只有16进制地址尾数为0或者8,其包含的各个位才可以位寻址。
代码:
1 2 3 4 5 6 7 8 9 10
| #include <regx52.h> void main(){ while(1){ if(P3_1 == 0){ P2_0 = 0; }else{ P2_0 = 1; } } }
|
现象:
五、独立按键控制LED的状态
5.1 按键的抖动问题
对于机械开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开,所以在开关闭合及断开的瞬间会伴随一连串的抖动。虽然肉眼分辨不出,但是单片机可以识别到,从而对其造成影响。
解决办法:
- 硬件除抖:通过增加硬件实现
- 软件除抖:通过代码实现,由上图知,抖动在5-10ms后会趋于稳定,我们可以延迟5-10ms再去检测按键的状态。
5.2 案例
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include <regx52.h> #include <intrins.h> void Delay20ms(); void main(){ while(1){ if(P3_1 == 0){ Delay20ms(); while(P3_1 == 0){} Delay20ms(); P2_0 = ~P2_0; } } } void Delay20ms() { unsigned char i, j;
i = 36; j = 217; do { while (--j); } while (--i); }
|
现象:
不加延迟有时候按下松开后,LED轻微的闪了几下后灭了。
六、独立按键控制LED显示二进制
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <regx52.h> #include <intrins.h> void Delay20ms(); void main(){ unsigned char LEDNum = 0; while(1){ if(P3_1 == 0){ Delay20ms(); while(P3_1 == 0){} Delay20ms(); LEDNum++; P2 = ~LEDNum; } } } void Delay20ms() { unsigned char i, j;
i = 36; j = 217; do { while (--j); } while (--i); }
|
现象:
七、独立按键控制LED移位
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #include <regx52.h> #include <intrins.h> void Delay20ms(); void main(){ unsigned char LEDNum = 0; unsigned char LEDNum1 = 7; P2 = 0xfe; while(1){ if(P3_1 == 0){ Delay20ms(); while(P3_1 == 0){} Delay20ms();
LEDNum++; P2 = ~(0x1<<LEDNum); if(LEDNum >= 7){ LEDNum = -1; } }
if(P3_0 == 0){ Delay20ms(); while(P3_0 == 0){} Delay20ms();
if(LEDNum!=0){ LEDNum--; }else{ LEDNum = 8-1; } P2 = ~(0x1<<LEDNum); if(LEDNum <= 0){ LEDNum = 8; } } } } void Delay20ms() { unsigned char i, j;
i = 36; j = 217; do { while (--j); } while (--i); }
|
现象: