单片机8*8点阵连线

2010-01-02 21:54:00 gududesiling 阅读数 2484
8X8 LED点阵显示原理与编程技术(转)
2008/01/14 23:50

1. 实验任务 在8X8 LED点阵上显示柱形,让其先从左到右平滑移动三次,其次从右到左平滑移动三次,再次从上到下平滑移动三次,最后从下到上平滑移动三次,如此循环下去。

2. 电路原理图

   

3硬件电路连线

(1)把“单片机系统”区域中的P1端口用8芯排芯连接到“点阵模块”区域中的“DR1-DR8”端口上;

(2)把“单片机系统”区域中的P3端口用8芯排芯连接到“点阵模块”区域中的“DC1-DC8”端口上;

4程序设计内容

(1)8X8点阵LED工作原理说明

 

 

从图4.24.2中可以看出,8X8点阵共需要64个发光二极管组成,且每个发光二极管是放置在行线和列线的交叉点上,当对应的某一列置1电平,某一行置0电平,则相应的二极管就亮;因此要实现一根柱形的亮法,如图49所示,对应的一列为一根竖柱,或者对应的一行为一根横柱,因此实现柱的亮的方法如下所述:

一根竖柱:对应的列置1,而行则采用扫描的方法来实现。

一根横柱:对应的行置0,而列则采用扫描的方法来实现。

5.汇编源程序
ORG 00H
START: NOP
MOV R3,#3
LOP2: MOV R4,#8
MOV R2,#0
LOP1: MOV P1,#0FFH
MOV DPTR,#TABA
MOV A,R2
MOVC A,@A+DPTR
MOV P3,A
INC R2
LCALL DELAY
DJNZ R4,LOP1
DJNZ R3,LOP2

MOV R3,#3
LOP4: MOV R4,#8
MOV R2,#7
LOP3: MOV P1,#0FFH
MOV DPTR,#TABA
MOV A,R2
MOVC A,@A+DPTR
MOV P3,A
DEC R2
LCALL DELAY
DJNZ R4,LOP3
DJNZ R3,LOP4

MOV R3,#3
LOP6: MOV R4,#8
MOV R2,#0
LOP5: MOV P3,#00H
MOV DPTR,#TABB
MOV A,R2
MOVC A,@A+DPTR
MOV P1,A
INC R2
LCALL DELAY
DJNZ R4,LOP5
DJNZ R3,LOP6

MOV R3,#3
LOP8: MOV R4,#8
MOV R2,#7
LOP7: MOV P3,#00H
MOV DPTR,#TABB
MOV A,R2
MOVC A,@A+DPTR
MOV P1,A
DEC R2
LCALL DELAY
DJNZ R4,LOP7
DJNZ R3,LOP8
LJMP START

DELAY: MOV R5,#10
D2: MOV R6,#20
D1: MOV R7,#248
DJNZ R7,$
DJNZ R6,D1
DJNZ R5,D2
RET

TABA: DB 0FEH,0FDH,0FBH,0F7H,0EFH,0DFH,0BFH,07FH
TABB: DB 01H,02H,04H,08H,10H,20H,40H,80H
END


6. C语言源程序
#include <AT89X52.H>

unsigned char code taba[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsigned char code tabb[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

void delay(void)
{
unsigned char i,j;

for(i=10;i>0;i--)
for(j=248;j>0;j--);
}

void delay1(void)
{
unsigned char i,j,k;

for(k=10;k>0;k--)
for(i=20;i>0;i--)
for(j=248;j>0;j--);

}

void main(void)
{
unsigned char i,j;

while(1)
{
for(j=0;j<3;j++)  //from left to right 3 time
{
for(i=0;i<8;i++)
{
P3=taba[i];
P1=0xff;
delay1();
}
}

for(j=0;j<3;j++)  //from right to left 3 time
{
for(i=0;i<8;i++)
{
P3=taba[7-i];
P1=0xff;
delay1();
}
}

for(j=0;j<3;j++)  //from top to bottom 3 time
{
for(i=0;i<8;i++)
{
P3=0x00;
P1=tabb[7-i];
delay1();
}
}

for(j=0;j<3;j++)  //from bottom to top 3 time
{
for(i=0;i<8;i++)
{
P3=0x00;
P1=tabb[i];
delay1();
}
}

}
}

2011-12-17 11:21:13 yu_xiaofei 阅读数 7831

使用PROTEUS仿真软件中的液晶显示屏(型号AMPIRE12864)探索点阵液晶的编程方式;该型号液晶屏内部无字库,只能自建字模进行字符显示(使用方法与图形显示方式一致);字模可通过“字模提取”软件提取,省去手工建模

的麻烦。

整体电路图  

功能说明:该电路使用AT89C52作控制器,电路左下方为时钟芯片DS1302;用液晶屏显示当前时间、若干汉字、一幅小图等内容;

电路连线:

1)液晶模块: E=P2^0;  RW=P2^1;  RS=P2^2;  CS2=P2^3;  CS1=P2^4;  RST(复位信号)=5V;  

               数据口D0~D7接单片机P0口;

2)时钟芯片DS1302:  RST = P3^6 ;    CLK =  P1^6 ;    SDA =  P1^7 ;

电路仿真结果如下:

首先分析下该液晶模块内部控制器的工作原理:

管脚功能:

管脚名称

LEVER

管脚功能描述

VSS

0

电源地

VDD

+5.0V

电源电压

V0

-

液晶显示器驱动电压 (在PROTUES仿真软件中可不接)

RS

1/0

RS=0,表示DB7∽DB0为显示数据

RS=1,表示DB7∽DB0为显示指令数据

R/W

1/0

R/W=1,E=1数据被读到DB7∽DB0

R/W=0,E=“1→0”,数据被写到IR或DR

E

1/0

R/W=0,E信号下降沿锁存DB7∽DB0

R/W=1,E=1, DDRAM数据读到DB7∽DB0

DB0~DB7

1/0

数据线

1/0

0:选择芯片(左半屏)信号

1/0

0:选择芯片(右半屏)信号

1/0

复位信号,低电平复位

VOUT

-10V

LCD驱动负电压 (在PROTUES仿真软件中可不接)

12864内部功能器件及相关功能:

1. 指令寄存器(IR)

IR是用于寄存指令码,与指令寄存器寄存指令相对应。当RS =0时,在E信号下降沿的作用下,指令码写入IR。

2.数据寄存器(DR)

DR是用于寄存数据的,与数据寄存器数据相对应。当RS =1时,在下降沿作用下,图形显示数据写入DR,或在E信号高电平作用下由DR读到DB7∽DB0数据总线。DR和DDRAM之间的数据传输是模块内部自动执行的。

3.忙标志:BF

BF标志提供内部工作情况。BF=1表示模块在内部操作,此时模块不接受外部指令和数据。BF=0时,模块为准备状态,随时可接受外部指令和数据。利用STATUS READ指令,可以将BF读到DB7总线,检验模块工作状态。

4.显示控制触发器DFF

此触发器是用于模块屏幕显示开和关的控制。DFF=1为开显示(DISPLAY OFF),DDRAM的内容就显示在屏幕上,DFF=0为关显示(DISPLAY OFF)。DDF的状态是指令DISPLAY ON/OFF和RST信号控制的。

5.XY地址计数器

XY地址计数器是一个9位计数器。高3位是X地址计数器,低6位为Y地址计数器,XY地址计数器实际上是作为DDRAM的地址指针,X地址计数器为DDRAM的页指针,Y地址计数器为DDRAM的Y地址指针。

X地址(页地址,页的概念迟点会解释)计数器是没有记数功能的,只能用指令设置。

Y地址(列地址)计数器具有循环记数功能,各显示数据写入后,Y地址自动加1,Y地址指针从0到63。

6.显示数据RAM(DDRAM)

DDRAM是存储图形显示数据的。数据为1表示选择显示,数据为0表示选择非显示。DDRAM与地址和显示位置的关系见DDRAM地址表。

7.Z地址计数器

Z地址计数器是一个6位计数器,此计数器具备循环记数功能,它是用于显示行扫描同步。当一行扫描完成,此地址计数器自动加1,指向下一行扫描数据,RST复位后Z地址计数器为0。

Z地址计数器可以用指令DISPLAY START LINE预置。因此,显示屏幕的起始行就由此指令控制,即DDRAM的数据从哪一行开始显示在屏幕的第一行。此模块的DDRAM共64行,屏幕可以循环滚动显示64行。

12864LCD的指令系统

    该类液晶显示模块(即KS0108B及其兼容控制驱动器)的指令系统比较简单,总共只有七种。其指令表如表2所示:

指令名称

控制信号

控制代码

R/W

RS

DB7

DB6

DB5

DB4

DB3

DB2

DB1

DB0

显示开关

0

0

0

0

1

1

1

1

1

1/0

显示起始行设置

0

0

1

1

X

X

X

X

X

X

页设置

0

0

1

0

1

1

1

X

X

X

列地址设置

0

0

0

1

X

X

X

X

X

X

读状态

1

0

BUSY

0

ON/OFF

0

0

0

0

写数据

0

1

写数据

读数据

1

1

读数据

1、 显示开/关指令 

R/W RS

DB7 DB6 DB5 DB4 DB3DB2DB1 DB0

0  0

0 0 1 1 1 1 1  1/0

当DB0=1时,LCD显示RAM中的内容;DB0=0时,关闭显示。

2、显示起始行(ROW)设置指令

R/W RS

DB7 DB6 DB5 DB4 DB3DB2DB1 DB0

0  0

1 1显示起始行(0~63)

该指令设置了对应液晶屏最上一行的显示RAM的行号,有规律地改变显示起始行,可以使LCD实现显示滚屏的效果。

3、页(PAGE)设置指令

R/W RS

DB7 DB6 DB5 DB4 DB3DB2DB1 DB0

0  0

1 0 1 1 1页号(0~7)

显示RAM共64行,分8页,每页8行。

4、列地址(Y Address)设置指令

R/W RS

DB7 DB6 DB5 DB4 DB3DB2DB1 DB0

0  0

0 1显示列地址(0~63)

设置了页地址和列地址,就唯一确定了显示RAM中的一个单元,这样MPU就可以

用读、写指令读出该单元中的内容或向该单元写进一个字节数据。

5、读状态指令

R/W RS

DB7 DB6 DB5 DB4 DB3DB2DB1 DB0

1  0

BUSY 0 ON/OFF  0 0 0 0

该指令用来查询液晶显示模块内部控制器的状态,各参量含义如下:

BUSY:  1-内部在工作   0-正常状态

ON/OFF:1-显示关闭     0-显示打开

:  1-正常状态     0- 复位状态

在BUSY和状态时,除读状态指令外,其它指令均不对液晶显示模块产生作用。

在对液晶显示模块操作之前要查询BUSY状态,以确定是否可以对液晶显示模块进行操作。

6、写数据指令

R/W RS

DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

0  1

写数据

7、 读数据指令 

R/W RS

DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

1  1

读显示数据

    读、写数据指令每执行完一次读、写操作,列地址就自动增一。必须注意的是,进行读操作之前,必须有一次空读操作,紧接着再读才会读出所要读的单元中的数据。

 

12864由两个完全相同的左右半屏拼成,两个半屏的显示通过CS1和CS2来选择,如CS1=0、CS2=1时选择左半屏显示,每页占8行(指令0xb8~0xbf分别指定页0~页7地址);

写入液晶的数据在屏上为纵向显示,如在指定位置(页0第0列)显示12H:

0xb8 指定页0

0x40 指定列0

0x12 送入数据,该数据的最高位对应“该页该列”最下端的点(第0行)

下面以“你”字为例,分析其字模(16*16点阵,占两页位置)

从最左边上半部开始

上页字模0x80,0x40,0xF0,0x2C,0x43,0x20,0x98,0x0F,0x0A,0xE8,0x08,0x88,0x28,0x1C,0x08,0x00

下页字模0x00,0x00,0x7F,0x00,0x10,0x0C,0x03,0x21,0x40,0x3F,0x00,0x00,0x03,0x1C,0x08,0x00

2017-02-21 18:48:23 u011910350 阅读数 681

a 单色点阵与双色点阵发光原理

1)单色点阵

单色LED点阵等效图如下:

51单片机之声双色点阵驱动



8X8点阵共需要64个发光二极管组成,且每个发光二极管是放置在行线和列线的交叉点上,当对应的某一列置1电平,某一行置0电平,则相应的二极管就亮;因此要实现一根柱形的亮法,如图上图所示,对应的一列为一根竖柱,或者对应的一行为一根横柱,因此实现柱的亮的方法如下所述:
   一根竖柱:对应的列置1,而行则采用扫描的方法来实现。一根横柱:对应的行置0,而列则采用扫描的方法来实现。

2)双色点阵

双色点阵示意图如下:COL上有两种颜色LED在相应的管脚上,按单色点阵点亮原理置相应的电平即可发出相应的光。

           51单片机之声双色点阵驱动

b硬件

51单片机之声双色点阵驱动

1) 74HC595

51单片机之声双色点阵驱动

HC595 是串行转并行的芯片,可以多级级联,输入需要 3 个端口:

1DSSER)串行数据输入端

2SHSRCLK)串行时钟输入端

3STRCLK)(LATCH)锁存端

写入数据原理,SRCLK 输入时钟信号,为输入数据提供时间基准,跟随时钟信号输入对应的数据信号,输入全部完毕后,控制锁存端,把串行输入的数据锁存到输出端并保持不

变。

c双色点阵控制程序


51单片机之声双色点阵驱动

51单片机之声双色点阵驱动

51单片机之声双色点阵驱动

51单片机之声双色点阵驱动

51单片机之声双色点阵驱动

51单片机之声双色点阵驱动
51单片机之声双色点阵驱动

以黑金动力太阳风MCU-51实验板为例说明,连线如下图:

51单片机之声双色点阵驱动


 

现象如下图:


51单片机之声双色点阵驱动



51单片机之声双色点阵驱动

     总结:本节绍了怎样用51单片机制作电子音乐盒及双色点阵的控制,下节《51单片机之声——LCD12864汉字图形显示及电子日历制作(2)》将带您走进图形化显示世界及万年历的制作,为了帮助初学者尽快地学习与掌握51单片机的常用功能模块,与之配套程序讲解的视频不久将会在网上发布,敬请期待。

    太阳风MCU-51开发板具体介绍可访问:http://item.taobao.com/item.htm?spm=1103*oQM.3-5SusJ.h-2Yh1mq&id=14049701171&

2018-12-30 19:59:24 weixin_43483381 阅读数 5266

使用51单片机实现点阵汉字平滑滚动显示

#说明:采用的芯片是89C51,LED点阵屏的规格是16*16,同时使用了两个74HC595芯片,字模生成软件在文末有网盘链接。

1 连接原理图

在这里插入图片描述
整体的电路连接如上图所示,单片机只需要使用三个IO接口,就可以实现对点阵屏的控制。当然对于不同的单片机而言连线是不同的,但是使用74HC595扩展的原理是相同的,在这里不再对于其IO扩展原理进行探究。

2 实现的功能

在51单片机以及C语言的环境下,实现LED点阵屏幕上汉字的平滑滚动,就像是公交车上显示“前方到站第二医院,下车乘客请提前做好准备”一样。我们最后显示的是“计算机测控技术”几个字,当然显示的汉字内容是自定义的。同时,设置一个按钮能够让平滑滚动的汉字可以随时停下来。
在这里插入图片描述
这里有两点细节需要注意一下:
1、汉字循环到最后一个时,要继续滚动出第一个汉字,而不是跳变到开头重新循环。
2、汉字滚动的时候按下按钮停止,滚动停止的时候按下按钮继续滚动,使用同一个按钮。

3 C语言程序实现

3.1 定义变量

在这里我们定义芯片P3.4、P3.5、P3.6 三个接口为输出IO接口,P2.7为接开关控制的IO接口。同时定义一个大数组储存所有汉字对应的取模16进制码,一个小数组用于表示现在屏幕上所需显示的汉字。

#include <reg51.h>
#include <intrins.h>

typedef unsigned int u16;	//常规无符号字符串和整数定义		  
typedef unsigned char u8;
//将595的三个内置接口赋给新的名字
sbit SRCLK = P3 ^ 6;	// 数据输入口(串)	
sbit RCLK = P3 ^ 5;	// 移位寄存器时钟	
sbit SER = P3 ^ 4;	// 存储寄存器时钟
sbit stopscreen = P2^7;	 //暂停与开始开关定义引脚

/*定义一个数组存储所有需要平滑滚动的文字的16进制码,由取模软件自动生成,
每个字由32个16进制数字组合而成,现在数组中存储的是“计算机测控技术”*/
u8 code word[] = {
/*--  文字:  计  --*/
	0x00, 0x02, 0x04, 0x02, 0x08, 0x02, 0x08, 0x02, 0x00, 0x02, 0x00, 0x02, 0xEF, 0x7F, 0x08, 0x02,
	0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x28, 0x02, 0x18, 0x02, 0x08, 0x02, 0x00, 0x02,

	/*--  文字:  算  --*/
	0x04, 0x02, 0x7C, 0x7E, 0x12, 0x09, 0x01, 0x00, 0xFC, 0x1F, 0x04, 0x10, 0xFC, 0x1F, 0x04, 0x10,
	0xFC, 0x1F, 0x04, 0x10, 0xFC, 0x1F, 0x10, 0x04, 0xFF, 0x7F, 0x10, 0x04, 0x08, 0x04, 0x04, 0x04,

	/*--  文字:  机  --*/
	0x08, 0x00, 0x88, 0x0F, 0x88, 0x08, 0x88, 0x08, 0xBF, 0x08, 0x88, 0x08, 0x8C, 0x08, 0x9C, 0x08,
	0xAA, 0x08, 0xAA, 0x08, 0x89, 0x08, 0x88, 0x48, 0x88, 0x48, 0x48, 0x48, 0x48, 0x70, 0x28, 0x00,

	/*--  文字:  测  --*/
	0x00, 0x20, 0xE4, 0x23, 0x28, 0x22, 0x28, 0x2A, 0xA1, 0x2A, 0xA2, 0x2A, 0xA2, 0x2A, 0xA8, 0x2A,
	0xA8, 0x2A, 0xA4, 0x2A, 0xA7, 0x2A, 0x84, 0x20, 0x44, 0x21, 0x44, 0x22, 0x24, 0x28, 0x10, 0x10,

	/*--  文字:  控  --*/
	0x08, 0x02, 0x08, 0x04, 0x08, 0x04, 0xC8, 0x7F, 0x5F, 0x40, 0x28, 0x29, 0x88, 0x10, 0x58, 0x20,
	0x0C, 0x00, 0x8B, 0x3F, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0xEA, 0x7F, 0x04, 0x00,

	/*--  文字:  技  --*/
	0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0xC8, 0x7F, 0x3F, 0x04, 0x08, 0x04, 0x08, 0x04, 0xA8, 0x3F,
	0x18, 0x21, 0x0C, 0x11, 0x0B, 0x12, 0x08, 0x0A, 0x08, 0x04, 0x08, 0x0A, 0x8A, 0x11, 0x64, 0x60,

	/*--  文字:  术  --*/
	0x80, 0x00, 0x80, 0x04, 0x80, 0x08, 0x80, 0x08, 0xFE, 0x3F, 0xC0, 0x01, 0xA0, 0x02, 0xA0, 0x02,
	0x90, 0x04, 0x88, 0x08, 0x84, 0x10, 0x82, 0x20, 0x81, 0x40, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00};
//下面一个用于存储每一时刻点阵屏显示内容的数字,随着时间会不断重新赋值与变化
u8 now[32] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

3.2 点阵显示函数

由于使用595进行了接口扩展,首先编写行显示函数LED_line,接着再编写汉字显示函数LED_array,>>和<<这两个符号是二进制移位符号。

void delay(u16 i)	   //延时函数,很普通
{
	while (i--);
}
//行显示函数: LED_line (字节1 1 ,字节2 2 ,行号)
void LED_line(u8 ledata1, u8 ledata2, u8 line_num)
{
	u8 b_num, i;
	u8 REG595[4]; 		 // 发送到595的四个字节。
	REG595[0] = ledata2; REG595[1] = ledata1;
	if (line_num<8) {
		REG595[2] = 0;
		REG595[3] = 0x01 << line_num;
	}
	else {
		REG595[2] = 0x01 << (line_num - 8);
		REG595[3] = 0;
	}
	SRCLK = 1; // 移位准备
	RCLK = 1; 	//输出准备
	for (b_num = 0; b_num<4; b_num++) {   // 向595发送四个字节
		for (i = 0; i<8; i++) { 	   //发送8位数
			SER = REG595[b_num] >> 7; 	 //从最高位开始发送
			REG595[b_num] <<= 1;
			SRCLK = 0;
			SRCLK = 1; 	  //移位寄存器时序,低电平准备,高电平有效
		}
	}
	RCLK = 0; 	// 存储寄存器时序,低电平准备,高电平有效,四个字节同时发出
	RCLK = 1;
}

void LED_array(u8 word[], u16 t_delay)	//汉字显示函数
{
	u8 i;
	while (t_delay--) {
		for (i = 0; i<16; i++) { // 逐行显示
			LED_line(~word[i * 2], ~word[i * 2 + 1], i);
		}
	}
}

3.3 平滑滚动

通过上面的内容,我们只要调用LED_array函数,正确传参后就可以在LED点阵屏上显示我们想要显示的内容了。实现平滑滚动才是本文的关键,主函数的算法流程图如下所示:
在这里插入图片描述
总的来说,就是使用小数组(now)在大数组(word)中一步步移动的方法,在算法与数据结构里,我们往往把这种方法叫做滑动窗口法。在汉字取模软件中生成的16进制数,每两个一组代表LED点阵上的一行灯的亮灭。这也不难理解,因为一行是16个LED灯,一个两位16进制数刚好可以表示8个2进制数,所以两个两位16进制数控制一行。因此,我们滑动窗口每次移动2个两位16进制数。

void main()	   //主函数
{
	u16 i, j;	
		for(j=0;;j++){	   //在这里不使用while循环是因为while循环显示输出不稳定
			//每次赋给now的值都后移两位,显示出来就是点阵一行行地变化
			for (i=0;i<32;i++){			//对now中32个位置,每个位置都赋值
				/*将需要实时显示的内容放到实时数组now中去,同时使用对数组最大数224取余实现循环平滑滚动*/
				now[i] = word[(i+(2*j))%224];	
			}
			LED_array(now, 10);		//调用汉字显示函数,依次显示now中内容
			delay(300);	  //延迟后进行下一循环
			if(stopscreen==0){		//按键防抖设计
				delay(50);
				if(stopscreen==0){			
					while(1){		//按第一下开关停止平滑滚动
						LED_array(now, 10);
						if(stopscreen==0){	 	//按键防抖设计
							delay(50);
							if(stopscreen==0){
								break;	  //按第二下开关继续平滑滚动
							}
						
						}
					}
				}		
				
			}
		}			
}

4 总结

清楚了LED点阵屏显示的原理,我们可以设计LED点阵屏的多种显示方式,甚至可以做出动画片、游戏等。
字模生成软件百度云:链接:https://pan.baidu.com/s/1OwK_L_aDjWas5LF_MuULmQ
提取码:idov

2018-08-30 15:51:20 qq_41639829 阅读数 18076

代码及仿真原理图下载地址:

https://download.csdn.net/download/qq_41639829/10641349

一、效果展示及连线方式

 

注:制作动图时效果显示不好

 

二、所用材料

1、Proteus中8x8点阵

 

8x8点阵主要分为以下两种:

 

第一种为行共阴,第二种为行共阳

 

详细介绍可以参考这位大神说的:

http://www.51hei.com/bbs/dpj-31998-1.html

在Proteus中我选择的是绿色的8x8的点阵,其类型是行共阴

 

2、74hc595

详细介绍见我上一篇文章

https://blog.csdn.net/qq_41639829/article/details/82151706

3、stc89c52

可以选择其他单片机,我用的这个

 

三、原理介绍

1、点阵的 “静态显示”

这里所说的静态显示就是不滚动画面的意思,比如你用点阵只显示一个数字,或者只显示一个心形。

首先明白点阵显示的原理就相当于发光二极管一样,只不过是64个发光二极管罢了。

 

假如你想让第一行全亮,应该怎么做?

很简单,因为是行共阴,所以第一行首先接负极,其他行都接正极或者不接,然后每一列都接正极,这样就可以使第一行全亮。如果第二列不接正极,则第一行的第二列的灯就不会亮,就只亮七个灯。如果第二行这时接地,则第二行也会和第一行一样亮同样的七个灯(不懂得话看看上边的原理图)。

 

假如你想显示心形应该怎么办?

如果我们想显示上面的这个图形,可知,第一行和第八行是不需要接地的,其他的需要接地。

但是看列,每一列都能用到。如果按照上面说的接线就是下图这个样子(不懂看原理图)。

所以不能采取这种方法,我们采取“扫描”的方式,即一行一行的亮,也就是先第一行接地(其他行不接地),然后如果按照心形的图,就是所有都列都不接正极。然后接着第二行接地(其他行不接地),由心形图可知,需要第二、三、六、七列亮,则这几列接正。再往下是第三行,第三行再接地,然后第一、四、五、八列接正,依次往下。循环一圈后接着再第一行然后一直循环即可。

 

或许大家会疑惑,假如第二行接地,只有第二行的几个灯亮,那么其他行都是暗的,怎么会看到心形呢,其实这个每一行的切换时间需要很短,几毫秒左右,利用人眼的视觉暂留效应(不懂得可以查一下)来显示,正所谓 ”眼见不一定为实“ 啊。

2、点阵的滚动显示

本实验应为行扫描即行选择端口,所以上下滚动显示,当然也可以左右,大家可以自己探索一下。

滚动显示和静态类似,只不过差别是,在一次循环后回到第一行时,静态情况下是显示第一行应有的列,而滚动是显示上次循环第二行对应的列,第二行就显示第三行对应的列,依次往下,这样就相当于图形往上移了一个格。然后每次循环都说是这样,这样就滚动显示了。不懂可以再看代码。

 

3、74hc595的原理

详细原理见我上一篇文章

https://blog.csdn.net/qq_41639829/article/details/82151706

 

四、取模软件

软件来源于网络(使用方法百度一下):

链接:https://pan.baidu.com/s/1fRfJ_QPTqsN8LM9Npya_lQ 密码:avhl

五、Proteus连线方式

如下图:

六、代码展示

#include<reg52.h>
#include<intrins.h>

//intrins.h函数,一般出现在C51单片机编程中,一般程序中需要使用到空指令_nop_();字符循环移位指令_crol_等时使用
//OE	第13脚	输出有效(低电平)
//MR	第10脚	主复位(低电平)

typedef unsigned char uchar;
typedef unsigned int uint;


/**********管脚说明********************/
#define P P1   //define 不用加;

sbit SER = P3^4;    //p3.4串行数据输入   DS
sbit SCK = P3^6;    //串行输入时钟,上升沿有效    SHCP	第11脚	数据输入时钟线
sbit RCK = P3^5;    //串行寄存器时钟,上升沿有效  STCP	第12脚	输出存储器锁存时钟线

/***********************************/

/**********函数声明********************/
void SendTo595(uchar byteData);
/***********************************/

/**********全局参数声明********************/
char shu=0xFE;
/***********************************/


void delay(unsigned int n)//延时函数
{
    unsigned int i=0,j=0;
    for(i=0;i<n;i++)
        for(j=0;j<123;j++);
}

void hang()//行扫描
{
	P=shu;
	shu=_crol_(shu,1);
}

char a[32]={0x3E,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,
						0x00,0x66,0x99,0x81,0x42,0x24,0x18,0x00,
						0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,
					  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
void main()
{
  int i,b=0;
	while(1)
	{
			int num=12;
			while(num--)
			{
				for(i=0;i<8;i++)
				{
					hang();     //先位选再段选
					SendTo595(a[i+b]);			
					delay(3);
				}
				//P=0xFF;
				//SendTo595(0x00);
			}
		  b++;
			if(b>=24)b=0;
			//P=0xFF;
	 }	
}



//发送一个字节数据给595再并行输出
void SendTo595(uchar Data)
{
   int j=0;
   for(j;j<8;j++)
   {
		    SCK = 0; 
        SER=0x80&Data;//&为按位运算符,即全1为1,有0为0,上式也就是 (1000 0000)&(1111 1111)=1000 0000,若高位为1则是1高位为0则这个式子为0 
        Data=_crol_(Data,1); //左移一位 将高位补给低位,如果二进制数为01010101 那么_crol_(1) 为10101010
        SCK = 1;          //上升沿让串行输入时钟变成高电平 并延时两个时钟周期
        _nop_();

   }  
   
   /*位移寄存器完毕,转移到存储寄存器*/
	 
	
	 RCK = 0;
   RCK = 1;         //上升沿,存储寄存器变为高电平 延迟两个时钟周期
   _nop_();
	 RCK = 0;

}