51单片机_LED点阵屏

51单片机_LED点阵屏

PS: 普中开发板需要把数码管右边的跳线帽插到左两孔中,否则点阵屏不会点亮。

点阵显示是一种常见的显示技术,广泛应用于电子设备中,如LED显示屏、电子钟表、广告牌等。它由多个LED灯组成,通过控制每个LED的亮灭来显示字符、数字或图形。51单片机是一种常用的微控制器,能够通过编程控制点阵显示的内容和效果。

在本教程中,我们将学习如何使用51单片机控制8x8点阵显示模块,并逐步实现一个简单的字符显示程序。

一、点阵显示的基本原理

点阵显示模块通常由多个LED灯排列成矩阵形式,例如8x8点阵模块由8行8列共64个LED组成。每个LED可以通过控制其所在的行和列的电平来点亮或熄灭。

  • LED点阵屏的结构类似于数码管,只不过是数码管把每一列的像素以"8"字型排列而已-
  • LED点阵屏与数码管一样,有共阴和共阳两种接法,不同的接法对应的电路结构不同
  • LED点阵屏需要进行逐行或逐列扫描,才能使所有LED同时显示

二、硬件电路组成

从上图中可以看出, 该电路是集成的, 电路中的 K1~K8 是 LED 点阵的第1-8 列, 通过 P0 口控制(低电平有效)。

DPh-DPa 是 LED 点阵的 8 行控制管脚, 通过动态数码管模块中的74HC245 进行驱动, 高电平有效。

15 和 1 到 7 脚 QA--QH: 并行数据输出

9 脚 QH 非: 串行数据输出

10 脚 SCLK 非(MR) : 低电平复位引脚

11 脚 SCK(SHCP) : 移位寄存器时钟输入

12 脚 RCK(STCP) : 存储寄存器时钟输入

13 脚 G 非(OE) : 输出有效

14 脚 SER(DS) : 串行数据输入

74HC595 芯片介绍

74HC595 是一个 8 位串行输入、并行输出的位移缓存器, 其中并行输出为三态输出(即高电平、低电平和高阻抗) 。它能将少量数据信号(如51单片机的几个IO口)高效地转换为控制大量LED(如点阵屏的行或列)所需的信号。芯片管脚及功能说明如下:

三、应用实践示例

1)显示图形

main.c

c 复制代码
#include <REGX52.H>   // 包含51单片机寄存器定义头文件,用于操作P0、P3等端口
#include "Delay.h"    // 包含自定义延时函数头文件,用于控制显示时间

// 定义74HC595芯片的三个控制引脚与单片机P3口的连接
sbit RCK=P3^5;        // RCLK (Register Clock,寄存器时钟/锁存时钟),上升沿时将移位寄存器的数据锁存到输出寄存器
sbit SCK=P3^6;        // SRCLK (Shift Register Clock,移位寄存器时钟),上升沿时移位寄存器数据移动一位
sbit SER=P3^4;        // SER (Serial Data Input,串行数据输入),逐位输入数据(1或0)

#define MATRIX_LED_PORT P0 // 定义LED点阵列选择控制端口为P0口,用于选择要点亮哪一列

void _74HC595_WriteByte(unsigned char Byte)
{
    unsigned char i; // 循环计数器,用于控制8位数据的移位
    for(i=0;i<8;i++) // 循环8次,依次处理字节的每一个位(从最高位MSB开始)
    {
        // 核心操作:逐位提取并发送
        // 1. 数据提取:(0x80>>i) 生成从最高位到最低位的位掩码(0x80=1000 0000)
        // 2. 位与操作:Byte & (0x80>>i) 检查Byte的特定位是1还是0
        // 3. 赋值结果:将比较结果(0或非0)赋给SER引脚。非0即1,0就是0。
        SER = Byte & (0x80>>i); 

        // 产生一个移位时钟上升沿,将SER引脚上的当前位数据"推入"74HC595的移位寄存器
        SCK = 1; // 时钟线拉高
        SCK = 0; // 时钟线拉低,完成一次上升沿触发
        // 循环8次后,Byte的8个位就依次全部移入了移位寄存器
    }

    // 产生一个锁存时钟上升沿,将移位寄存器中已准备好的8位数据,一次性锁存到输出寄存器(Q0-Q7)
    RCK = 1; // 锁存线拉高,此时输出引脚更新
    RCK = 0; // 锁存线拉低,完成更新。输出将保持直到下次锁存。
    // 此操作是"两段式"的关键:后台移位,瞬间更新,显示稳定无拖影。
}

void MatrixLED_ShowColumn(unsigned char Column, Data) // 参数:Column(0~7), Data(列数据)
{
    // 第一步:通过74HC595设置该列8个LED的行状态(哪个亮哪个灭)
    _74HC595_WriteByte(Data); // 将列数据Data写入595,其输出直接控制LED行(阳极或阴极,取决于硬件接法)

    // 第二步:通过P0口选择要点亮的列
    // 假设点阵屏为共阴接法,列选通为低电平有效。
    // (0x80 >> Column): 0x80(1000 0000)右移Column位,将1移动到对应列的位置。
    // ~(0x80 >> Column): 按位取反,将对应列位变为0(低电平),其余列为1(高电平),从而选通该列。
    MATRIX_LED_PORT = ~(0x80 >> Column); 

    // 第三步:保持点亮一小段时间,形成视觉暂留
    Delay(1); // 调用延时函数,大约维持1ms(具体时间取决于Delay.h的实现)

    // 第四步:消影操作!关闭所有列选通(将P0口全部置高),在切换列前熄灭所有LED。
    MATRIX_LED_PORT = 0xFF; // 0xFF(1111 1111)使所有列都为高电平(无效),点阵屏所有LED熄灭
    // 这是动态扫描显示避免"鬼影"的关键一步。
}

void main()
{
    // 初始化:将74HC595的时钟引脚置为低电平,确保初始状态稳定
    SCK = 0;
    RCK = 0;

    // 主循环,动态刷新显示
    while(1)
    {
        // 依次显示第0列到第7列的数据,每列数据是一个8位二进制数,对应8行LED的状态(1亮0灭)。
        // 这些数据共同构成了一个笑脸图案。
        // 由于循环执行速度极快,人眼看到的是完整的静态图案。
        MatrixLED_ShowColumn(0, 0x3C); // 0x3C -> 0011 1100
        MatrixLED_ShowColumn(1, 0x42); // 0x42 -> 0100 0010
        MatrixLED_ShowColumn(2, 0xA9); // 0xA9 -> 1010 1001
        MatrixLED_ShowColumn(3, 0x85); // 0x85 -> 1000 0101
        MatrixLED_ShowColumn(4, 0x85); // 0x85 -> 1000 0101
        MatrixLED_ShowColumn(5, 0xA9); // 0xA9 -> 1010 1001
        MatrixLED_ShowColumn(6, 0x42); // 0x42 -> 0100 0010
        MatrixLED_ShowColumn(7, 0x3C); // 0x3C -> 0011 1100
        
        // 循环回到开头,不断重复,实现稳定显示。
    }
}

//笔记:

//     P0 控制的是点亮哪一列       (低电平有效)
//74CH595 控制的是每列哪个LED灯点亮(高电平有效)
//综上,通过不断的扫描,实现LCD点阵屏效果

Delay.c

c 复制代码
void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

Delay.h

c 复制代码
#ifndef __DELAY_H__
#define __DELAY_H__

void Delay(unsigned int xms);

#endif

2)显示动画

main.c

c 复制代码
#include <REGX52.H>
#include "Delay.h"
#include "MatrixLED.h"

//动画数据
unsigned char code Animation[]={
	0x3C,0x42,0xA9,0x85,0x85,0xA9,0x42,0x3C,
	0x3C,0x42,0xA1,0x85,0x85,0xA1,0x42,0x3C,
	0x3C,0x42,0xA5,0x89,0x89,0xA5,0x42,0x3C,
};

void main()
{
	unsigned char i,Offset=0,Count=0;
	MatrixLED_Init();
	while(1)
	{
		for(i=0;i<8;i++)	//循环8次,显示8列数据
		{
			MatrixLED_ShowColumn(i,Animation[i+Offset]);
		}
		Count++;			//计次延时
		if(Count>15)
		{
			Count=0;
			Offset+=8;		//偏移+8,切换下一帧画面
			if(Offset>16)
			{
				Offset=0;
			}
		}
	}
}

Delay.c

c 复制代码
void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}

Delay.h

c 复制代码
#ifndef __DELAY_H__
#define __DELAY_H__

void Delay(unsigned int xms);

#endif

MatrixLED.c

c 复制代码
#include <REGX52.H>
#include "Delay.h"

sbit RCK=P3^5;		//RCLK
sbit SCK=P3^6;		//SRCLK
sbit SER=P3^4;		//SER

#define MATRIX_LED_PORT		P0

/**
  * @brief  74HC595写入一个字节
  * @param  Byte 要写入的字节
  * @retval 无
  */
void _74HC595_WriteByte(unsigned char Byte)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		SER=Byte&(0x80>>i);
		SCK=1;
		SCK=0;
	}
	RCK=1;
	RCK=0;
}

/**
  * @brief  点阵屏初始化
  * @param  无
  * @retval 无
  */
void MatrixLED_Init()
{
	SCK=0;
	RCK=0;
}

/**
  * @brief  LED点阵屏显示一列数据
  * @param  Column 要选择的列,范围:0~7,0在最左边
  * @param  Data 选择列显示的数据,高位在上,1为亮,0为灭
  * @retval 无
  */
void MatrixLED_ShowColumn(unsigned char Column,Data)
{
	_74HC595_WriteByte(Data);
	MATRIX_LED_PORT=~(0x80>>Column);
	Delay(1);
	MATRIX_LED_PORT=0xFF;
}

MatrixLED.h

c 复制代码
#ifndef __MATRIX_LED_H__
#define __MATRIX_LED_H__

void MatrixLED_Init();
void MatrixLED_ShowColumn(unsigned char Column,Data);


#endif

3)显示滚动字幕

只需要修改main.c部分即可,其余代码同上。

c 复制代码
#include <REGX52.H>
#include "Delay.h"
#include "MatrixLED.h"

//动画数据
unsigned char code Animation[]={
		0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
		0x3F,0x48,0x48,0x48,0x3F,0x00,0x7F,0x49,
		0x49,0x49,0x36,0x00,0x1C,0x22,0x41,0x41,
		0x41,0x00,0x7F,0x41,0x41,0x22,0x1C,0x00,
		0x7F,0x49,0x49,0x49,0x49,0x00,0x7D,0x00,
		0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};

void main()
{
	unsigned char i,Offset=0,Count=0;
	MatrixLED_Init();
	while(1)
	{
		for(i=0;i<8;i++)	//循环8次,显示8列数据
		{
			MatrixLED_ShowColumn(i,Animation[i+Offset]);
		}
		Count++;			//计次延时
		if(Count>10)
		{
			Count=0;
			Offset+=1;		//偏移+1
			if(Offset>40)
			{
				Offset=0;
			}
		}
	}
}
相关推荐
亿道电子Emdoor2 小时前
【Altium】原理图中网络标签作用范围的设置
单片机·嵌入式硬件
风行男孩2 小时前
stm32基础学习——串口(USART)的基本使用
stm32·嵌入式硬件·学习
点灯小铭2 小时前
基于单片机的多模式档位调节与过热保护风扇设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
星源~2 小时前
Zephyr - MCU 开发快速入门指南
单片机·嵌入式硬件·物联网·嵌入式开发·zephyr
星源~2 小时前
zephyr-开发环境配置疑难问题解决
单片机·嵌入式硬件·物联网·项目开发
BMS小旭3 小时前
CubeMx-DMA
单片机·学习·cubemx·dma
电子小白12312 小时前
第13期PCB layout工程师初级培训-1-EDA软件的通用设置
笔记·嵌入式硬件·学习·pcb·layout
清风66666612 小时前
基于单片机的多传感器智能云梯逃生控制器设计
单片机·嵌入式硬件·毕业设计·智能家居·课程设计
小何code12 小时前
STM32入门教程,第10课(上),OLED显示屏
stm32·单片机·嵌入式硬件