【Proteus仿真】51单片机16×16点阵显示汉字,附程序

该文详细介绍了如何使用AT89C52单片机结合4个74HC595芯片驱动16×16点阵模块显示汉字的过程,包括电路设计、74HC595的时序控制、取模软件的应用以及C语言程序的编写和调试。通过横向取模和移位锁存器,实现了汉字的动态显示,并提供了移屏显示的实现方法。
摘要由CSDN通过智能技术生成

51单片机点阵学习总结

利用AT89C52单片机开发板结合4个8×8点阵(即16×16)模块+4个74HC595芯片+取模软件+C语言编制的程序显示汉字

一、学习思路——基于AT89C52单片机(结合指针横向移平等显示汉字)

1、电路详情

1.点阵模块如图所示,这里还需要4片74HC595芯片。
在这里插入图片描述
(1)单片机端口直接驱动。要驱动8×8的点阵需要2个IO端口(16个IO口)、要驱动16×16的点阵需要4个IO端口(32个IO口)。
(2)使用串转并移位锁存器驱动。要驱动16×16点阵只需要4个74HC595+3个IO口即可(数据口、SCLK、RCLK)。
显然在点阵足够大时,我们需要使用串转并移位锁存器驱动。
在这里插入图片描述
2.74HC595芯片特点是8位串行输入/输出或并行输出移位寄存器,具有高阻关状态。
(1)74HC595有三态,SER(数据输入),SRCLK(移位寄存器时钟)和RCLK(锁存器时钟);且SER、SRCLK和RCLK均需连接到52单片机I/O引脚上,SER连接到P3-4,SRCLK连接到P3-6,RCLK连接到 P3-5,QA-QH8路并行输出接到点阵的一个端口且QH’串行输出口接下一个74HC595的串行输入SER(串联顺序按照0123),所以将来编程时整个4个74HC595的串行数据都是从P3.4出来的。
(2)它的时序规则,发送方是单片机,接收方是74HC595,根据595芯片手册上的时序描述,SER进行数据的串行输入,SRCLK是移位时钟,595芯片内部在每个SRCLK的上升沿会对SER引脚进行一次采样输入,就向595内部输入了1位,如此循环8次就输入了8位二进制。RCLK是锁存时钟,QA-QH的8位并行输出信号在RCLK的上升沿进行一次锁存更新。
需要注意POS1-16和NEG1-16分别接移位锁存器并行输出端,POS就是Positive正极,NEG是negetive负极。QA-QH为低到高位

2、74HC595程序:

void SenData(uchar d1,uchar d2,uchar d3,uchar d4)
{
	uchar i = 0,j = 0;

	SCLK = 0;//起初位移、锁存给低电平
	LCLK = 0;//锁存时钟,原本为RCLK,与reg52中的T2CON冲突了
	
	for(i = 0;i <8;i++)
	{
		SER = d1 >> 7;//将d1的最高bit取出给SER
		SCLK = 0;
		SCLK = 1;//2步制造了一个SCLK上升沿
		d1 = d1 << 1;
	}
	//至此已经在8个SCLK上升沿把D1的8位依次全部发送出去
	//但是还没有进行锁存,所以QA-QH还没有东西
	
	for(i =0;i < 8;i++)
	{
		SER = d2 >> 7;//将d2的最高bit取出给SER
		SCLK = 0;
		SCLK = 1;//2步制造了一个SCLK上升沿
		d2 = d2 << 1;
	}
	//到这里已经把d1和d2发送出去,并且d2把d1挤入第二个595芯片
	//但是还没有进行锁存,所以QA-QH还没有东西

	for(i =0;i < 8;i++)
	{
		SER = d3 >> 7;//将d3的最高bit取出给SER
		SCLK = 0;
		SCLK = 1;//2步制造了一个SCLK上升沿
		d3 = d3 << 1;
	}
	//到这里已经把d1、d2和d3发送出去,并且d1被d2和d3挤入第三个595芯片,d3把d2挤入第二个595芯片
	//但是还没有进行锁存,所以QA-QH还没有东西
	
	for(i =0;i < 8;i++)
	{
		SER = d4 >> 7;//将d4的最高bit取出给SER
		SCLK = 0;
		SCLK = 1;//2步制造了一个SCLK上升沿
		d4 = d4 << 1;
	}
	//到这里已经把d1、d2、d3和d4发送出去
	//但是还没有进行锁存,所以QA-QH还没有东西
	//注意最先进入的会被挤到最后一个芯片中,四个字节数据沿着SER->OH'串行输出线进入四个芯片,但此时没有锁存,不会点亮
	LCLK = 0;
	LCLK = 1;//一次跳变(上升沿)四个芯片同时进行锁存
}

3、取模软件进行取模(横向取模,这里是两两对应)

16×16点阵,256个点用256个二进制位表示,1表示这个点亮,0表示不亮。256个点就是256个二进制位,也就是256/8=32个字节。所以一个大小为16×16的字的字模是32个字节大小。所以字模的表现形式就是32个unsigned char型数据。注意字模的结果不是唯一的,关键看取模方式
在这里插入图片描述
这里我们将C代码数组保存下来,后续根据需要是否取反

unsigned char code ji[] =
{
	16,0,17,240,17,16,17,16,
	253,16,17,16,49,16,57,16,
	85,16,85,16,145,16,17,18,
	17,18,18,18,18,14,20,0
}

行的数组如下所示

unsigned char code ss[] = 
{	
		0x7f,0xff,0xbf,0xff,0xdf,0xff,0xef,0xff,
		0xf7,0xff,0xfb,0xff,0xfd,0xff,0xfe,0xff,
		0xff,0x7f,0xff,0xbf,0xff,0xdf,0xff,0xef,
		0xff,0xf7,0xff,0xfb,0xff,0xfd,0xff,0xfe	
};

4、程序编译与调试

(1)程序如下:

#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit SER = P3^4;//74HC595的串行输入端
sbit LCLK = P3^5;//锁存时钟,原本为RCLK,与reg52中的冲突了
sbit SCLK = P3^6;//移位时钟
uchar d1,d2,d3,d4;//给四个595并行输出端输出的值
uchar code ji[]=
{
	16,0,17,240,17,16,17,16,
	253,16,17,16,49,16,57,16,
	85,16,85,16,145,16,17,18,
	17,18,18,18,18,14,20,0
};

uchar code ss[] = 
{
		0x7f,0xff,0xbf,0xff,0xdf,0xff,0xef,0xff,
		0xf7,0xff,0xfb,0xff,0xfd,0xff,0xfe,0xff,
		0xff,0x7f,0xff,0xbf,0xff,0xdf,0xff,0xef,
		0xff,0xf7,0xff,0xfb,0xff,0xfd,0xff,0xfe
};

void senData(uchar d1,uchar d2,uchar d3,uchar d4)
{
	uchar i = 0,j = 0;

	SCLK = 0;//起初位移、锁存给低电平
	LCLK = 0;
	
	for(i = 0;i <8;i++)
	{
		SER = d1 >> 7;//将d1的最高bit取出给SER
		SCLK = 0;
		SCLK = 1;//2步制造了一个SCLK上升沿
		d1 = d1 << 1;
	}
	//至此已经在8个SCLK上升沿把D1的8位依次全部发送出去
	//但是还没有进行锁存,所以QA-QH还没有东西
	
	for(i =0;i < 8;i++)
	{
		SER = d2 >> 7;//将d2的最高bit取出给SER
		SCLK = 0;
		SCLK = 1;//2步制造了一个SCLK上升沿
		d2 = d2 << 1;
	}
	//到这里已经把d1和d2发送出去,并且d2把d1挤入第二个595芯片
	//但是还没有进行锁存,所以QA-QH还没有东西

	for(i =0;i < 8;i++)
	{
		SER = d3 >> 7;//将d3的最高bit取出给SER
		SCLK = 0;
		SCLK = 1;//2步制造了一个SCLK上升沿
		d3 = d3 << 1;
	}
	//到这里已经把d1、d2和d3发送出去,并且d1被d2和d3挤入第三个595芯片,d3把d2挤入第二个595芯片
	//但是还没有进行锁存,所以QA-QH还没有东西
	
	for(i =0;i < 8;i++)
	{
		SER = d4 >> 7;//将d4的最高bit取出给SER
		SCLK = 0;
		SCLK = 1;//2步制造了一个SCLK上升沿
		d4 = d4 << 1;
	}
	//注意最先进入的会被挤到最后一个芯片中,四个字节数据沿着SER->OH'串行输出线进入四个芯片,但此时没有锁存,不会点亮
	LCLK = 0;
	LCLK = 1;//一次跳变四个芯片同时进行锁存
}

void main()
{	
	uchar a = 0;
	for(a = 0;a <= 15 ;a++)
	{		
		senData(ji[2*a],ji[2*a+1],ss[2*a],ss[2*a+1]);
	};
}

(2)Keil编译器编译:
在这里插入图片描述
(3)效果展示
在这里插入图片描述

5、移屏显示

这里我是直接清屏,当然也可以一格一格左移或右移等;定义一个指针数据指向汉字,因为汉字有多个,所以借用指针。主函数代码和数组如下所示,SenData()在上述程序已说明。

//  没
unsigned char code tab1[]={0,0,33,240,17,16,17,16,129,16,66,16,84,14,24,0,19,248,34,8,225,8,33,16,32,160,32,64,33,176,14,14};
//  有
unsigned char code tab2[]={2,0,2,0,255,254,4,0,4,0,15,240,8,16,24,16,47,240,72,16,136,16,15,240,8,16,8,16,8,80,8,32};
//  伞
unsigned char code tab3[]={1,0,1,0,2,128,4,64,8,32,48,24,193,6,17,16,9,16,9,32,1,0,255,254,1,0,1,0,1,0,1,0};
//  的
unsigned char code tab4[]={16,64,16,64,32,64,126,124,66,132,66,132,67,4,66,68,126,36,66,36,66,4,66,4,66,4,126,4,66,40,0,16};
//  孩
unsigned char code tab5[]={0,32,252,16,4,16,11,254,16,32,16,66,20,132,25,248,48,16,208,34,16,196,19,8,16,16,16,40,80,196,35,2};
//  子
unsigned char code tab6[]={0,0,127,248,0,16,0,32,0,64,1,128,1,0,255,254,1,0,1,0,1,0,1,0,1,0,1,0,5,0,2,0};
//  必
unsigned char code tab7[]={0,0,4,0,2,16,1,16,1,32,8,32,40,72,40,68,40,132,73,2,74,2,140,18,8,16,24,16,39,240,64,0};
//  须
unsigned char code tab8[]={8,0,9,254,16,32,32,64,65,252,137,4,9,36,17,36,33,36,69,36,133,36,9,68,16,80,32,136,65,4,130,2};
//  努
unsigned char code tab9[]={16,0,16,0,254,252,34,132,68,136,40,80,16,32,40,88,197,134,2,0,2,0,127,248,4,8,8,8,16,80,96,32};
//  力
unsigned char code tab10[]={2,0,2,0,2,0,2,0,127,248,2,8,2,8,2,8,2,8,4,8,4,8,8,8,8,8,16,136,32,80,64,32};
//  奔
unsigned char code tab11[]={2,0,2,0,127,252,4,64,9,32,49,24,207,230,1,0,9,32,8,32,127,252,8,32,8,32,16,32,16,32,32,32};
//  跑
unsigned char code tab12[]={0,128,124,128,69,252,69,4,70,4,125,244,17,20,17,20,93,20,81,244,81,4,81,40,93,18,225,2,0,254,0,0};


void main()
{ 
	int k = 0, i = 0, ms;
	//定义一个指针数据指向汉字
  uchar *p[] = {tab1, tab2, tab3, tab4, tab5, tab6,tab7, tab8,tab9, tab10, tab11,tab12};				  		
	while(1)
	{
		for(i = 0; i < 12; i++)		//总共12个字
		{
			for(ms = 50; ms > 0; ms--)	//显示50次,即肉眼可识别的停留时间
			{
				for(k = 0; k < 16; k++)			//显示一个字
				{	 						
					SenData((*(p[i] + 2*k )),(*(p[i] + 2*k + 1)),ss[2*k],ss[2*k + 1]); 
				}
				SenData(0,0,0xff,0xff);				//清屏		 
			}
		}  							    		  
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是太宰呀!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值