一、所需元器件
- 52单片机芯片 X 1;
- 8*8 LED点阵 X 32;
- 74HC595位移寄存器 X 16 ;
- 74HC154译码器 X 1;
- 74HC04 X 4;
- PNP三极管 X 16;
- 电阻电容若干。
二、STC89C52
STC89C52是STC公司生产的一种低功耗、高性能CMOS8位微控制器,具有 8K 在系统可编程Flash存储器。STC89C52使用经典的MCS-51内核,但做了很多的改进使得芯片具有传统51单片机不具备的功能。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
52单片机最小系统原理图:
三、点阵
LED点阵屏通过LED(发光二极管)组成,以灯珠亮灭来显示文字、图片、动画、视频等,是各部分组件都模块化的显示器件,通常由显示模块、控制系统及电源系统组成。
8X8点阵实物图
8X8点阵原理图
四、点阵驱动原理
列驱动
74HC595具有8位移位寄存器和一个存储器,三态输出功能。 移位寄存器和存储器有相互独立的时钟。数据在SH_cp(移位寄存器时钟输入)的上升沿输入到移位寄存器中,在ST_cp(存储器时钟输入)的上升沿输入到存储寄存器中去。如果两个时钟连在一起,则移位寄存器总是比存储寄存器早一个脉冲。移位寄存器有一个串行移位输入(Ds),和一个串行输出(Q7’),和一个异步的低电平复位,存储寄存器有一个并行8位的,具备三态的总线输出,当使能OE时(为低电平),存储寄存器的数据输出到总线。8位串行输入/输出或者并行输出移位寄存器,具有高阻关断状态。
行驱动
74HC154是一款高速CMOS器件,译码器可接受4位高有效二进制地址输入,并提供16个互斥的低有效输出。74HC154可充当一个1-16的多路分配器。
引脚1-11 13-17 :输出端。(outputs (active LOW))
引脚12:Gnd电源地 (ground (0 V))
引脚18-19:使能输入端、低电平有效 (enable inputs (active LOW))
引脚20-23:地址输入端 (address inputs)
引脚24:VCC电源正 (positive supply voltage)
行驱动电路原理图
五、PCB layout图
PCB 2维图展示
PCB 3维图展示
六、Proteus 仿真
仿真所需元器件
仿真图单片机部分
仿真图点阵屏部分
七、C程序代码
#include<REG51.h>
#define uchar unsigned char
#define uint unsigned int
uchar speed=8; //移动速度
//595芯片引脚
sbit ST=P3^5;
sbit SH=P3^6;
sbit DATA=P3^7;
//154芯片引脚
sbit EN=P2^4;
//按键
sbit K1=P1^0;
sbit K2=P1^1;
sbit K3=P1^2;
sbit K4=P1^3;
sbit K5=P1^4;
sbit K6=P1^5;
//按键触发标志位
bit LeftFlag;
bit RightFlag;
bit UpFlag;
bit DownFlag;
bit ZJ1Flag;
bit ZJ2Flag=1; //开始显示模式
//延时函数
void delay(uchar ms)
{
uchar y;
for(;ms>0;ms--)
for(y=120;y>0;y--);
}
uchar code hanzi[][32]={
};
void SendByte(uchar a) //向595发送字节
{
uchar byte,i;
byte=~a;
for(i=0;i<8;i++)
{
SH=0;
if(byte&0X80)
DATA=1;
else
DATA=0;
SH=1;
byte<<=1;
}
}
void LeftDisplay(void) //左移
{
uchar i,j,scan,k;
for(i=0;i<16;i++) //16个汉字
{
if(LeftFlag==1)
{
for(k=0;k<speed;k++) //移动速度
{
scan=0; //154译码
if(LeftFlag==1) //
{
for(j=0;j<31;j+=2)
{
ST=0;
SendByte(hanzi[i+7][j+1]); //发送数据
SendByte(hanzi[i+7][j]);
SendByte(hanzi[i+6][j+1]);
SendByte(hanzi[i+6][j]);
SendByte(hanzi[i+5][j+1]);
SendByte(hanzi[i+5][j]);
SendByte(hanzi[i+4][j+1]);
SendByte(hanzi[i+4][j]);
SendByte(hanzi[i+3][j+1]);
SendByte(hanzi[i+3][j]);
SendByte(hanzi[i+2][j+1]);
SendByte(hanzi[i+2][j]);
SendByte(hanzi[i+1][j+1]);
SendByte(hanzi[i+1][j]);
SendByte(hanzi[i][j+1]);
SendByte(hanzi[i][j]);
ST=1; //一个上升沿送数据
EN=0;
P2=scan;
delay(4);
EN=1;
scan++;
}
}
else
break;
}
for(k=0;k<speed;k++)
{
scan=0;
if(LeftFlag==1)
{
for(j=0;j<31;j+=2)
{
ST=0;
SendByte(hanzi[i+8][j]); //另外半个字
SendByte(hanzi[i+7][j+1]);
SendByte(hanzi[i+7][j]);
SendByte(hanzi[i+6][j+1]);
SendByte(hanzi[i+6][j]);
SendByte(hanzi[i+5][j+1]);
SendByte(hanzi[i+5][j]);
SendByte(hanzi[i+4][j+1]);
SendByte(hanzi[i+4][j]);
SendByte(hanzi[i+3][j+1]);
SendByte(hanzi[i+3][j]);
SendByte(hanzi[i+2][j+1]);
SendByte(hanzi[i+2][j]);
SendByte(hanzi[i+1][j+1]);
SendByte(hanzi[i+1][j]);
SendByte(hanzi[i][j+1]);
ST=1;
EN=0;
P2=scan;
delay(4);
EN=1;
scan++;
}
}
else
break;
}
}
else
break;
}
}
void RightDisplay(void) //右移
{
uchar i,j,k,scan;
for(i=0;i<16;i++)
{
if(RightFlag==1)
{
for(k=0;k<speed;k++)
{
scan=0;
if(RightFlag==1)
{
for(j=0;j<31;j+=2)
{
ST=0;
SendByte(hanzi[i][j+1]);
SendByte(hanzi[i][j]);
SendByte(hanzi[i+1][j+1]);
SendByte(hanzi[i+1][j]);
SendByte(hanzi[i+2][j+1]);
SendByte(hanzi[i+2][j]);
SendByte(hanzi[i+3][j+1]);
SendByte(hanzi[i+3][j]);
SendByte(hanzi[i+4][j+1]);
SendByte(hanzi[i+4][j]);
SendByte(hanzi[i+5][j+1]);
SendByte(hanzi[i+5][j]);
SendByte(hanzi[i+6][j+1]);
SendByte(hanzi[i+6][j]);
SendByte(hanzi[i+7][j+1]);
SendByte(hanzi[i+7][j]);
ST=1;
EN=0;
P2=scan;
delay(5);
EN=1;
scan++;
}
}
else
break;
}
for(k=0;k<speed;k++)
{
scan=0;
if(RightFlag==1)
{
for(j=0;j<31;j+=2)
{
ST=0;
SendByte(hanzi[i][j]);
SendByte(hanzi[i+1][j+1]);
SendByte(hanzi[i+1][j]);
SendByte(hanzi[i+2][j+1]);
SendByte(hanzi[i+2][j]);
SendByte(hanzi[i+3][j+1]);
SendByte(hanzi[i+3][j]);
SendByte(hanzi[i+4][j+1]);
SendByte(hanzi[i+4][j]);
SendByte(hanzi[i+5][j+1]);
SendByte(hanzi[i+5][j]);
SendByte(hanzi[i+6][j+1]);
SendByte(hanzi[i+6][j]);
SendByte(hanzi[i+7][j+1]);
SendByte(hanzi[i+7][j]);
SendByte(hanzi[i+8][j+1]);
ST=1;
EN=0;
P2=scan;
delay(5);
EN=1;
scan++;
}
}
else
break;
}
}
else
break;
}
}
void UpDisplay(void) //上移
{
uchar i,j,k,scan;
char temp=0;
for(i=0;i<16;) //16个字
{
if(UpFlag==1)
{
for(k=0;k<speed;k++)
{
scan=15-temp; //译码
if(UpFlag==1)
{
for(j=0;j<2*temp+1;j+=2)
{
ST=0;
SendByte(hanzi[i+7][j+1]);
SendByte(hanzi[i+7][j]);
SendByte(hanzi[i+6][j+1]);
SendByte(hanzi[i+6][j]);
SendByte(hanzi[i+5][j+1]);
SendByte(hanzi[i+5][j]);
SendByte(hanzi[i+4][j+1]);
SendByte(hanzi[i+4][j]);
SendByte(hanzi[i+3][j+1]);
SendByte(hanzi[i+3][j]);
SendByte(hanzi[i+2][j+1]);
SendByte(hanzi[i+2][j]);
SendByte(hanzi[i+1][j+1]);
SendByte(hanzi[i+1][j]);
SendByte(hanzi[i][j+1]);
SendByte(hanzi[i][j]);
ST=1;
EN=0;
P2=scan;
delay(5);
EN=1;
scan++;
}
}
else
break;
}
temp++; //控制译码
if(temp==16)
{
temp=0; //temp复位
i+=8; //显示下四个字
}
}
else
break;
}
}
void DownDisplay(void) //下移
{
uchar i,j,k,scan;
char temp=30;
for(i=0;i<16;)
{
if(DownFlag==1)
{
for(k=0;k<speed;k++)
{
scan=0;
if(DownFlag==1)
{
for(j=temp;j<31;j+=2) //开始j=30
{
ST=0;
SendByte(hanzi[i+7][j+1]);
SendByte(hanzi[i+7][j]);
SendByte(hanzi[i+6][j+1]);
SendByte(hanzi[i+6][j]);
SendByte(hanzi[i+5][j+1]);
SendByte(hanzi[i+5][j]);
SendByte(hanzi[i+4][j+1]);
SendByte(hanzi[i+4][j]);
SendByte(hanzi[i+3][j+1]);
SendByte(hanzi[i+3][j]);
SendByte(hanzi[i+2][j+1]);
SendByte(hanzi[i+2][j]);
SendByte(hanzi[i+1][j+1]);
SendByte(hanzi[i+1][j]);
SendByte(hanzi[i][j+1]);
SendByte(hanzi[i][j]);
ST=1;
EN=0;
P2=scan;
delay(5);
EN=1;
scan++;
}
}
else
break;
}
temp-=2;
if(temp==-2)
{
temp=30;
i+=8;
}
}
else
break;
}
}
void ZJDisplay1(void) //
{
uchar i,j,k,scan,temp;
for(i=0;i<16;)
{
if(ZJ1Flag==1)
{
for(k=0;k<speed;k++)
{
scan=0;
if(ZJ1Flag==1)
{
for(j=0;j<2*temp+1;j+=2)
{
ST=0;
SendByte(hanzi[i+7][j+1]);
SendByte(hanzi[i+7][j]);
SendByte(hanzi[i+6][j+1]);
SendByte(hanzi[i+6][j]);
SendByte(hanzi[i+5][j+1]);
SendByte(hanzi[i+5][j]);
SendByte(hanzi[i+4][j+1]);
SendByte(hanzi[i+4][j]);
SendByte(hanzi[i+3][j+1]);
SendByte(hanzi[i+3][j]);
SendByte(hanzi[i+2][j+1]);
SendByte(hanzi[i+2][j]);
SendByte(hanzi[i+1][j+1]);
SendByte(hanzi[i+1][j]);
SendByte(hanzi[i][j+1]);
SendByte(hanzi[i][j]);
ST=1;
EN=0;
P2=scan;
delay(5);
EN=1;
scan++;
}
}
else
break;
}
temp++;
if(temp==16)
{
temp=0;
i+=8;
}
}
else
break;
}
}
void ZJDisplay2(void) //
{
uchar i,j,k,scan,z=0;
char temp=30;
for(i=0;i<16;)
{
if(ZJ2Flag==1)
{
for(k=0;k<speed;k++)
{
scan=15-z; //z译码控制
if(ZJ2Flag==1)
{
for(j=temp;j<31;j+=2)
{
ST=0;
SendByte(hanzi[i+7][j+1]);
SendByte(hanzi[i+7][j]);
SendByte(hanzi[i+6][j+1]);
SendByte(hanzi[i+6][j]);
SendByte(hanzi[i+5][j+1]);
SendByte(hanzi[i+5][j]);
SendByte(hanzi[i+4][j+1]);
SendByte(hanzi[i+4][j]);
SendByte(hanzi[i+3][j+1]);
SendByte(hanzi[i+3][j]);
SendByte(hanzi[i+2][j+1]);
SendByte(hanzi[i+2][j]);
SendByte(hanzi[i+1][j+1]);
SendByte(hanzi[i+1][j]);
SendByte(hanzi[i][j+1]);
SendByte(hanzi[i][j]);
ST=1;
EN=0;
P2=scan;
delay(5);
EN=1;
scan++;
}
}
else
break;
}
temp-=2;
z++;
if(temp==-2)
{
temp=30;
i+=8;
z=0;
}
}
else
break;
}
}
void ClearFlag(void) //清标志位
{
LeftFlag=0;
RightFlag=0;
UpFlag=0;
DownFlag=0;
ZJ1Flag=0;
ZJ2Flag=0;
}
void KeyScan(void)
{
if(K1==0)
{
delay(10);
if(K1==0)
{
while(!K1);
ClearFlag();
LeftFlag=1;
}
}
if(K2==0)
{
delay(10);
if(K2==0)
{
while(!K2);
ClearFlag();
RightFlag=1;
}
}
if(K3==0)
{
delay(10);
if(K3==0)
{
while(!K3);
ClearFlag();
UpFlag=1;
}
}
if(K4==0)
{
delay(10);
if(K4==0)
{
while(!K4);
ClearFlag();
DownFlag=1;
}
}
if(K5==0)
{
delay(10);
if(K5==0)
{
while(!K5);
ClearFlag();
ZJ1Flag=1;
}
}
if(K6==0)
{
delay(10);
if(K6==0)
{
while(!K6);
ClearFlag();
ZJ2Flag=1;
}
}
}
void main(void)
{
TMOD=0X01;
TH0=(65535-1000)/256;
TL0=(65535-1000)%256;
ET0=1;
EA=1;
TR0=1;
while(1)
{
if(LeftFlag==1)
{
LeftDisplay();
}
if(RightFlag==1)
{
RightDisplay();
}
if(UpFlag==1)
{
UpDisplay();
}
if(DownFlag==1)
{
DownDisplay();
}
if(ZJ1Flag==1)
{
ZJDisplay1();
}
if(ZJ2Flag==1)
{
ZJDisplay2();
}
}
}
void timer0(void) interrupt 1 //刷新 按键
{
TH0=(65535-1000)/256;
TL0=(65535-1000)%256;
KeyScan();
}