51单片机8*8点阵原理及实现
2023-01-12 来源:zhihu
LED点阵(8*8)
LED 点阵是由发光二极管排列组成的显示器件,在我们日常生活的电器中随处可见,被广泛应用于汽车报站器,广告屏等。
通常应用较多的是 8* 8 点阵,然后使用多个 8 * 8 点阵可组成不同分辨率的 LED点阵显示屏,比如 16* 16 点阵可以使用 4 个 8* 8 点阵构成。因此理解了 8* 8LED点阵的工作原理,其他分辨率的 LED 点阵显示屏都是一样的。这里以 8* 8LED 点阵来做介绍。
发光原理
8* 8 点阵共由 64 个发光二极管组成,且每个发光二极管是放置在行线和列线的交叉点上,当对应的某一行置 1 电平(行所接的是二极管的阳极,所以为高电平),某一列置 0 电平(列所接的是二极管的阴极极,所以为低电平),则相应的二极管就亮;如要将第一个二极管点亮,则 1 脚接高电平 a 脚接低电平,则第一个点就亮了;如果要将第一行点亮,则第 1 脚要接高电平,而(a、b、c、d、e、f、g、h )这些引脚接低电平,那么第一行就会点亮;如要将第一列点亮,则第 a 脚接低电平,而(1、2、3、4、5、6、7、8)接高电平,那么第一列就会点亮。
74HC95模块电路
74HC95简介
74HC595 是一个 8 位串行输入、并行输出的位移缓存器,其中并行输出为三态输出(即高电平、低电平和高阻抗)。
74HC595 是具有 8 位移位寄存器和一个存储器,三态输出功能。移位寄存器和存储器是分别的时钟。
数据在 SCK 的上升沿输入,在 RCK 的上升沿进入到存储器中。如果两个时钟连在一起,则移位寄存器总是比存储器早一个脉冲。移位寄存器有一个串行输入(DS),和一个串行输出(Q7 非),和一个异步的低电平复位, 存储寄存器有一个并行 8 位的, 具有三态的总线输出, 当 MR 为高电平,OE 为低电平时,数据在 SHCP 上升沿进入移位寄存器,在 STCP 上升沿输出到并行端口。
74HC95原理图
74HC95管脚脚图
部分管叫名称可能与原理图对应得名称不同属于正常因为命名习惯的不同,主看看管脚号以及对应的功能。
10管脚只有接低电平才有效,在本实验用不到此功能,所以原理图上直接接高电平使其失效。
74HC95功能表
H=高电平状态 L=低电平状态 ↑=上升沿 ↓=下降沿
Z=高阻 NC=无变化 ×=无效
当 MR 为高电平(即复位功能失效),OE 为低电平时,数据在 SHCP 上升沿进入移位寄存器(即数据存储在移位寄存器中),在STCP 上升沿输出到并行端口(即移位寄存器的数据传到存储寄存器中,存储器连接输出的IO口,所以输出到并行端)。
74HC595 的数据端:
QA--QH(1-7脚): 八位并行输出端,可以直接控制数码管的 8 个段。
QH'(9脚): 级联输出端。我将它接下一个 595 的 SI 端。(可以扩大多个C95,因为它是串行输出端,与串行输入的数据一样)。这样要实现16* 16的点阵,就需要4个C95,那么就可以通过第9个管脚级联实现。
SI(14脚): 串行数据输入端。
74595 的控制端说明:
SCLR(10 脚): 低点平时将移位寄存器的数据清零。通常我将它接 Vcc。
SCK(11 脚):上升沿时数据寄存器的数据移位。QA-->QB-->QC-->...-->QH;下降沿移位寄存器数据不变。(脉冲宽度:5V 时,大于几十纳秒就行了。)
RCK(12 脚):上升沿时移位寄存器的数据进入数据存储寄存器,下降沿时存储寄存器数据不变。通常我将 RCK 置为低点平,当移位结束后,在 RCK 端产生一个正脉冲(5V 时,大于几十纳秒就行了。我通常都选微秒级),更新显示数据。
G(13 脚): 高电平时禁止输出(高阻态)。如果单片机的引脚不紧张,用一个引脚控制它,可以方便地产生闪烁和熄灭效果。比通过数据端移位控制要省时省力。
5.用74HC595实现LED流水灯(8个LED)
为了更好的理解74HC595的控制原理,我们先用这个简单的实验进行说明
原理图
如图,将8个LED灯连接到J12 8个排针上,然后将8个8针与c988个并行串口相连,实现c95控制8个LED。
代码实现
#include #include typedef unsigned int u16; //对数据类型进行声明定义 typedef unsigned char u8; sbit RCLK=P3^5; //移位数据寄存器 sbit SRCLK=P3^6;//数据存储寄存器 sbit SER=P3^4; //串行输入 /*延时·函数*/ void delay(u16 i) { while(i--); } /*C95控制例程*/ void Hc595SendByte(u8 dat) { u8 i; SRCLK = 1; RCLK = 1; for(i=0;i<8;i++) //发送8位数即循环执行8次,从高位到低位开始移动将数据存入。(QH~QA) { SER = dat >> 7; //从最高位开始发送 例:1111 0000,最高为1右移7位,最后变为1,那么最高位就保存下来 dat <<= 1; //左移移位变为次高位 ,接上一例,左移移位变为次高位,在右移7位,变为次高位 /*从0到1给,即从低电平到高电平,给移位寄存器上升沿,数据存入移位寄存器中*/ SRCLK =0; _nop_(); _nop_(); SRCLK =1; } /*数据存储寄存器加上升沿,数据并行输出*/ RCLK =0; _nop_(); _nop_(); RCLK =1; } /*主函数*/ void main() { u8 lednum=0x01; //刚开始 0000 0001, while(1) { Hc595SendByte(lednum); lednum=_crol_(lednum,1); //左移,变为0000 0010,依次变化 delay(50000); } } 8* 8点阵点亮第一个LED灯(原理见代码) 代码实现 #include #include typedef unsigned int u16; //对数据类型进行声明定义 typedef unsigned char u8; sbit RCLK=P3^5; //移位数据寄存器 sbit SRCLK=P3^6;//数据存储寄存器 sbit SER=P3^4; //串行输入 sbit LED=P0^7; //第一个LED灯管脚 /*C95控制例程 ******************************************************************************* * 函 数 名 : Hc595SendByte(u8 dat1,u8 dat2) * 函数功能 : 通过595发送2个字节的数据 * 输 入 : dat1:第2个595输出数值 * * dat2: 第1个595输出数值 * 输 出 : 无 ********************************************************************************/ void Hc595SendByte(u8 dat1,u8 dat2) //两个数据,通过两个595控制第一个控制列,第二个控制行。 { u8 i; SRCLK = 1; RCLK = 1; for(i=0;i<8;i++) //发送8位数即循环执行8次,从高位到低位开始移动将数据存入。(QH~QA) { SER = dat1 >> 7; //从最高位开始发送 例:1111 0000,最高为1右移7位,最后变为1,那么最高位就保存下来 dat1 <<= 1; //左移移位变为次高位 ,接上一例,左移移位变为次高位,在右移7位,变为次高位 /*从0到1给,即从低电平到高电平,给移位寄存器上升沿,数据存入移位寄存器中*/ SRCLK =0; _nop_(); _nop_(); SRCLK =1; } for(i=0;i<8;i++) { SER = dat2 >> 7; dat2 <<= 1; SRCLK = 0; _nop_(); _nop_(); SRCLK = 1; } /*数据存储寄存器加上升沿,数据并行输出*/ RCLK =0; _nop_(); _nop_(); RCLK =1; } /*主函数*/ void main() { LED=0; while(1) { Hc595SendByte(0xfe,0x01); //第一个控制列(阴极),除了第一列全部为高电平(1111 1110) //第二个控制行(阳极),除了第一行,每一行都置为低电平(0000 1111),行列交叉及得到第一个LED灯点亮 } } LED点阵显示图像或数字 前面讲到怎样实现点亮一个LED灯。但是我们最常见的是通过LED·显示图像或数字,怎样实现呢?这就需要数码管动态显示的原理。 数码管动态显示原理: 位选控制亮不亮,而段选控制显示数字,那怎样显示不同的数字呢?这就利用了人体肉眼观察的能力。举个例子,假设段选1控制第一位数码管数字显示1,那么在显示第二个数码管是段选控制数码管显示2,而位选控制灯第二位数码管亮,第一位数码管灭。但是给人的感受是第一位数码管并没有灭(实际已经灭了),因为时间太短人体肉眼无法识别。这样就会发现数码管动态显示是向左或向右一位一位点亮。 而点阵正是利用这一原理,利用肉眼无法察觉的速度来实现点亮。 要实现行列不同位置亮灯,需要使用动态显示的方法,也要结合扫描的方法。在第一行亮灯一段时间以后灭掉,点亮第二行一段时间以后灭掉,点亮第三行一段时间以后灭掉,如此点亮,直到八行全部点亮一次,在第一行点亮到最后一行灭掉的总时间不能超过人肉眼可识别的时间,即 24 毫秒。在每一行点亮的时候,给列一个新的数据,此时对应列而在该行上要点亮的灯的数据。 数字字符显示数据 要想在点阵上显示数字等字符,首先要获取在 LED 点阵上显示数字字符所需的数据,即一个数字字符在 LED 点阵上显示,对应的每行每列都会有一些灯点亮或者熄灭,这样就会构成一组数据,也就是数字字符的显示数据,我们只要将这些数据通过 74HC595 发送到点阵对应的行或列就能显示数字字符。 数字字符数据的获取可直接通过软件的方式获取。软件不再这里介绍,网上有资源或者开发B板再带的也有。 代码实现(以显示数字0为例) 结合原理图 #include 'reg51.h' //此文件中定义了单片机的一些特殊功能寄存器 #include typedef unsigned int u16; //对数据类型进行声明定义 typedef unsigned char u8; sbit SRCLK=P3^6; sbit RCLK=P3^5; sbit SER=P3^4; u8 ledduan[]={0x00,0x00,0x3e,0x41,0x41,0x41,0x3e,0x00};//相当于数码管中的段选,由C95对行进行控制 u8 ledwei[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //位选,相当于对点阵列的控制,相当于数码管中的位选 /******************************************************************************* * 函 数 名 : delay * 函数功能 : 延时函数,i=1时,大约延时10us *******************************************************************************/ void delay(u16 i) { while(i--); } /******************************************************************************* * 函数名 : Hc595SendByte(u8 dat) * 函数功能 : 向74HC595发送一个字节的数据 *******************************************************************************/ void Hc595SendByte(u8 dat) { u8 a; SRCLK=0; RCLK=0; for(a=0;a<8;a++) { SER=dat>>7; dat<<=1; SRCLK=1; _nop_(); _nop_(); SRCLK=0; } RCLK=1; _nop_(); _nop_(); RCLK=0; } /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数 *******************************************************************************/ void main() { u8 i; while(1) { P0=0x7f; for(i=0;i<8;i++)//8行8列,在扫描行的同时,位选也进行,所以共8次循环 { P0=ledwei[i]; //位选,控制8个P0口 Hc595SendByte(ledduan[i]); //发送段选数据,如原理图,控制8个DP口与c95相连 delay(100); //延时,肉眼无法观察的速度 Hc595SendByte(0x00); //消隐,防止给下次扫描带来影响 } } }
上一篇:51单片机中断基本概念
下一篇:51单片机独立按键和矩阵按键实现