【Proteus仿真】51单片机+74HC595驱动8X8点阵位移显示

【Proteus仿真】51单片机+74HC595驱动8X8点阵位移显示


  • 📺Proteus仿真
    在这里插入图片描述

🛠取模软件和取模方式

  • 图形取模和显示:
1
2
0x1C,0x38,0x70,0xE0,0xE0,0x70,0x38,0x1C,

在这里插入图片描述

  • 说明一点:实际显示的效果是逆时针旋转了90°的效果。如下图
    在这里插入图片描述

📝驱动程序

  • main.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#ifndef \_\_MAIN\_H\_\_
#define \_\_MAIN\_H\_\_

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

#define uchar unsigned char //类型转义
#define uint unsigned int //类型转义

/\*重要:
第一片的74HC595的引脚14要接到第二片的74HC595的引脚9, 千万不能搞反
第一片的74HC595的引脚12接第二片的74HC595的引脚12
第一片的74HC595的引脚11接第二片的74HC595的引脚11

其它引脚接法, 请看电路图
\*/

sbit LEDARRAY_DI = P3^4; //第二片74HC595的引脚14
sbit LEDARRAY_LAT = P3^5; //第二片74HC595的引脚12
sbit LEDARRAY_CLK = P3^6; //第二片74HC595的引脚11


//函数或者变量声明
extern void Delay\_ms(uint n);
extern void Send\_Data(uchar dat);
extern void Send\_Byte(uchar dat);

#endif

  • main.c文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
接线方式请看main.h说明
二片74HC595 + 一个8\*8点阵(1088AS共阴)
实现文字静态显示+移动显示(左移/右移/上移/下移)
代码精简,方便理解
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
#include "main.h"

//定义变量
uchar temp = 0xfe;

/\*取模说明:
菜单选项:
"点阵格式" : 根据你的点阵是共阴还是共阳, 我的是共阴, 所以选择的是阴码
"取模走向" : 根据你的需求, 选择逆向或顺向, 我这里选择的是逆向
"取模方式" : 请看下面示例说明, 根据移动方向选择
"每行显示数据" : 点阵=8, 索引=8
"液晶面板仿真" : 像素大小=8
"输出数制" : 选择"十六进制数"
"输出选项" : 选择"输出精简格式"和"输出紧凑格式"
"自定义格式" : 选择"C51格式", 其它默认

主界面选项:
字体: 幼圆
字宽: 8 字高: 8
点阵宽: 8 点阵高: 8
\*/

//动态显示数组
uchar code Display_word1[64] = { //数组个数(这里的40代表有40个十六进制,因为是8\*8点阵,所以每个字有8个十六进制)
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //空白(前面放一个空白屏,实现移动出字效果)
//0x10,0x38,0x54,0x10,0x10,0x10,0x10,0x10, //箭头

//逆向+逐列式或列行式 (左移/右移)
0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08, //"一",0
0x80,0x80,0x80,0xFE,0x90,0x90,0x80,0x80, //"上",1
0x00,0x40,0x44,0x44,0x44,0x44,0x40,0x00, //"二",2
0x00,0x02,0x02,0xFE,0x0A,0x12,0x02,0x00, //"下",3
0x18,0x3C,0x7E,0xE7,0xC3,0x81,0x0,0x0, // <<
0x1C,0x38,0x70,0xE0,0xE0,0x70,0x38,0x1C, // 向下
//逆向+行列式或逐行式 (上移/下移)
/\*0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00, //"一",0
0x00,0x08,0x08,0x08,0x38,0x08,0x08,0xFF, //"上",1
0x00,0x00,0x3C,0x00,0x00,0x00,0x7E,0x00, //"二",2
0x00,0x7E,0x08,0x18,0x28,0x08,0x08,0x08, //"下",3
\*/

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //空白(最后放一个空白屏,以免出现乱码)
};

//静态显示数组(第1个参数为几个字,第2个参数为每字多少字节)
uchar Display_word2[3][8] = {
0x0C,0x1E,0x3E,0x7C,0x7C,0x3E,0x1E,0x0C, //心
0x10,0x38,0x54,0x10,0x10,0x10,0x10,0x10, //箭头
0x0C,0x1E,0x3E,0x7C,0x7C,0x3E,0x1E,0x0C, //心
};

//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
//主函数
//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
void main()
{
uint i;
uchar j,k;
while(1)
{
///
//静态显示的代码区域

for(j = 0 ; j < 3 ; j++) { //共需显示3个字
for(i = 0 ; i < 1000 ; i++) { //静态显示时间
temp = 0x7f;
for(k = 0 ; k < 8 ; k++) { //显示1-8列(8为显示8列)如果改成4则有4列显示,另4列黑屏
Send\_Data(Display_word2[j][k]);
}
}
}

///
//移动方式(想要不同的移动方式,就按以下说明修改两处)

for(j = 0 ; j < 40 ; j++) //左移(逐列式)/上移(逐行式1)
//for(j = 39 ; j-1 > 0 ; j--) //右移(逐列式)/下移(逐行式2)

for(j = 0 ; j < 56 ; j++) { //要显示的字数(每个字8位,这里是显示一屏空白+6个字,所以是8+6\*8=56)
for(i = 0 ; i < 50 ; i++) { //控制移动的速度(数字越小移动速度越快,越大越慢)
temp = 0x7f;

//移动方式(想要不同的移动方式,就按以下说明修改)
for(k = 0 ; k < 8 ; k++) //左移(逐列式)/右移(逐列式1)
//for(k = 8 ; k-1 > 0 ; k--) //上移(逐行式)/下移(逐行式2)

Send\_Data(Display_word1[j+k]); //(每个字取8次数组, 不要修改)
}
}
}
}


//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
//发送数据(不需要修改)
//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
void Send\_Data(uchar dat)
{
Send\_Byte(temp); //列选择
Send\_Byte(dat); //数据
LEDARRAY_LAT = 1; //锁存数据
\_nop\_();
LEDARRAY_LAT = 0;
\_nop\_();
temp = (temp>>1)|0x80;
}

//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
//发送一个字节数据(不需要修改)
//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
void Send\_Byte(uchar dat)
{
uchar i;
LEDARRAY_CLK = 0;
\_nop\_();
LEDARRAY_LAT = 0;
\_nop\_();

for( i = 0 ; i < 8 ; i++ )
{
if( dat&0x01 ) {
LEDARRAY_DI = 1;
} else {
LEDARRAY_DI = 0;
}
LEDARRAY_CLK = 1; //上升沿发送数据
LEDARRAY_CLK = 0;
dat >>= 1;
}
}

📑代码使用说明

  • 静态显示的代码
1
2
3
4
5
6
7
8
9
10
11
12
///
//静态显示的代码区域

for(j = 0 ; j < 3 ; j++) { //共需显示3个字
for(i = 0 ; i < 1000 ; i++) { //静态显示时间
temp = 0x7f;
for(k = 0 ; k < 8 ; k++) { //显示1-8列(8为显示8列)如果改成4则有4列显示,另4列黑屏
Send\_Data(Display_word2[j][k]);
}
}
}

  • 动态显示的代码

启用或禁用对应项对应的代码即可实现移动方式的改变。一种是向左变移动显示,另一种就是向右移动显示方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/// 
//移动方式(想要不同的移动方式,就按以下说明修改两处)

for(j = 0 ; j < 40 ; j++) //左移(逐列式)/上移(逐行式1)
//for(j = 39 ; j-1 > 0 ; j--) //右移(逐列式)/下移(逐行式2)

for(j = 0 ; j < 56 ; j++) { //要显示的字数(每个字8位,这里是显示一屏空白+6个字,所以是8+6\*8=56)
for(i = 0 ; i < 50 ; i++) { //控制移动的速度(数字越小移动速度越快,越大越慢)
temp = 0x7f;

//移动方式(想要不同的移动方式,就按以下说明修改)
for(k = 0 ; k < 8 ; k++) //左移(逐列式)/右移(逐列式1)
//for(k = 8 ; k-1 > 0 ; k--) //上移(逐行式)/下移(逐行式2)

Send\_Data(Display_word1[j+k]); //(每个字取8次数组, 不要修改)
}
}

📚程序代码和仿真资源

1
2
3
链接:https://pan.baidu.com/s/1ByAdUyOa\_1vueG6d5l\_kLQ 
提取码:e23s

示例二

  • 🎬效果演示:

在这里插入图片描述

  • 📝驱动代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/\* Main.c file generated by New Project wizard
\*
\* Created: 周六 2月 25 2023
\* Processor: AT89C52
\* Compiler: Keil for 8051
\*/

//#include <stdio.h>
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int

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



typedef unsigned int u16;
typedef unsigned char u8;


sbit RCL=P2^1;
sbit SCL=P2^0;
sbit SER=P2^2;

int offset=0;
unsigned char Animation[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x18,0x3C,0x7E,0xE7,0xC3,0x81,0x00,0x00,
0x38,0x44,0x82,0xC1,0xC1,0x82,0x44,0x38,
0x00,0x00,0x81,0xC3,0xE7,0x7E,0x3C,0x18,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};//

void Delay(unsigned int Xms) //11.0592Mhz 1ms
{
unsigned char i, j;
while(Xms--)
{
\_nop\_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
/\*
\*函数名: \_74HC595Write(unsigned char byte)
\*函数功能:向74HC595串行输入一个字节的数据
\*输入: byte :一个字节数据
\*输出: 无
\*/
void \_74HC595Write(unsigned char byte)
{
int i=0;
for(i=0;i<8;i++)
{
SER=byte&(0x80>>i);
SCL=1;
SCL=0;
}
RCL=1;
RCL=0;
}
/\*
\*函数名: \_74HC595\_Init()
\*函数功能:初始化74HC595的SCL、RCL
\*输入: 无
\*输出: 无
\*/
void \_74HC595\_Init()
{
SCL=0;
RCL=0;
}

/\*
\*函数名: MatrixLED(unsigned char COL,unsigned char byte)
\*函数功能: 控制点阵屏某一列的显示
\*输入: COL:列 范围0~7; byte:要显示数据的二进制形式(8位)
\*输出: 无
\*/
void MatrixLED(unsigned char COL,unsigned char byte)
{
\_74HC595Write(byte);
P0=~(0x80>>COL);
Delay(1);
P0=0xff;//消影
}
void Timer0\_Init()//定时器0,工作方式1
{
TMOD=0x01;
TH0=0xfc;//1ms
TL0=0x18;
EA=1;
ET0=1;
TR0=1;
}
//定时100ms中断
void Timer0\_ISR() interrupt 1
{
static int count=0;
count++;
TH0=0xfc;
TL0=0x18;
if(count==100)//每100ms,offset加一,画面移动左一下
{
count=0;
offset++;
if(offset >32)
{
offset=0;
}
}
}

int main()
{
int i=0;
\_74HC595\_Init();
Timer0\_Init();//T0初始化
while(1)
{
for(i=0;i<8;i++)
{
MatrixLED(i,Animation[i+offset]);
}
}
}

📚基于VSM Proteus文件资源

1
2
3
4
复制这段内容后打开百度网盘手机App,操作更方便哦
链接: https://pan.baidu.com/s/1vdJNS7Tq-zyivL2bEDk\_dQ
提取码: qm9s