一、实验项目:
基于51单片机的汉字显示系统设计
二、实验目的:
本系统设计的目的是使学生掌握单片机应用系统的设计方法。深刻理解单片机应用系统的开发的过程。具体要求用单片机的控制8*8的点阵屏进行汉字显示。请在Proteus中设计出仿真硬件电路,在keil uvision中设计出源程序,然后用Proteus进行整体系统仿真运行。
三、实验原理:
在这次的实验中,利用单片机AT89C51控制8*8点阵屏进行汉字显示。其中点阵屏由64个LED灯组成,每个LED灯可以亮或灭,通过控制每个LED灯的亮灭状态,可以显示出各种图形和字符。
同时,为了控制点阵屏的显示,需要使用到74LS245移位寄存器。74LS245寄存器可以将数据从串行输入转换为并行输出,通过向寄存器输入数据,可以实现对点阵屏每个LED灯的控制。
在具体显示的时候,我们将需要显示的字符存储在一个字符集中,此字符集为二进制代码,并分别控制8行。利用单片机来循环显示字符集中的每个字符,在每个字符的每一行上控制点阵屏LED灯的亮灭状态。
使用74LS245移位寄存器控制点阵屏显示,将需要显示的数据写入寄存器,然后将寄存器输出到点阵屏,即可控制点阵屏的显示。应该注意的是,在进行显示的时候,利用上面的字符来进行显示,每次操作只能控制点阵屏的一行,我们在控制8行的时候,延时一定时间,给一定的视觉缓冲效果,达到显示字符的效果,然后清除屏幕,进入下一个字符的显示。
四、硬件电路图:
五、C语言代码:
#include <REGX51.H>
typedef unsigned char u8; //定义无符号8位字符型变量u8
xdata u8 chars[36][8]={ //定义一个8*8的字符矩阵,其中每个元素是8位二进制数,表示一个点阵字符
0xE3,0xC9,0x9C,0x9C,0x80,0x9C,0x9C,0xFF,//0-A
0x81,0x9C,0x9C,0x81,0x9C,0x9C,0x81,0xFF,//1-B
0xE1,0xCC,0x9F,0x9F,0x9F,0xCC,0xE1,0xFF,//2-C
0x83,0x99,0x9C,0x9C,0x9C,0x99,0x83,0xFF,//3-D
0xC0,0xCF,0xCF,0xC1,0xCF,0xCF,0xC0,0xFF,//4-E
0x80,0x9F,0x9F,0x81,0x9F,0x9F,0x9F,0xFF,//5-F
0xE0,0xCF,0x9F,0x98,0x9C,0xCC,0xE0,0xFF,//6-G
0x9C,0x9C,0x9C,0x80,0x9C,0x9C,0x9C,0xFF,//7-H
0xC0,0xF3,0xF3,0xF3,0xF3,0xF3,0xC0,0xFF,//8-I
0xFC,0xFC,0xFC,0xFC,0xFC,0x9C,0xC1,0xFF,//9-J
0x9C,0x99,0x93,0x87,0x83,0x91,0x98,0xFF,//10-K
0xCF,0xCF,0xCF,0xCF,0xCF,0xCF,0xC0,0xFF,//11-L
0x9C,0x88,0x80,0x80,0x94,0x9C,0x9C,0xFF,//12-M
0x9C,0x8C,0x84,0x80,0x90,0x98,0x9C,0xFF,//13-N
0xC1,0x9C,0x9C,0x9C,0x9C,0x9C,0xC1,0xFF,//14-O
0x81,0x9C,0x9C,0x9C,0x81,0x9F,0x9F,0xFF,//15-P
0xC1,0x9C,0x9C,0x9C,0x90,0x99,0xC2,0xFF,//16-Q
0x81,0x9C,0x9C,0x98,0x83,0x91,0x98,0xFF,//17-R
0xC3,0x99,0x9F,0xC1,0xFC,0x9C,0xC1,0xFF,//18-S
0xC0,0xF3,0xF3,0xF3,0xF3,0xF3,0xF3,0xFF,//19-T
0x9C,0x9C,0x9C,0x9C,0x9C,0x9C,0xC1,0xFF,//20-U
0x9C,0x9C,0x9C,0x88,0xC1,0xE3,0xF7,0xFF,//21-V
0x9C,0x9C,0x94,0x80,0x80,0x88,0x9C,0xFF,//22-W
0x9C,0x88,0xC1,0xE3,0xC1,0x88,0x9C,0xFF,//23-X
0xCC,0xCC,0xCC,0xE1,0xF3,0xF3,0xF3,0xFF,//24-Y
0x80,0xF8,0xF1,0xE3,0xC7,0x8F,0x80,0xFF,//25-Z
0xE3,0xD9,0x9C,0x9C,0x9C,0xCC,0xE1,0xFF,//26-0
0xF3,0xE3,0xF3,0xF3,0xF3,0xF3,0xC0,0xFF,//27-1
0xC1,0x9C,0xF8,0xE1,0xC3,0x8F,0x80,0xFF,//28-2
0xC0,0xF9,0xF3,0xE1,0xFC,0x9C,0xC1,0xFF,//29-3
0xF9,0xE1,0xC9,0x99,0x80,0xF9,0xF9,0xFF,//30-4
0x81,0x9F,0x81,0xFC,0xFC,0x9C,0xC1,0xFF,//31-5
0xE1,0xCF,0x9F,0x81,0x9C,0x9C,0xC1,0xFF,//32-6
0x80,0x9C,0xF9,0xF3,0xE7,0xE7,0xE7,0xFF,//33-7
0xC3,0x9D,0x8D,0xC3,0xB0,0xBC,0xC1,0xFF,//34-8
0xC1,0x9C,0x9C,0xC0,0xFC,0xF9,0xC3,0xFF,//35-9 };
u8 x[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //从00000001到10000000,用于位选控制信号
void delay_ms(u8 n) //延时函数
{
u8 i,j;
for(j=n;j>0;j--)
for(i=112;i>0;i--);
}
void display(u8 n)
{
u8 i,t=100; //定义计数变量i和t,t表示每个字符显示的次数
while(t--)
{
for(i=0;i<8;i++) //循环8次,控制点阵屏的每一列
{
P3=0;//先将位选控制信号清零
P0=chars[n][i];//将第n个字符的第i列数据写入P0口
P3=x[i]; //将第i个位选控制信号写入P3口
delay_ms(1); //延时1ms,控制显示时间
}
}
}
void main(void)
{
u8 i;
while(1) //循环进行字符显示
{
for(i=0;i<35;i++) //循环显示字符集中的每个字符
{
display(i); //调用显示函数,显示第i个字符
}
}
}
六:汇编代码:
ORG 0000H ;设定程序的起始地址为0000H
LJMP START ; 无条件跳转到 START 标签处
ORG 0030H
START:
MOV R5,#26 ; 将26存储到 R5 寄存器中,用于字母表循环计数
MOV R1,#0 ; 将0存储到 R1 寄存器中,用于字母表循环计数
MOV DPTR,#TABLE1 ; 将TABLE1字母表的地址存储到 DPTR 中,用于数据指针寻址
LOOP1:
LCALL DISPLAY ; 调用 DISPLAY 子程序
;显示下一个数准备
MOV A,R1 ; 将 R1 寄存器的值存储到累加器 A 中
ADD A,#8 ; 将累加器 A 的值加上 8
MOV R1,A ; 将累加器 A 的值存储回 R1 寄存器中
DJNZ R5,LOOP1 ; R5 寄存器值减 1,如果不为零则跳转到 LOOP1 标签处
MOV R5,#10 ; 将 10 数字表大小存储到 R5 寄存器中,用于循环计数
MOV R1,#0
MOV DPTR,#TABLE2 ; 将TABLE2数字表的地址存储到 DPTR 中,用于数据指针寻址
LOOP2:
LCALL DISPLAY ; 调用 DISPLAY 子程序
MOV A,R1 ;与上面的操作相同
ADD A,#8
MOV R1,A
DJNZ R5,LOOP2
SJMP START
DISPLAY:
MOV R4,#20 ;控制P0字符 P3地址 口输出
LOOP3:
MOV A,R1 ;刚开始,需要进行传值,将 R1 寄存器的字符值0存储到累加器 A 中
MOV R2,A ; 将累加器 A 的值存储到 R2 寄存器中
MOV R3,#8 ;8送入R3
MOV R7,#01H ; 将 01H 存储到 R7 寄存器中,用于控制 P3.0 端口输出
LOOP4: ;一个码对应一个地址,8个码一个字符
MOV A,R2 ; 将 R2 寄存器的值存储到累加器 A 中
MOVC A,@A+DPTR ; 间接寻址取出表中的字符
MOV P3,#00H ; 将 00H 存储到 P3 端口中,地址值
MOV P0,A ; 将累加器 A 的值存储到 P0 端口中
MOV P3,R7 ; 将 R7 寄存器的值存储到 P3 端口中,使 P3.0 端口输出
MOV A,R7 ; 将 R7 寄存器的值存储到累加器 A 中
RL A ;左移1
MOV R7,A ; 将左移 A 的值存储回 R7 寄存器中
INC R2 ;加 1,下一个表的码
LCALL DELAY_1MS ; 调用延迟子程序
DJNZ R3,LOOP4 ; R3 寄存器值减 1,如果不为零则跳转到 LOOP4标签处
DJNZ R4,LOOP3 ;短暂停留
RET ; 子程序返回
DELAY_1MS: ;延时1ms程序,采用堆栈的方法
PUSH 30H
PUSH 31H
MOV 30H,#2
MOV 31H,#234
NEXT:
DJNZ 31H,NEXT ;出栈,程序结束
DJNZ 30H,NEXT
POP 31H
POP 30H
RET
TABLE1: ;字母表
DB 0E3H,0C9H,09CH,09CH,080H,09CH,09CH,0FFH ;0-A
DB 081H,09CH,09CH,081H,09CH,09CH,081H,0FFH ;1-B
DB 0E1H,0CCH,09FH,09FH,09FH,0CCH,0E1H,0FFH ;2-C
DB 083H,099H,09CH,09CH,09CH,099H,083H,0FFH ;3-D
DB 0C0H,0CFH,0CFH,0C1H,0CFH,0CFH,0C0H,0FFH ;4-E
DB 080H,09FH,09FH,081H,09FH,09FH,09FH,0FFH ;5-F
DB 0E0H,0CFH,09FH,098H,09CH,0CCH,0E0H,0FFH ;6-G
DB 09CH,09CH,09CH,080H,09CH,09CH,09CH,0FFH ;7-H
DB 0C0H,0F3H,0F3H,0F3H,0F3H,0F3H,0C0H,0FFH ;8-I
DB 0FCH,0FCH,0FCH,0FCH,0FCH,09CH,0C1H,0FFH ;9-J
DB 09CH,099H,093H,087H,083H,091H,098H,0FFH ;10-K
DB 0CFH,0CFH,0CFH,0CFH,0CFH,0CFH,0C0H,0FFH ;11-L
DB 09CH,088H,080H,080H,094H,09CH,09CH,0FFH ;12-M
DB 09CH,08CH,084H,080H,090H,098H,09CH,0FFH ;13-N
DB 0C1H,09CH,09CH,09CH,09CH,09CH,0C1H,0FFH ;14-O
DB 081H,09CH,09CH,09CH,081H,09FH,09FH,0FFH ;15-P
DB 0C1H,09CH,09CH,09CH,090H,099H,0C2H,0FFH ;16-Q
DB 081H,09CH,09CH,098H,083H,091H,098H,0FFH ;17-R
DB 0C3H,099H,09FH,0C1H,0FCH,09CH,0C1H,0FFH ;18-S
DB 0C0H,0F3H,0F3H,0F3H,0F3H,0F3H,0F3H,0FFH ;19-T
DB 09CH,09CH,09CH,09CH,09CH,09CH,0C1H,0FFH ;20-U
DB 09CH,09CH,09CH,088H,0C1H,0E3H,0F7H,0FFH ;21-V
DB 09CH,09CH,094H,080H,080H,088H,09CH,0FFH ;22-W
DB 09CH,088H,0C1H,0E3H,0C1H,088H,09CH,0FFH ;23-X
DB 0CCH,0CCH,0CCH,0E1H,0F3H,0F3H,0F3H,0FFH ;24-Y
DB 080H,0F8H,0F1H,0E3H,0C7H,08FH,080H,0FFH ;25-Z
TABLE2: ;数字表
DB 0E3H,0D9H,09CH,09CH,09CH,0CCH,0E1H,0FFH ;26-0
DB 0F3H,0E3H,0F3H,0F3H,0F3H,0F3H,0C0H,0FFH ;27-1
DB 0C1H,09CH,0F8H,0E1H,0C3H,08FH,080H,0FFH ;28-2
DB 0C0H,0F9H,0F3H,0E1H,0FCH,09CH,0C1H,0FFH ;29-3
DB 0F9H,0E1H,0C9H,099H,080H,0F9H,0F9H,0FFH ;30-4
DB 081H,09FH,081H,0FCH,0FCH,09CH,0C1H,0FFH ;31-5
DB 0E1H,0CFH,09FH,081H,09CH,09CH,0C1H,0FFH ;32-6
DB 080H,09CH,0F9H,0F3H,0E7H,0E7H,0E7H,0FFH ;33-7
DB 0C3H,09DH,08DH,0C3H,0B0H,0BCH,0C1H,0FFH ;34-8
DB 0C1H,09CH,09CH,0C0H,0FCH,0F9H,0C3H,0FFH ;35-9
END