51单片机学习笔记 ——(六)LED点阵屏

简介

LED点阵屏实际上就是将每一个LED作为一个像素点,通过矩阵的连接方式进行连接,用少数IO口操作大量的LED显示出图像。

LED点阵屏与之前提到的数码管类似,都是将每行每列LED的阴极或阳极连接,达到逐行逐列扫描控制的效果,当某个LED满足导通条件则会发光。

74HC595

为了进一步减少IO口的使用,我们还需要用芯片74HC595来控制LED点阵屏。

功能简介

通过控制串行输入数据、寄存器时钟、串行输出时钟,74HC595可以将串行输入的数据并行输出。

图片来自b站江科大视频:

当串行时钟的上升沿到来时,串行数据被压入缓存区(类似于手枪弹匣上子弹,一颗一颗压入,最先压入的在最底下)

如果缓存区满了仍然写入数据,多出的数据就会从QH`输出,此时如果将QH`接到下一块74HC595的SER引脚就可以实现数据级联,再将两块芯片的两个时钟引脚连在一起,实现时钟同步,就实现了两块芯片的级联,可以实现16位的并行输出,而且不会增加外部引脚(仍然是3条)

当寄存器时钟的上升沿到来时,缓存区的数据被同时发送到输出缓存(并行输出)

注意:并行输出的最后一位是串行输出的第一位!

芯片引脚介绍

\overline{}\overline{OE}引脚意为Output Enable,输出使能。上方的横杠代表低电平使能,观察原理图左侧的J24部分,我们将OE和GND使用跳线帽接在一起,确保输出使能开启。

RCLK引脚意为Register Clock,寄存器时钟。

\overline{SRCLR}引脚意为Serial Clear,串行清零。清零引脚一般都设置为低电平触发。直接接到VCC意味着在运行过程中都不会清空。

SRCLK引脚意为Serial Clock,串行时钟。

SER引脚为串行数据输入引脚。

QA~QH为并行输出。

QH`用于多芯片级联。当缓存区满了之后溢出的数据会发送到QH`引脚。

51单片机上电引脚默认为高电平。

使用74HC595的另一个原因

IO口自身类型

虽然这里是为了减少IO口的使用,但是实际上我们也勉强负担的起16个IO口的需求,为什么行和列不都使用IO口直接控制呢?这样不是可以减少芯片的使用吗?

不这么做还有一个原因:单片机的IO口是弱上拉类型的,原理图大致如下:

从原理图可以看出,因为高电平保护电阻的存在,IO口低电平能够经过的电流是远大于高电平的。这也是它被称为弱上拉型的原因。

所以如果像我们上面说的那样连接,因为有保护电阻,最后我们的点阵屏就会很暗,效果不好。

改进方式

虽然如此,但是我们有时也会遇见需要IO口直接驱动外设的情况,此时外设需要的电压一般都会超出IO口能够提供的电压(3.3V、5V...),这时候我们可以考虑使用IO口驱动三极管来实现目标。

大致原理图如下:

对于NPN型的三极管,只需要基极(IO口)为高电平,就可以输出需要的VCC给外设,实现了IO口直接控制外设的功能。

当然为了防止设备损坏可以加上一个保护电阻。

实际代码

sfr、sbit

sfr意为special function register,特殊功能寄存器声明。

sbit意为special bit,特殊位声明。

这两个声明都类似于给寄存器取一个别名,便于我们记忆和提高代码的可读性。

例如:sfr P0 = 0x80 ;这一句代码就是来自于头文件REGX52.H里面,意味着我们直接写关于P0的代码,实际上就是写代码控制地址为0x80的寄存器。

sbit P0_0 = 0x80 ;则是单独控制0x80这一位,上面的sfr控制的是0x80之后的8位。

为了增加代码的可读性,此处进行声明:

sbit SER = P3_4 ;

//不叫RCLK的原因是在头文件<REGX52.H>里面已经有关于RCLK的定义了,会引起重定义

sbit RCK = P3_5 ;

sbit SRCLK = P3_6 ;
向74HC595写入数据

想要控制74HC595输出我们想要的数据,就需要将一个8位的数据按照它的规则串行写入。即先写入第八位,再写入第七位...直到第一位。

假设我们想要输出的八位数据为Byte,但是SER只有一位,应该如何把Byte的某一位赋值给SER呢?

SER如果接收到数据,只有两种情况:

1.零,SER = 0 ;

2.非零,SER = 1 ;

我们想要提取Byte的某一位,实际上就是判断Byte的某一位是0还是1,以最高位为例,我们只需要:SER = Byte & 0x80 ;此时如果Byte最高位为0,SER = 0;Byte最高位为1,SER = 0x80,也就是SER = 1。这样我们就实现了向SER写入Byte的最高位数据。

接下来就需要把SER的数据写入缓存区,即给串行时钟一个上升沿:SRCLK = 1 ;

当然记得进行软件复位:SRCLK = 0 ;

这样就写入了一位数据,接下来需要写入第二位数据,观察我们会发现,除了SER = Byte & 0x80 ;这一句代码以外,其他代码都不需要进行改变只需要将0x80改为0x40,也就是把1的位置右移一位,所以得到最终代码:

	for(i=0;i<8;i++)
	{
		SER=Byte&(0x80>>i);
		SRCLK=1;
		SRCLK=0;
	}
	RCK=1;
	RCK=0;
选中列

74HC595控制的是行的状况,所以我们还需要选择要控制的列。

在实际的使用过程中,我们需要的当然是整个点阵屏,所以需要进行逐列扫描,与LED数码管类似,先进行段选、再进行位选、延时约1ms、进行位清零(可以参考学习笔记(一))

最终代码

效果为显示棋盘

#include <REGX52.H>
#include "Delay.h"

sbit RCK=P3^5;//原理图里面的RCLK
sbit SRCLK=P3^6;
sbit SER=P3^4;//定义P34寄存器为SER(别名,增强文件可读性)(位声明)

/**
  * @brief  控制74HC595输出想要的数据
  * @param  Byte 目标数据
  * @retval 无
  */
void _74HC595_SendByte(unsigned char Byte)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		SER=Byte&(0x80>>i);//从输入信息的最高位开始判断是0还是1
		SRCLK=1;//上升沿移位置一,SER的数据进入临时寄存器(临时寄存器内部数据下移一位)
		SRCLK=0;//再次恢复原来状态
	}
	RCK=1;//上升沿锁存置一,数据送到输出口
	RCK=0;//恢复原来状态
}

/**
  * @brief  控制点阵屏某一行显示想要的图像
  * @param  col 目标行(从左到右为0-7行);data 想要点亮的位置(点亮为1,从上到下对应高位到低位)
  * @retval 无
  */
void MatrixLED_ShowCol(unsigned char col,unsigned char num)
{
	_74HC595_SendByte(num);	
	P0 = ~(0x80 >> col);//给0为选中
	Delay(1);
	P0 = 0xFF;
}

void main()
{
	RCK = 0;
	SRCLK = 0;//单片机上电默认为高电平,为了不丢失第一个数据,初始化为低电平

	while(1)
	{
		MatrixLED_ShowCol(0,0xAA);
		MatrixLED_ShowCol(1,0x55);
		MatrixLED_ShowCol(2,0xAA);
		MatrixLED_ShowCol(3,0x55);
		MatrixLED_ShowCol(4,0xAA);
		MatrixLED_ShowCol(5,0x55);
		MatrixLED_ShowCol(6,0xAA);
		MatrixLED_ShowCol(7,0x55);
	}
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值