基于单片机的点阵滚屏显示器的设计

收藏和点赞,您的关注是我创作的动力

文章目录

  • 概要
  • 一、系统的硬件部分设计
  • 1 设计基本方案
  • 2 硬件系统的整体设计图与原理分析
  • 二、软件设计
  • 1 主函数的设计
  • 三、 实物
  • 源码
  • 四、 参考文献
  • 五、 结论
  • 概要

      LED是英文light emitting diode(发光二极管)的缩写。由镓(Ga)与砷(As)、磷(P)、氮(N)、铟(In)的化合物制成的二极管,当电子与空穴复合时能辐射出可见光,因而可以用来制成发光二极管。在电路及仪器中作为指示灯,或者组成文字或数字显示。并且不同的元素化合形成的二极管会发出不同颜色的可见光。LED行业发展迅速并已成为一个具有一定规模的新兴产业,而且从总体上来看,宏观环境也非常有利于LED行业的发展,可以说LED行业前景广阔,市场潜力巨大。
      本设计实现了基于单片机AT89C51的16×64 LED点阵的图形的滚动显示。本文主要介绍了LED点阵显示的硬件电路的设计思路以及各个部分的功能及原理和相应程序设计的设计思路和功能。该设计使用取模软件对所要显示的图形进行取模,采用C语言编写其显示程序,利用KeilC集成开发平台生成HEX文件,在Proteus中对硬件电路的时钟、复位、驱动、16×64点阵进行设计并通过译码器等与AT89C51芯片连接,进而对系统进行仿真调试。本设计具有使用性强,操作简单易实现等优点。

    一、系统的硬件部分设计

    1 设计基本方案

    本次设计采用AT89C51单片机及其周边芯片,达到点阵LED与单片机的接口电路的设计。硬件电路主要有:复位电路模块、LED显示模块、时钟电路模块、主控单片机模块、驱动电路模块。如下图2.1所示。

    图2.1 总体结构框图

    图2.1 简略的描述了系统的结构,本系统由电源电路提供电源,先由单片机的P2.0口按位输出所要显示字的代码到列驱动,然后再通过单片机的P3.0至P3.3口送行代码到LED显示模块选中行,这样进行逐行扫描从而实现汉字、图形等的显示。

    2 硬件系统的整体设计图与原理分析

    图2.5 硬件系统的整体设计图
    硬件系统的整体设计图如图2.5所示。
    原理分析:
    Proteus 7.4软件中只有8×8和5×7等LED点阵,所以需要由小的LED屏拼接成一个大的LED。由16个8×8的点阵构成上图的LED显示部分整体的16×64点阵屏。点阵屏的拼接方法已经在前面叙述过了。
    本设计中 LED点阵显示屏采用的是逐行扫描的工作方式。XTAL1与XTAL2接12MHz的晶振;RST接复位电路;P1.7口与74HC138的E1相连,以此控制74HC138是否工作即是否产生输出;E2直接接地,即E2保持为低电平;P3.0与74HC138的地址线A相连,P3.1与74HC138的地址线B相连,P3.2与74HC138的地址线C相连,P3.3与74HC138的地址线D相连,以此选择74HC138有效的输出端口;74HC138的输出端口(0到15脚)分别连接一个反相器74HC04,需要说明的是,Proteus中的74HC04是一相反相的,真实的74HC04则是六相反相,即输入端与74HC138的0号输出引脚相连的反相器74HC04的输出端与点阵最上端的行线相连,其余各行按顺序对应相连;P2.0口连接左边第一个74HC595的DS端口,将上一个74HC595的Q7’与后一个74HC595的DS端口连起来,便能达到串行数据的依次“向后传递”;每个 74HC595的SH_CP端口均与P2.1端口相连;每个74HC595的ST_CP端口与P2.2端口连接起来;将每一个74HC595的OE与地相连、MR与电源相连;74HC595按从左向右,输出端口按Q0—Q7的顺序,依次与列线(自左向右)相连。
    画仿真图时,很多行线与列线需要相连,然而我们直接将两个端口连接,仿真图将会呈现出多条密密麻麻的线,便于美观和方便,我们只需要将各个连线端口各引出一条小短线,然后给其命上相同的名字便可,这样Proteus就默认为这两条线是连接在一起的。其操作方法是,选中要命名的线,右键选择“Place Wire Label”(给线写标签),然后在弹出的对话框中的“String”(线)中选择或者输入名称。

    二、软件设计

    1 主函数的设计

    各种各样的应用软件能够帮助系统实现各大功能,而本系统采取了模块化结构,其中主要为显示子程序、延时程序及主程序。
    计算机为了完成规定的任务,通过系统程序一条一条来执行颁布的指令。为了计算机能够完成我们所提出的各项任务,需要编写计算机语言来达到这一目标,而本设计主要采取C语言来完成。C语言作为一种常用的计算机语言具有极高的使用效能,它不仅能够适用如windows 98、windows NT、 UNIX等多种操作系统,而且能够满足多种机型的要求。因此C语言备受青睐。在该设计中,能在程序中方便的改变所要显示的内容,能够使显示内容实现向左、向右、向上、向下任何一个方向的移动,能够通过改变程序实现其移动速度的改变。

    三、 实物

    源码

    #include<reg52.h>
    #define uint unsigned int
    #define uchar unsigned char
    sbit E1=P1^7;
    sbit DS=P2^0;
    sbit SRCK=P2^1;
    sbit RCK=P2^2;
    uchar yid,h;			  
    uint zi;
    uchar BUFF[10];
    void sbuf_outr();
    void in_datar();				  
    void rxd_datar();
    void sbuf_outl();
    void in_datal();				  
    void rxd_datal();
    uchar speed=7;
    uchar code bless[][32]={
    /*--  文字:  迁  --*/
    /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
    {0x00,0x00,  0x03,0xFE,  0xFF,0x66,  0x33,0x66,  
    0x33,0xFE,  0x33,0x66,  0xFF,0x66,  0x33,0xFE,  
    0x33,0x66,  0x30,0x60,  0x33,0xFE,  0x3C,0x60,  
    0xE0,0x60,  0x00,0x60,  0x0F,0xFF,  0x00,0x00,
       },
    /*--  文字:  安  --*/
    /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
    {0x00,0x00,  0x3F,0xFE,  0x01,0x80,  0x01,0x80,  
    0x01,0x80,  0x01,0x80,  0x01,0x80,  0x01,0x80,  
    0x01,0x80,  0x01,0x80,  0x01,0x80,  0x01,0x80,  
    0x01,0x80,  0xFF,0xFF,  0x00,0x00,  0x00,0x00,
       },
    /*--  文字:  学  --*/
    /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
    {0x01,0x8C,  0x18,0xCE,  0x0E,0xEC,  0x0C,0xD8,  
    0x7F,0xFF,  0x60,0x06,  0xCF,0xFC,  0x00,0x60,  
    0x00,0xC0,  0x7F,0xFF,  0x00,0xC0,  0x00,0xC0,  
    0x00,0xC0,  0x00,0xC0,  0x03,0xC0,  0x01,0x80,
     },
    /*--  文字:  院  --*/
    /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
    {0x00,0xC0,  0xFC,0x60,  0xCF,0xFF,  0xDE,0x06,  
    0xF0,0x00,  0xF3,0xFC,  0xD8,0x00,  0xCC,0x00,  
    0xCF,0xFF,  0xFD,0xB0,  0xD9,0xB0,  0xC1,0xB0,  
    0xC3,0x33,  0xC3,0x33,  0xC6,0x33,  0xCC,0x1F,
     },
    /*--  文字:  欢  --*/
    /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
    {0x00,0xC0,  0x00,0xC0,  0xFE,0xC0,  0x07,0xFF,  
    0xC7,0x86,  0x6F,0x6C,  0x3C,0x60,  0x18,0x60,  
    0x1C,0x60,  0x1C,0x70,  0x36,0xF0,  0x36,0xD8,  
    0x61,0x9C,  0xC7,0x0F,  0x3C,0x06,  0x00,0x00,
     },
    /*--  文字:  迎  --*/
    /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
    {0x60,0x00,  0x31,0xC0,  0x3F,0x7E,  0x36,0x66,  
    0x06,0x66,  0x06,0x66,  0xF6,0x66,  0x36,0x66,  
    0x37,0xE6,  0x37,0x7E,  0x36,0x6C,  0x30,0x60,  
    0x30,0x60,  0x78,0x00,  0xCF,0xFF,  0x00,0x00,
        },
    /*--  文字:  您  --*/
    /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
    {0x0C,0x00,  0x0D,0x80,  0x19,0xFF,  0x1B,0x06,  
    0x3E,0x60,  0x3B,0x78,  0x7B,0x6C,  0xDE,0x66,  
    0x19,0xE6,  0x18,0xC0,  0x00,0x00,  0x3D,0x86,  
    0x3C,0xDB,  0x7C,0x1B,  0x07,0xF8,  0x00,0x00,
      },
    /*--  文字:  !  --*/
    /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
    {0x00,0x00,  0x00,0x00,  0x00,0x00,  0x00,0x00,  
    0x18,0x00,  0x18,0x00,  0x18,0x00,  0x18,0x00,  
    0x18,0x00,  0x18,0x00,  0x18,0x00,  0x18,0x00,  
    0x18,0x00,  0x00,0x00,  0x18,0x00,  0x00,0x00,
      },
    /*--  文字:  空屏  --*/
    /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
    {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,
      },
    /*--  文字:  空屏  --*/
    /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
    {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,
     },
    };
    /************延时函数***********/
    void DelayMS(uint x)
    {
       uchar i;
       while(x--) for(i=0;i<1;i++);
    } 
    /***********向74HC595输送字模代码***********/
    void write_byte(uchar a)
    {
    	uchar i,num;
    	num=~a;
    	for(i=0;i<8;i++)
    	{
    		num>>=1;
    		SRCK=0;
    		 DS=CY;
    			SRCK=1;
    				}
    }
    /************左移函数**********/
     void left(void)
    {
      uchar i,d=3;
     yid=0;
     zi=0;							   
     while(1)
      {
      E1=0;
    	while(yid<16)				       
    	{
    		for(i=0;i<d;i++)			   
    		 {
    		 sbuf_outl();
             }
    		yid++;				
    	}
       yid=0;
       zi=zi+1;			    
       if(zi>=8)			
       zi=0;
      }
     }
    /********************************/
    void sbuf_outl()
    	  {
    		for(h=0;h<16;h++)	  
    			{
    			in_datal();				  
    			rxd_datal();
                P3=h;	                 
                RCK=0;
    			RCK=1;
    			DelayMS(1);
               				}
    		}
    /******************************************************/
    void in_datal(void)
    {
     char s;
    for(s=0;s<=4;s++)			
    	{
    	 BUFF[2*s+1]=bless[s+zi][2*h+1];			 
    	 BUFF[2*s]=bless[s+zi][2*h];	    
    	}
    }
    
    /*******************************************************/
    void rxd_datal(void)
    {
      char s;
      uchar inc,tempyid,temp;
      if(yid<8)
        inc=0;
      else 
        inc=1;
      for(s=8+inc;s>=0+inc;s--)
    	{
    	  if(yid<8) 
         tempyid=yid;
          else 
        tempyid=yid-8;
    	temp=(BUFF[s]<<tempyid)|(BUFF[s+1]>>(8-tempyid));
        write_byte(temp) ;
    					 	}
    }
    /************右移函数**********/
     void right(void)
    {
     uchar i,d=2;
     yid=0;
     zi=0;							   
     while(1)
      {	
      E1=0 ;
    	while(yid<16)				      
    	{
    		for(i=0;i<d;i++)			   
    		 {
    		 sbuf_outr();
             }
    		yid++;			
    	}
       yid=0;
       zi=zi+1;			    
       if(zi>=8)			
       zi=0;
      }
     E1=1;
     }
    /********************************/
    void sbuf_outr()
    	  {
    		for(h=0;h<16;h++)	  
    			{
    			in_datar();				 
    			rxd_datar();
                P3=h;	                
                RCK=0;
    			RCK=1;
    			DelayMS(1);
    				             			}
    		}
    /******************************************************/
    void in_datar(void)
    {
     char s;
    for(s=4;s>=0;s--)		
    	{
    	 BUFF[2*s+1]=bless[s+zi][2*h];			 
    	 BUFF[2*s]=bless[s+zi][2*h+1];	   
    	}
    }
    /*******************************************************/
    void rxd_datar(void)
    {
      char s;
      uchar inc,tempyid,temp;
      if(yid<8)
        inc=0;
      else 
        inc=1;
      for(s=0+inc;s<8+inc;s++)
    	{
    	  if(yid<8) 
         tempyid=yid;
          else 
        tempyid=yid-8;
    	temp=(BUFF[s]>>tempyid)|(BUFF[s+1]<<(8-tempyid));
        write_byte(temp);
    					 	}
    }
    /************上移函数**********/
    void up()
    {
    	uchar i,j,k,scan,m,a;
    	DS=1;
    	E1=0;
    	while(1)
    	{
    		for(j=0;j<9;j=j+4)
    		{
               for(k=0;k<speed/2;k++)
                 {
                   for(m=0;m<16;m++)
                    {
    			for(k=0;k<speed;k++)
    			{
    				    a=0	;
    				for(i=m+1;i>0;i=i-1)
    				{	
    					write_byte(bless[j+3][a*2+1]);
    					write_byte(bless[j+3][a*2]);
    					write_byte(bless[j+2][a*2+1]);
    					write_byte(bless[j+2][a*2]);
    					write_byte(bless[j+1][a*2+1]);
    					write_byte(bless[j+1][a*2]);
    					write_byte(bless[j][a*2+1]);
    					write_byte(bless[j][a*2]);
    					RCK=0;
    					RCK=1;
    					P3=16-i;
    					a=a+1 ;
    					E1=0;
    				DelayMS(60);
    					E1=1;	
    								}
                             }			
                            }
                           }
    		 //从底部出来向上移动
    		for(k=0;k<2*speed;k++)
    			{
    				scan=0;
    				for(i=0;i<16;i=i+1)
    				{
    					write_byte(bless[j+3][i*2+1]);
           				write_byte(bless[j+3][i*2]);
    					write_byte(bless[j+2][i*2+1]);
    					write_byte(bless[j+2][i*2]);
    					write_byte(bless[j+1][i*2+1]);
    					write_byte(bless[j+1][i*2]);
    					write_byte(bless[j][i*2+1]);
    					write_byte(bless[j][i*2]);
    					RCK=0;
    					RCK=1;
    					P3=scan;
    					E1=0;
    				DelayMS(60);
    			   		E1=1;
    					scan++;
    								}
    				}//四个字静止显示一段时间
    				for(k=0;k<speed/2;k++)
                 {
                   for(m=16;m>0;m--)
                    {
    			for(k=0;k<speed;k++)
    			{
    				    a=15	;
    				for(i=m;i>0;i=i-1)
    				{	
    					write_byte(bless[j+3][a*2+1]);
    					write_byte(bless[j+3][a*2]);
    					write_byte(bless[j+2][a*2+1]);
    					write_byte(bless[j+2][a*2]);
    					write_byte(bless[j+1][a*2+1]);
    					write_byte(bless[j+1][a*2]);
    					write_byte(bless[j][a*2+1]);
    					write_byte(bless[j][a*2]);
    					RCK=0;
    					RCK=1;
    					P3=i-1;
    					a=a-1 ;
    					E1=0;
    				DelayMS(60);
    					E1=1;	
    								}
                             }			
                            }
                           }  //四个字从屏幕中向上移出
    	}
    }
    }
    /************下移函数**********/
    void down()
    {
    	uchar i,j,k,scan,m,a;
    	DS=1;
    	E1=0;
    	while(1)
    	{
    		for(j=0;j<9;j=j+4)
    		{
               for(k=0;k<speed/2;k++)
                 {
                   for(m=0;m<16;m++)
                    {
    			for(k=0;k<speed;k++)
    			{
    				    a=15	;
    				for(i=m+1;i>0;i=i-1)
    				{	
    					write_byte(bless[j+3][a*2+1]);
    					write_byte(bless[j+3][a*2]);
    					write_byte(bless[j+2][a*2+1]);
    					write_byte(bless[j+2][a*2]);
    					write_byte(bless[j+1][a*2+1]);
    					write_byte(bless[j+1][a*2]);
    					write_byte(bless[j][a*2+1]);
    					write_byte(bless[j][a*2]);
    					RCK=0;
    					RCK=1;
    					P3=i-1;
    					a=a-1 ;
    					E1=0;
    				DelayMS(60);
    					E1=1;	
    								}
                             }			
                            }
                           }
    		 //从顶部出来向下移动
    		for(k=0;k<2*speed;k++)
    			{
    				scan=0;
    				for(i=0;i<16;i=i+1)
    				{
    					write_byte(bless[j+3][i*2+1]);
           			write_byte(bless[j+3][i*2]);
    					write_byte(bless[j+2][i*2+1]);
    					write_byte(bless[j+2][i*2]);
    					write_byte(bless[j+1][i*2+1]);
    					write_byte(bless[j+1][i*2]);
    					write_byte(bless[j][i*2+1]);
    					write_byte(bless[j][i*2]);
    				   RCK=0;
    					RCK=1;
    					P3=scan;
    					E1=0;
    				DelayMS(60);
    					E1=1;
    					scan++;
    								}
    				}//四个字静止显示一段时间
    				for(k=0;k<speed/2;k++)
                 {
                   for(m=16;m>0;m--)
                    {
    			for(k=0;k<speed;k++)
    			{
    				    a=0	;
    				for(i=m;i>0;i=i-1)
    				{	
    					write_byte(bless[j+3][a*2+1]);
    					write_byte(bless[j+3][a*2]);
    					write_byte(bless[j+2][a*2+1]);
    					write_byte(bless[j+2][a*2]);
    					write_byte(bless[j+1][a*2+1]);
    					write_byte(bless[j+1][a*2]);
    					write_byte(bless[j][a*2+1]);
    					write_byte(bless[j][a*2]);
    					RCK=0;
    					RCK=1;
    					P3=16-i;
    					a=a+1 ;
    					E1=0;
    			DelayMS(60);
    					E1=1;	
    								}
                             }			
                            }
                           }  //四个字从屏幕中向下移出
    	}
    }
    }
     /************主函数**********/
     void main ()
     {
        down();
    }
    
    

    四、 参考文献

    [1] 张迎新.单片机初级教程[M]. 北京:北京航空航天大学出版社,2006.
    [2] 张俊谟.SOC单片机原理与应用—基于C8051F系列[M]. 北京:北京航空航天大学出版社,2009.
    [3] 诸昌钤. LED显示屏系统原理及工程技术[M].成都:电子科技大学出版社,2000.
    [4] 梅开乡.数字逻辑电路(第2版). 北京:电子工业出版社,2005.
    [5] 张培仁.基于C语言C8051F系列微控制器原理及应用[M]. 北京:清华大学出版社,2009.
    [6] 应朝龙.基于C8051F020芯片的多功能计数器设计[J]. 微计算机信息,2009年(23).
    [7] 吉雷. Protel99从入门到精通. 西安:西安电子科技大学出版社,2004.
    [8] Vizimuller.P. RF design guide-systems,circuits,and equations. 1995.
    [9] R.Dye. Visual Object-Orientated Programming,Dr.Dobbs Macintosh Journal. Sept.1st (1991).

    五、 结论

    本论文向读者介绍了对单片LED滚动显示屏基本功能及使用方法。将硬件电路和软件程序结合在一起,详细分析了电路的工作原理,程序的执行过程和程序编写的思想。并介绍了仿真软件Proteus和程序开发软件Keilc的操作方法,给出了仿真结果。
    本设计能够实现图形的上下左右四个方向滚动的功能, 本设计在使用16×64LED点阵的基础上,通过含纳LED显示屏电路的运行程序及原理,便可以帮助我们设计出样式不一的大面积LED显示屏,而且仅仅只需要扩大单片机的I/O接口并加入一些芯片和LED点阵。
    单片机原理、模拟电子技术、微机原理机电子技术是此次设计的主要理论基础,通过MCS—51完善了AT89C51芯片的工作原理。
    本次设计帮助我进一步学习到以前所学习的专业知识,而且在互联网搜集整理信息的同时学习了很多其它以前没有学习过的芯片,学会了芯片引脚的认识方法等。在制作实物的过程中,也锻炼了自己的耐心和动手能力。 在这次毕业论文的独立设计下,我将专业知识与实际运用高效结合起来,在毕业论文的设计过程中我也遇到了许许多多的困难,但是它不仅培养了我遇到困难不放弃的决心也培养了我对于新事物的探索求知能力,对我在将来的工作是一次十分宝贵的经历。

    作者:启初科技

    物联沃分享整理
    物联沃-IOTWORD物联网 » 基于单片机的点阵滚屏显示器的设计

    发表回复