8*8 LED矩阵第一个灯
为了提升软件编码能力,不愿当码农的码农发起向软件工程师征程的号角,学习硬件,首先从简单的51开始,慢慢扩展知识点。
看了几节基础视频,LED点亮的原理就是控制板子上连接LED的阳极方的电平为高电平(1),阴极为低电平(0)才能点亮,其他情况,双高,双低,接反的情况都不能正常工作。
首先上图(我的51版型号是HC6800-ES),此次学习的是8*8矩阵LED模块,74HC595芯片。
上图中画圈的地方是控制74HC595的OE引脚的电平,OE位低电平时(重要),74HC595芯片输出正常。
8*8LED矩阵是通过74HC595芯片和P0 I/O口(8个I/O口)控制。如上图所示,P0口控制显示列, D0-D7(595芯片的输出口)控制行,相交处为一个LED点。
此款单片机的8*8LED模式
可以看到,阳极接到D0-D7,阴极接到P0^0-P0^7口,要让某个LED点亮,例如左上角第一个,只需让D7=1(高电平),D0-D6=0 。 P0^7=0(低电平),P0^0-P0^6=1即可(这里=0也可以,由于D0-D6=0,LED阳极方向低电平,电流总是不通)。 P0口可以直接控制,使P0=0x7f(0111 1111)即可。
下面讲解如何控制D0-D7。
74HC595串行输入,并行输出
我理解串行输入就是一次次输入一个0或者1,最后输出的时候输出8位的数比如 1001 0110。
重要的地方:
- 595芯片只有一个输入口,即P34 I/O口,对应图中的SER,引脚号时14
- P36,对应图中SRCLK,引脚号是11,它的作用是,每当它发生一次上升沿,则P34口的电平值会在位移寄存器中左移一位。当下一次上升沿发生时,移位寄存器的所有位都往左移一位。
- P35,对应图中RCLK,引脚号12,当它发生一次上升沿,移位寄存器的值会输出到DA-DH(D0-D7),这里注意一下,D7是高位。
- 由于移位寄存器是一直往左移,那么第一个进入移位寄存器的就是最高位,所以,P34第一个值是高位。
请看下面两张图对照。
程序说明:
spi_shcp对应引脚号是11,P36口,SRCLK。
spi_ds对应引脚号是13,P34口,SER。
spi_stcp对应引脚是12,P35口,RCLK。
引脚说明
SHCP对应P36,STCP对应P35,DS对应P34。
我们可以得出结论:595芯片是通过P3^4,P3^5,P3^6进行输入输出。
为了有助于理解(假如我们要通过595芯片输出 1000 0000),我模拟过程如下:
- 第一次:
- P3^4=1*(P34是一个I/O口,只能有0或者1)*;
- 让P3^6发生一次上升沿(P3^6初始位0),P3^6=1;
- 移位寄存器里面值为1;
- 第二次:
- 让 P3^4=0;
- P3^6发生一次上升沿,P3^6=0*(之前发生过上升沿,需要重置为0)*,P3^6=1;
- 移位寄存器里面值为10;
- 第三次:
- 让 P3^4=0;
- P3^6发生一次上升沿,P3^6=0;P3^6=1;
- 移位寄存器里面值为100;
循环8次后,移位寄存器里面的值为1000 0000
最后,通过P3^5的上升沿(P3^5=0;P3^5=1),移位寄存器中的值会被输出到D0-D7,最后D7=1,D0-D6=0;
(我的理解是这样,实际运行我不太懂)
教程代码如下:
#include "reg51.h"
#include<intrins.h>
typedef unsigned int u16; //无符号的2个字节 51单片机int占2字节
typedef unsigned char u8; //无符号的1个字节
sbit SRCLK=P3^6; // P3^6 IO口 SHCP
sbit RCLK=P3^5; // P3^5 IO口 STCP
sbit SER=P3^4; // P3^4 IO口 DS
void Hc595SendByte(u8 dat)
{
u8 a;
SRCLK=0;
RCLK=0;
for(a=0;a<8;a++) // 8次循环
{
SER=dat>>7; //DS等于传入值的最高位
dat<<=1; //最高位获取过了,将最高位移除,这一次的次高位位下次最高位
SRCLK=1; //SHCP 上升沿
_nop_(); //intrins.h中的方法。
_nop_();
SRCLK=0; // SHCP 下降沿,什么都不会发生
}
RCLK=1; // STCP上升沿,移位寄存器的数据输出
_nop_();
_nop_();
RCLK=0; // STCP下降沿,移位寄存器的数据输出
}
void main()
{
Hc595SendByte(0x80); //1000 0000 控制第一行的led
P0=0x7f; // 0111 1111 控制第一列led
while(1);
}
编译后,烧录到单片机中的效果。
为什么这里左边一列全部都亮了,预测效果应该是之亮第一列,第一个led,一开始我也是看了好久,以为代码错了,或者是595芯片的原理没有掌握好,最后我还是发现,原来一开始我的板子JOE (对应引脚是13,文档里面的OE) 接到了VCC,也就是高电平,OE在文档里面说明的是低电平才可以正常输出(但是为啥是一列全亮我也没搞明白),所以我重新将OE介入GND,此时就位低电平正常了,重新按下电源,一切正常了。