LED点阵屏由若干个独立LED以阵列的形式排列构成,
根据颜色分类有单色、双色(红+绿,一起亮为黄)、全彩;
根据像素分类有8*8、16*16等(点阵可以拼接,大规模的LED点阵通常由很多个小点阵拼接而成)(可以是任意像素,但是一般是8的倍数,因为一个字节是8倍,使字节每一位被充分利用)
LED显示屏的连接方式类似于数码管,都是将每行、列的LED以共阳/共阴的方式进行连接
单色点阵屏的连接方式(图源:B站普中科技视频截图)
点阵屏上LED的引脚有可能是按最近引脚引出,因此可能是乱序排列
共阴还是共阳对单色点阵影响不大,但对双色或是彩色存在明显影响(电流的输入输出的设置不同)
双色点阵屏的连接方式(图源:B站江协科技视频截图)
和数码管一样,点阵屏的图像显示也是通过不断扫描来实现的,扫描方式有逐行扫描和逐列扫描。
开发板上的点阵屏(图源:普中科技开发手册)
阴极直接连到P0,阳极利用74HC595扩展IO,实现三个IO控制8个引脚
开发板上的74HC595(图源:普中科技开发手册)
用P35、P36、P34来控制(跳线帽的OE要接GND进行短接)
74HC595是串行输入并行输出的移位寄存器,可用3根线输入串行数据,8根线输出并行数据,多片级联后,可输出16位、24位、32位等,常用于IO口扩展。
OE(上面带横线,低电平有效):输出使能,接低电平才输出(即接GND)
PCLK:接在P35,为寄存器时钟
SRCLR(serial clear):串行清零,会清空数据,接VCC代表不清零
SRCLK:串行时钟
SER:串行数据
OH’:用于多片级联
左边是移位寄存器,右边是输出缓存
串行数据(数据是一个一个输出的(并行即为所有数据一起输出)输出到移位寄存器,串行时钟每给一次移位上升沿,数据输出一位,当寄存器时钟有上升沿时,将移位寄存器中的数据输出到输出缓存中
eg:输出1010 0000的流程:SRCLK、RCLK置0->SER输出1->SRCLK置1->SER中的1被移入移位寄存器->SRCLK、SER置0->SRCLK置1->1被移到第二位,0被移入寄存器->…->RCLK置1->数据由移位寄存器输出到输出缓存->所有IO同时输出(并行输出)
多片级联时,将QH’接到下一片的SER,两片共用SRCLK、RCLK,当级联的数量过大时,会出现较大延迟,印象影响使用
74HC138也可以扩展IO,但是每次只能输出一位,不能并行输出
如果不用芯片,直接将阳极接到单片机IO口用于电灯不太可行,因为单片机的IO是弱上拉(输出低电平能接受大电流,输出高电平是的电流小(相当于低电平直接到GND,高电平和GND之间有个电阻)),即输出高电平时驱动能力弱,灯会比较暗(可以接一个PNP三极管,三极管上再接一个VCC,IO控制三极管开关,输出0时VCC和LED导通(NPN型则相反))
芯片输出的电流的能力也是有限的(恒压输出),点亮的LED数量多时,亮度下降(恒流输出则可以保证亮度一致)
sfr(special function register):特殊功能寄存器声明
例:sfr P0 = 0x80;
声明P0口寄存器,物理地址为0x80
sbit(special bit):特殊位声明
例:sbit P0_1 = 0x81; 或 sbit P0_1 = P0^1;
声明P0寄存器的第1位
可位寻址/不可位寻址:在单片机系统中,操作任意寄存器或者某一位的数据时,必须给出其物理地址,又因为一个寄存器里有8位,所以位的数量是寄存器数量的8倍,单片机无法对所有位进行编码,故每8个寄存器中,只有一个是可以位寻址的。对不可位寻址的寄存器,若要只操作其中一位而不影响其它位时,可用“&=”、“|=”、“^=”的方法进行位操作
STC89C52RC上的寄存器(图源:普中科技开发手册)
#include
sbit RCK = P3^5;
//位声明重新声明IO,方便使用(避免重定义,以CLK位名)
sbit SCK = P3^6;
sbit SER = P3^4;
void _74HC595_WriteByte(unsigned char Byte)
{
unsigned char i = 0;
for(i = 0; i < 8; i++)
{
SER = Byte & (0x80 >> i);//1000 0000
//SER为一位,赋值时非0即1,即赋值任何非0数,SER = 1
//取出最高位(第8位是1,则Byte = 0x80,如果是1,则Byte = 0)
SCK = 1;
SCK = 0;
}
RCK = 1;
//将数据移入IO进行输出
RCK = 0;
}
void main()
{
SCK = 0;
RCK = 0;
//时钟复位
P0 = 0;
//接通阴极
while(1)
{
_74HC595_WriteByte(0xF0);
}
}
点阵屏在段选和位选循环的过程中,下一次段选的内容可能影响上一次位选,因此需要位清零
即:->段选->位选->位清零->段选
手动计算显示笑脸对应的位码(图源:普中科技开发手册)
#include
#include"Delay.h"
sbit RCK = P3^5;
//位声明重新声明IO,方便使用(避免重定义,以CLK位名)
sbit SCK = P3^6;
sbit SER = P3^4;
#define MATRIX_LED_PORT P0
void _74HC595_WriteByte(unsigned char Byte)
{
unsigned char i = 0;
for(i = 0; i < 8; i++)
{
SER = Byte & (0x80 >> i);//1000 0000
//SER为一位,赋值时非0即1,即赋值任何非0数,SER = 1
//取出最高位(第8位是1,则Byte = 0x80,如果是1,则Byte = 0)
SCK = 1;
SCK = 0;
}
RCK = 1;
//将数据移入IO进行输出
RCK = 0;
}
void MatrixLED_ShowColmn(unsigned char Column, unsigned char Data)
{
_74HC595_WriteByte(Data);//选择行
MATRIX_LED_PORT = ~(0x80 >> Column);//选择列
Delay(1);
MATRIX_LED_PORT = 0xff;//位清零
}
void main()
{
SCK = 0;
RCK = 0;
//时钟复位
while(1)
{
//位选时按列为单位
MatrixLED_ShowColmn(0, 0x3c);
MatrixLED_ShowColmn(1, 0x42);
MatrixLED_ShowColmn(2, 0xa9);
MatrixLED_ShowColmn(3, 0x85);
MatrixLED_ShowColmn(4, 0x85);
MatrixLED_ShowColmn(5, 0xa9);
MatrixLED_ShowColmn(6, 0x42);
MatrixLED_ShowColmn(7, 0x3c);
}
}
#include
#include "Delay.h"
#define MATRIX_LED_PORT P0
sbit RCK = P3^5;
//位声明重新声明IO,方便使用(避免重定义,以CLK位名)
sbit SCK = P3^6;
sbit SER = P3^4;
/**
* @brief 74HC595写入一个字节
* @param Byte 要写入的字节
* @retval void
*/
void _74HC595_WriteByte(unsigned char Byte)
{
unsigned char i = 0;
for(i = 0; i < 8; i++)
{
SER = Byte & (0x80 >> i);//1000 0000
//SER为一位,赋值时非0即1,即赋值任何非0数,SER = 1
//取出最高位(第8位是1,则Byte = 0x80,如果是1,则Byte = 0)
SCK = 1;
SCK = 0;
}
RCK = 1;
//将数据移入IO进行输出
RCK = 0;
}
/**
* @brief Led点阵屏显示一列数据
*
* @param Column 要选择的列,范围(0~7)
* @param Data 选择列显示的数据,高位在上,1为亮,0为灭
* @retval void
*/
void MatrixLED_ShowColmn(unsigned char Column, unsigned char Data)
{
_74HC595_WriteByte(Data);//选择行
MATRIX_LED_PORT = ~(0x80 >> Column);//选择列
Delay(1);
MATRIX_LED_PORT = 0xff;//位清零
}
/**
* @brief 点阵屏初始化
*
*/
void MatrixLED_Init()
{
SCK = 0;
RCK = 0;
//时钟复位
}
我们可以通过文字取模软件自动获得需要显示的图像的位码
在“参数设置-其他设置”中可以选择横向/纵向取模、字节倒序(高位在下时用)
在“基本操作”中选择“新建图像”并设置图像的高(一般为8)和宽(合适即可),并直接用鼠标指针绘制图像
在绘制图像后,选择“取模方式-C51格式”即可生成图像对应位码
#include
#include"Delay.h"
#include "MatrixLED.h"
unsigned char code Animation[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0x10, 0x10, 0x10, 0xFF, 0x00, 0x1F, 0x15,
0x15, 0x1D, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x1F,
0x11, 0x11, 0x11, 0x1F, 0x00, 0x3D, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
//显示的图像,在最前面加8位0,用于防止图像突然被切换,实现图像的连贯显示
//ram的空间比较小,不能存放太多数据,且这里的数据无需改变值,可以用code,将数据放入Flash,此时数据不能被更改
void main()
{
unsigned char i = 0;
unsigned char offset = 0;
//偏移量
unsigned char count = 0;
MatrixLED_Init();
while(1)
{
for(i = 0; i < 8; i++)
{
MatrixLED_ShowColmn(i, Animation[i + offset]);
//利用循环,实现一行语句点亮整个点阵屏
}
count++;
if(count>10)
//在一个状态扫描10次后,进入下一个状态(左移1位)
{
count = 0;
offset++;
//图像左移
if(offset > 32)
//完整显示一次图像后重置
{
offset = 0;
}
}
}
}