C51单片机16×16点阵循环滚动显示(含16×32扩展方式)【详解】

目录

    • 基本功能
    • 开发软件
      • 软件介绍
        • Keil
        • Proteus
        • PCtol2002
      • 硬件部分
        • 元器件介绍
          • 74HC154
          • 74HC595
          • 8×8点阵
        • 仿真电路图
          • 整体电路
          • 16×16的组合
      • 软件
        • 各部分介绍
          • 延时子函数
          • 串行发送子函数
          • 主函数
        • 源程序
      • 扩展
        • 硬件扩展(扩展点阵大小)
          • 点阵扩展
          • 74154扩片
        • 程序修改
        • 继续扩展?
      • 写在最后

基本功能

要实现一个16×16小的LED点阵循环滚动显示“XXXXXXXx”字样。

开发软件

Proteus、Keil、PCtoLCD2002

软件介绍

Keil

Proteus

PCtol2002

取字模软件,简单实用,类似软件有很多
链接:https://pan.baidu.com/s/1rgO3B-a85U7wOkJXvk7bSw
提取码:og69

硬件部分

元器件介绍
74HC154

4-16线译码器
C51单片机16×16点阵循环滚动显示(含16×32扩展方式)【详解】_第1张图片
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)
C51单片机16×16点阵循环滚动显示(含16×32扩展方式)【详解】_第2张图片

74HC595

3态高速位移寄存器。串行输入,并行输出。
C51单片机16×16点阵循环滚动显示(含16×32扩展方式)【详解】_第3张图片
14脚:DS,串行数据输入引脚
12脚:ST_CP,存储寄存器时钟输入引脚。上升沿时,数据从移位寄存器转存带存储寄存器。
11脚:SH_CP,移位寄存器时钟引脚,上升沿时,移位寄存器中的数据整体后移,并接受新的数据(从DS输入)。
10脚:MR,低电平时,清空移位寄存器中已有的数据,一般不用,接高电平即可。
13脚:OE,输出使能控制脚,它是低电才使能输出,所以接GND
9脚:串行数据输出引脚。当移位寄存器中的数据多于8位时,会把已有的位“挤出去”,就是从这里出去的。用于595的级联。
1-7脚:Q1-Q7并行输出引脚

使用详解:https://blog.csdn.net/weixin_43808473/article/details/106567336

8×8点阵

Proteus提供了四种LED点阵
红色点阵和其他三种的极性不同
在这里插入图片描述
使用详解:https://blog.csdn.net/weixin_43808473/article/details/106571339

仿真电路图
整体电路

C51单片机16×16点阵循环滚动显示(含16×32扩展方式)【详解】_第4张图片

16×16的组合

C51单片机16×16点阵循环滚动显示(含16×32扩展方式)【详解】_第5张图片

软件

各部分介绍
延时子函数

void delay(uint i)
接收一个无符号整数i,将执行125次空语句作为循环体循环i次,每循环一次约消耗1ms,循环i次则延时了ims。

串行发送子函数

void Send(uchar Data,uchar Data1)
参数是两个无符号字符型数据(两位十六进制数),程序将该数8位二进制格式的首位加载到74595芯片的输入端,SH_CP上升沿触发。发送一次后该数左移一位,第二位变成首位,SH_CP上升沿触发,将对应的值送到595芯片上,以此类推,循环8次后实现了一个8位二进制数(2位十六进制数)的串行输出。依次将两个参数的串行输出到两篇595上后,ST_CP上升沿触发595芯片的并行输出。

主函数

void main (void)
主函数中,三层循环嵌套,最里层循环通过控制P1口的值间接控制74154芯片的输出,依次点亮点阵的第一列、第二列·····以实现位选的目的,最里层循环只循环32次,即控制32列,循环体每次调用串行发送子函数,参数为字模数组中相邻的两个值,例如第一次参数为a[0]和a[1],第二次参数为a[2]和a[3],以此类推。以显示一帧图像。其中语句n=(i+j)%(num*32);中n为数组的第n号元素,i是列选择数,j是当前帧数,num是要显示的字数(num×32是字模数组中元素的个数),取余运算实现了循环滚动的功能。
第二层循环控制将这一帧图像显示一次或重复多次,通过控制一帧图像刷新的次数来控制图像滚动的速度,刷新次数越多,滚动速度越慢。
最外层循环使图像滚动,每循环一次为一帧,循环次数为要显示的动态图像的帧数,动态图像的帧数取决于字模的宽度(列数)。
定义j和n为无符号整型变量,可使图像最大长度达到65566列(2048个字),极大的拓宽了使用范围。

源程序
#include
#include
  
#define unsigned char uchar;
#define unsigned int uint;
uchar code ldis[] = 
		{
		0xF7,0xDF,0xF9,0xDF,0xBF,0x81,0xCE,0x7F,0xFF,0xFF,0xDF,0xFF,0xD8,0x0F,0xDB,0xDF,0xDB,0xDF,0xD8,0x0F,0xDF,0xFD,0xDF,0xFE,0xC0,0x01,0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,/*"河",0*/
				0xFF,0xFB,0xFB,0xF9,0xFB,0xFB,0xFB,0xF7,0xFB,0xF7,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x03,0xFD,0xFD,0xFB,0xFD,0xF7,0xFD,0xEF,0xFD,0xFF,0xE1,0xFF,0xFF,/*"北",1*/
				0xFF,0xFF,0xC0,0x1E,0xFF,0xFD,0xFF,0xF3,0x00,0x0F,0xFF,0xFF,0xBF,0xFF,0xB8,0x07,0xBB,0xFF,0xBB,0xFF,0x80,0x00,0xBB,0xEF,0xBB,0xF7,0xB8,0x0F,0xBF,0xFF,0xFF,0xFF,/*"师",2*/
				0xDF,0xFF,0xDD,0xEF,0xDE,0x6F,0xD7,0xE1,0xD9,0xDF,0x0F,0x3F,0xDF,0xFF,0xD8,0x03,0xDB,0xFD,0x0B,0xFD,0xDB,0xBD,0xDB,0xDD,0xD8,0x3D,0xDF,0xFD,0xDF,0xE1,0xFF,0xFF,/*"范",3*/
				0xFB,0xFE,0xFB,0xFE,0xFB,0xFD,0xFB,0xFB,0xFB,0xF7,0xFB,0xCF,0xFB,0x3F,0x00,0xFF,0xFB,0x3F,0xFB,0xCF,0xFB,0xF7,0xFB,0xFB,0xFB,0xFD,0xFB,0xFE,0xFB,0xFE,0xFF,0xFF,/*"大",4*/
				0xFD,0xDF,0xF3,0xDF,0x77,0xDF,0x96,0xDF,0xF6,0xDF,0xF6,0xDD,0x76,0xDE,0x96,0x81,0xF6,0x9F,0xF6,0x5F,0xE6,0xDF,0xD7,0xDF,0x37,0xDF,0xF5,0xDF,0xF3,0xDF,0xFF,0xFF,/*"学",5*/
				0xDF,0xF7,0xDB,0xEF,0xDD,0x9F,0xDE,0x7F,0xD9,0xBE,0xC6,0xCD,0xFD,0xFB,0xF3,0xE7,0x0F,0x9F,0xEC,0x7F,0xEF,0x9F,0xEF,0xE7,0xEB,0xFB,0xE7,0xFD,0xFF,0xFE,0xFF,0xFF,/*"欢",6*/
				0xFD,0xFF,0xFD,0xFD,0xBD,0xFB,0xCC,0x07,0xFF,0xFB,0xFF,0xFD,0xC0,0x0D,0xDF,0xDD,0xBF,0xBD,0xFF,0xFD,0xC0,0x01,0xDF,0xBD,0xDF,0xDD,0xC0,0x3D,0xFF,0xFD,0xFF,0xFF,/*"迎",7*/
				0xFB,0xFD,0xF7,0xF3,0xEF,0xFF,0xC0,0x11,0x3B,0xFE,0xF7,0x7E,0xEE,0xEE,0x19,0xB2,0xDF,0xDE,0xD0,0x3E,0xDF,0xFE,0xDB,0xF8,0xD5,0xFF,0xCE,0x77,0xFF,0xF9,0xFF,0xFF,/*"您",8*/
		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};/*空白*/
/**********函数声明********************/
void delay(uint i);	
void Send(uchar Data,uchar Data1);
/***********************************/
sbit SH_CP = P3^4;    //串行输入时钟,上升沿有效
sbit ST_CP = P3^5;    //串行寄存器时钟,上升沿有效
sbit DS = P3^7;
sbit DS1 = P3^6;

void main()
{
	uint i,j,k,n,num;														
	num=10;		//		   
	while(1)
	{ 
	 	for(j=0;j<num*32;j+=2) //这个图像一共几列就几帧
		{	
			for(k=0;k<1;k++)//重复显示一帧数据多少次,调节滚动速度	
			{
				P1=0x00;
				for(i=0;i<32;i+=2)	
				{
					n=(i+j)%(num*32);
					P1++;					  //x轴移位
					Send(ldis[n],ldis[n+1]);
					ST_CP = 0;				//ST_CP=0-1并行送出一排
					_nop_();
					ST_CP = 1;	
					delay(1);		
				}
			}	
		}		
	}
}
//发送一个字节数据给595再并行输出
void Send(uchar Data,uchar Data1)
{
	char i;
	for(i=0;i<8;i++)
	{		
		SH_CP = 0;					  //SH_CP=0-1串行输入一位
		DS=0x80&Data;
		DS1=0x80&Data1;
		_nop_();		 
		SH_CP = 1;
		_nop_();               //上升沿让串行输入时钟变成高电平 并延时一个时钟周期  
        Data=_crol_(Data,1);
		Data1=_crol_(Data1,1);
   	} 
}
void delay(uint i)
{
	uchar j;
	while(i--)
	for(j=0;j<125;j++);
}

扩展

硬件扩展(扩展点阵大小)
点阵扩展

复制一个16*16的点阵,修改列号
C51单片机16×16点阵循环滚动显示(含16×32扩展方式)【详解】_第6张图片

74154扩片

没有采用片间级联的方式,我选择了用P1.4脚控制154的使能端,如下图
C51单片机16×16点阵循环滚动显示(含16×32扩展方式)【详解】_第7张图片
第一片154(U4)的使能端短接后连接P1.4;第二片154(U38)的使能端短接后连接P1.4非
如此 当P1<16时,U4工作,U38不工作,P1>15时,U4停止工作,U38开始工作。

程序修改

修改前

/**其他部分和外层循环不变**/
for(i=0;i<32;i+=2)	
{
	//循环体不变
}	

修改后

/**其他部分和外层循环**/
for(i=0;i<64;i+=2)	
{
	//循环体不变
}	

so,如果要再扩,就是128、256等等,至于硬件上同上,具体方法下面会写。

继续扩展?

假如行数不变只研究列,理论上单片机控制的154可以无限扩展,直到用完IO口(当然用完IO口也有办法)。但是刷新率不够,会产生显示不全的情况。
下面只提供一个思路:
前面是用P1.4控制使能端,一位二进制数有0和1两种情况,可以选择两片。那P1.4、P1.5两位数就有00、01、10、11四种情况,就可以控制四片。
使能端一共就两位,如果要扩到8片呢?我们可以用3-8线译码器74138,16片?32片?我们可以用4-16线译码器74154替换138,以此类推······
当然,还是那句话,理论上是可以的,实际上是实现不了的,不是糟蹋钱的问题,是真的刷新率不够。

写在最后

这次的课程设计只是一个简单的认识,生活中我们常见的电子屏当然不会是这么做的,但是这是基础,是我们走向更复杂的项目的第一步。

你可能感兴趣的:(C51单片机,单片机)