1.从零开始的单片机生活-LED篇
目录
- 1.前言
- 2.51单片机介绍
- 3.LED模块介绍
- 4.点亮一个LED
- 5.LED闪烁
- 6.LED流水灯
- 7.独立按键控制LED亮灭
- 8.独立按键控制LED状态
- 9.独立按键控制LED显示二进制
- 10. 独立按键控制LED移位
- 11.后记
1.前言
《关于没洗杯子在便利店门口穿越异世界学习51单片机这回事》, 分享学习过程和感悟。
2.51单片机介绍
使用普中51-实验板,Keil5写代码,STC-ISP进行烧录。
下面介绍开发板各部分。
1.动态数码管模块
2.接口
3.接口
4.8*8LED点阵模块
5.LED模块(本期主角)
6.矩阵按键模块
7.红外接收模块
8.DS18B20数字温度传感器:将环境温度转化为数字信号
9.NRF24L01无线通信模块:实现2.4GHz频段的低功耗、短距离无线数据传输
10.独立按键模块
11.USB转TTL下载模块
12.CH340C芯片,实现USB下载和串口通信功能
13.AMS1117低压差线性稳压器,将USB提供的5V电源,转换为单片机系统所需的3.3V电压
14.电源开关
15.ADC模块
16.存储数据
17.复位按键
18.蜂鸣器模块
19.DS1302时钟模块:为单片机系统提供精准的实时时钟(RTC)功能
20.五线四相步进电机
21.STC89C52RC单片机芯片
22.接口
23.74HC595D芯片,扩展I/O(输入/输出)口,控制8x8 LED点阵模块
24.74HC245KA芯片:驱动数码管段选,驱动点阵屏/LED,双向传输控制
25.扩展芯片
3.LED模块介绍
(1)LED在生活中很常见,它具有单向导通性,只有施加正向电压时才会发光。
(2)在单片机上,是8个LED组成的LED模块。编号由D1到D8,下面是两个限流电阻,左上方的P20-P27就是LED所对应的端口引脚,下面看看这一部分的原理图。
(3)从电源正极出发,经过LED,再串联了限流电阻,接到P2引脚。
(4)那么我们怎样控制LED呢,如图LED左端电源已经提供了高电平,要使LED发光,那么P2端口就要输出低电平。规定输出高电平为5V,低电平为0V,所以当P2输出0V,电路就会导通。
(5)那么接下来的问题就是如何控制P2输出高低电平,也就是单片机怎样控制外设。首先要了解寄存器,寄存器是一种存储器,以8个为一组,单片机通过控制寄存器来控制外部设备。CPU向P2寄存器写入0/1,连接驱动器后放大电流,最后就再在输入/输出端口输出高低电平,1对应5V高电平,0对应0V低电平。
所以只需要在P2端口的寄存器写入0/1就可以控制LED。
4.点亮一个LED
实现如图效果:只点亮D1 LED,其余LED熄灭。
代码如下:
#include<STC89C5xRC.H>voidmain(){while(1){P2=0xF0;}}首先引入头文件,因为P2定义在这个头文件中,不然keil5不知道P2是什么。
#include<STC89C5xRC.H>接着是主函数,P2的寄存器以8位为一组,刚好对应D1-D8八个LED,所以用二进制的八位分别对应,不过规定低位是D1,高位是D8(如下图所示)。
这样 P2=1111 1110 就可以点亮D1了。
而while(1)的循环使程序一直运行。
voidmain(){while(1){P2=11111110;}}
用十六进制表示:
#include<STC89C5xRC.H>voidmain(){while(1){P2=0xFE;}}5.LED闪烁
先看实现效果:
LED闪烁
我们已经点亮了LED,要实现LED闪烁,那么LED的状态是:亮—灭— 亮—灭……
代码如下:P2=1111 1111熄灭所有的LED,也就是D1的熄灭状态。(P2=0xFE)
#include<STC89C5xRC.H>voidmain(){while(1){P2=0xFE;P2=0xFF;}}看起来perfect,但是实际在单片机上运行这个程序时,会发现D1LED一直是亮的,这是因为单片机的运行速度非常快,熄灭的时间太短导致看起来“没有熄灭”,所以我们要加一个“延时”来实现闪烁效果。
这是一个500ms的延时函数:
#include<INTRINS.H>voidDelay500ms(void)//@11.0592MHz{unsignedchardata i,j,k;_nop_();i=4;j=129;k=119;do{do{while(--k);}while(--j);}while(--i);}加上延时函数之后,LED闪烁的过程变成了:亮—延时—灭—延时……
(周期为一秒的闪烁)
完整代码如下:
#include<STC89C5xRC.H>voidDelay500ms(void)//@11.0592MHz{unsignedchardata i,j,k;_nop_();i=4;j=129;k=119;do{do{while(--k);}while(--j);}while(--i);}voidmain(){while(1){P2=0xFE;Delay500ms();P2=0xFF;Delay500ms();}}6.LED流水灯
先看实现效果:
LED流水灯
我们已经点亮了一个LED,那么依次点亮D1~D8,同时使其余的LED熄灭,再重复这个过程,就得到了流水灯。
得到了以下代码:
#include<STC89C5xRC.H>voidmain(){while(1){P2=0xFE;P2=0xFD;P2=0xFB;P2=0xF7;P2=0xEF;P2=0xDF;P2=0xBF;P2=0x7F;}}对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗对吗
下面是结果:
因为单片机的运行速度非常快!!!快速的执行循环代码 使所有的LED看起来一直保持点亮,所以必须增加延时函数。
代码如下:
#include<STC89C5xRC.H>voidDelay500ms(void)//@11.0592MHz{unsignedchardata i,j,k;i=4;j=129;k=119;do{do{while(--k);}while(--j);}while(--i);}voidmain(){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();}}7.独立按键控制LED亮灭
先看实现效果:
独立按键控制LED亮灭
首先介绍独立按键:
这里用到的是独立按键模块(10):电路原理图如图
四个按键共地,另一端连接P3端口,要实现按下按键时LED点亮,松手时熄灭,就要检测按键什么时候被按下。
寄存器不仅能发出指令,还能检测端口的电平,再放到寄存器中,所以只需要读取按键对应端口的电平高低,就知道了按键什么时候被按下。
由于单片机上电时是高电平(1),按键一端是地,按键按下电路导通,变为低电平(0)。
1代表按键没有被按下;
0代表按键被按下。
我们来分析整个过程:
端口电平为1——>按键按下——>端口电平为0——>点亮LED——>松开按键——>熄灭LED。
代码如下:
#include<STC89C5xRC.H>voidmain(){while(1){if(P31==0){P20=0;}else{P20=1;}}}其中,P31对应k1按键,P20对应第一个LED(D1)。既可以像P2=0xFE来控制P2端口的八个寄存器,也可以用P20=0/1来单独控制单个寄存器。
8.独立按键控制LED状态
先看演示:
独立按键控制LED状态
要实现按下按键来点亮/熄灭LED, 本质上是检测到按下一次按键后来LED端口在0/1之间进行切换,那么就要讲到按键抖动。
也就是说,按键没有被按下时是高电平1,按下时是低电平0,松开又回到高电平1,但在按下和松开的瞬间,按键抖动会造成电平在0/1之间不断切换,5~10毫秒后才会稳定。按下一次按键对应1——0——1的变化,但是按键抖动造成随机次数的变化,也就是会判断为多次按下按键,所以我们要添加延时来消除抖动,分别加在检测到按下和松手的时候。
代码如下:
#include<STC89C5xRC.H>voidDelay(intx)//@11.0592MHz{unsignedchardata i,j;while(x--){_nop_();i=2;j=199;do{while(--j);}while(--i);}}voidmain(){while(1){if(P31==0)//1.检测到按键按下{Delay(20);//2.延时消除按下时的抖动while(P31==0);//3。等待按键松开Delay(20);//4.延时消除松开时的抖动P20=~P20;//5.取反实现LED亮灭转换}}}第三步为什么不用:
#include<STC89C5xRC.H>voidDelay(intx)//@11.0592MHz{unsignedchardata i,j;while(x--){_nop_();i=2;j=199;do{while(--j);}while(--i);}}voidmain(){while(1){if(P31==0){Delay(20);if(P31==1){Delay(20);P20=~P20;}}}}当按住按键时,会跳过**if(P31 == 1)并循环执行整个程序,松手后P31变为高电平1,被if(P31 == 0)的判断卡住,不能进入内层判断,出现按下按键被忽略的情况,而while(P31 == 0);**会卡住不放行,不管你按多久,松手后才继续往下执行翻转。
9.独立按键控制LED显示二进制
先看演示:
独立按键控制LED显示二进制
来举个例子,我们用八个二进制代表LED八个寄存器,模拟二进制计数:
8765432100000000//初始 //000000001//每按键一次加1 //100000010//200000011//300000100//400000101//500000110//600000111//700001000//8~~~~~~发现LED的点亮就是按键按下次数的二进制表示再取反即可,所以只需要记录按键次数,每按下一次,次数加一,再将次数赋给P2端口即可。
代码如下:
#include<STC89C5xRC.H>voidDelay(intx)//@11.0592MHz{unsignedchardata i,j;while(x--){_nop_();i=2;j=199;do{while(--j);}while(--i);}}voidmain(){charlednum=0;while(1){if(P31==0){Delay(20);while(P31==0);Delay(20);lednum++;P2=~lednum;}}}10. 独立按键控制LED移位
先看演示:
独立按键控制LED移位
要实现用两个按键控制LED左右移动,先来举个例子,这里我们用1表现LED点亮:
87654321(寄存器)00000001//假设初始电平状态00000010//左移00000100//左移00001000//左移00000100//右移~发现左右移动是初始情况左移位/右移位按键按下次数,而次数由两个按键的加减得到,再取反就得到点亮LED的寄存器表示。
实现:变量记录按键按下次数,右移加,左移减(实际LED移动),判断LED移动到边界的情况。
代码如下:
#include<STC89C5xRC.H>voidDelay(intx)//@11.0592MHz{unsignedchardata i,j;while(x--){_nop_();i=2;j=199;do{while(--j);}while(--i);}}voidmain(){charlednum=0;P2=~0x01;while(1){if(P30==0){Delay(20);while(P30==0);Delay(20);lednum++;if(lednum>=8){lednum=0;}P2=~(0x01<<lednum);}if(P31==0){Delay(20);while(P31==0);Delay(20);if(lednum==0){lednum=7;}else{lednum--;}P2=~(0x01<<lednum);}}}11.后记
拖延症陆陆续续写了很久,第一次写这种文章,内容,格式不好之处请见谅。文章中有些图片截自B站江协科技。以后也会继续更新学习内容,谢谢大家。(求三连)
