基于51单片机的LED点阵显示屏设计

一、设计任务与要求

1.点阵大小:16*32

2.可显示中英文及ASCII码

3.具有水平、垂直等多种移动显示功能

4.可通过上位机串口修改显示内容

二、方案设计与论证

初步思路

        LED点阵设计主要应用于显示屏,它是利用发光二极管点阵模块或像素单元组成的平面式显示屏幕。由于16*32的点阵规格,STC89C52单片机的端口数量没有足够到可以通过每一个引脚来控制LED点阵的每行每列,因此需要一定的外部电路进行实现。

        首先我选择了串行转并行的芯片-74HC595。该芯片最大的特点就是通过一位的产行输入转成八位的串口输出,芯片功能将在下方详细说明。这样虽然可以解决了单片机端口数量的问题,但是8*8LED点阵屏驱动的问题没有得到解决。16*32的点阵屏共有512个LED灯,即使点阵工作时仅有1/3~1/2的LED灯需要点亮,200个左右的LED灯,不管是74HC595芯片的输出还是单片机端口的输出都无法驱动。也就是说此处需要外部驱动电路,因此我选择了ULN2803芯片作为LED点阵屏的驱动,使用达林顿管结构(ULN2803内部均为该结构)来提高单片机的驱动能力使其足够驱动多个LED灯。

总原理图

        上方为本次实验的仿真原理图和相关元件分布,我将其分为2个模块,即单片机外围电路和LED驱动电路来说明。

单片机外围电路

        上方为单片机外围电路,由12MHz的晶振,两个22pF的电容和10K欧姆的电阻组成了单片机的晶振外围电路和复位电路,进而保证单片机正常工作。而右方的两个上拉电阻是单片机用外部电路所必备的部分,进而驱动芯片。

LED驱动电路

        上方为LED点阵屏的驱动电路。左方为ULN2803芯片,使用达林顿管结构,其基极足够灵敏,可以相应来自开关或直接来自单片机的小输入电流,并对其进行放大。但对于给定的负载电流,达林顿管结构会变热,需要散热性,同时其较慢的开关响应时间,使得其完全导通或完全截止的时间更长。但对于LED点阵屏,其性质能够完美满足其驱动。该芯片能够承载的输出电流为500mA,而点阵屏中一个LED灯的驱动电流为20mA,一行一共有16个LED灯,即最大电流为320mA,完全足够。

        右方为74HC595芯片,该芯片为串行输入,8位并口输出,具有三种输出状态,两个时钟接口SHCP与STCP和一个数据输入接口DS。其工作原理如下:将DS的数据,通过SHCP产生上升沿,一位位的移入移位寄存器,然后再有STCP产生一个上升沿,将移位寄存器的数据送入存储寄存器,再通过OE低电平使能,将对应的数据给到工作引脚,实现串口转并行输出,同时提供串行输出端口与其他的74HC595串联实现多位并行输出。

        由实际硬件结构可知,在编写C语言代码时,只能通过循环,更改行选,同时选择每一行点亮的LED灯,进而实现对LED点阵屏显示内容的控制。而显示内容上下移动的原理是在以上循环的基础上增加一个循环,不断更改偏移量,同时将偏移量增加到行选中,进而实现点阵显示屏上下移动的功能。而左右移动的逻辑与其相似,同样是增加一个外部循环,不断更改偏移量,同时将偏移量增加到列选中,进而实现左右移动的功能。

        最后是上位机串口。此处在代码中使用串口中断函数,即interrupt 4,同时在主函数中初始化波特率函数,之后使用烧录器对其送入数据,并与其内部存储字符的ASCAⅡ码对比,进而执行其对应的功能。

三、实验代码

        下方为流程图:

        下方为实验代码:其中取字模的部分可以在网上搜索软件自行使用,此处就不给出具体软件。其余原理已在上方详细说明。

#include<reg52.h>
#include<intrins.h>
sbit ds=P0^0;
sbit shc=P0^7;
sbit stc=P0^1;
unsigned char j;
void uart_init(unsigned char b);
void display_out();
void display();
int display_data=0;
unsigned char m=0;
unsigned char s=0;
//unsigned char code table2[] = {0x00,0xE4,0x48,0x48,0x41,0x82,0x92,0x90,0x08,0x08,0x07,0x04,0x04,0x84,0x44,0x30};
//unsigned char code table1[] = {0x00,0x1F,0x10,0x10,0x10,0x08,0x08,0x08,0x05,0x05,0x02,0x02,0x05,0x08,0x10,0x60};
/*unsigned char code table1[] = {0x00,0x00,0xE4,0x1F,0x48,0x10,0x48,0x10,0x41,0x10,0x82,0x08,0x92,0x08,0x90,0x08,
0x08,0x05,0x08,0x05,0x07,0x02,0x04,0x02,0x04,0x05,0x84,0x08,0x44,0x10,0x30,0x60};*/ 
//
unsigned char code table2[]={0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x40,0x00,
0x20,0x00,0x10,0x00,0x08,0x00,0x04,0x00,0x42,0x00,0x7E,0x00,0x00,0x00,0x00,0x00};//B
unsigned char code table1[]={0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x18,0x00,0x14,0x00,0x14,0x00,
0x24,0x00,0x3C,0x00,0x22,0x00,0x42,0x00,0x42,0x00,0xE7,0x00,0x00,0x00,0x00,0x00}; //A
//unsigned char code table1[] = {0x80,0x00,0x84,0x78,0x88,0x48,0xE8,0x4B,0x81,0x48,0x82,0x78,0x82,0x48,0xE8,0x4B,
//0x28,0x4A,0x24,0x7A,0x27,0x4A,0xE4,0x4B,0x24,0x4A,0x04,0x44,0x04,0x54,0x00,0x22}; //
//unsigned char code table2[] = {0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x22,0x20,0x12,0x3E,0x0A,0x20,0x06,0x20,0x02,
//0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x42,0x38,0x42,0x27,0x42,0x22,0x7C,0x20,0x00}; //
/*unsigned char code table1[] = {0x08,0x00,0x88,0x3F,0xBC,0x20,0x84,0x20,0x82,0x3F,0xBD,0x20,0x88,0x20,0x88,0x3F,
0x3F,0x00,0x88,0x48,0x88,0x2B,0x88,0x18,0xA8,0x08,0x98,0x4A,0x88,0x49,0x80,0x70}; /*/
//上方为测试时使用的许多字模
unsigned char code table5[] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};  // 1~8行
unsigned char code table6[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; // 9~16行

void shiftOut(unsigned char buf)
{
    unsigned char i;
    for(i = 0;i<8;i++) 
	
		{
			
      ds=buf&(0x80);
      buf <<= 1;
      shc = 0; 
			_nop_();
			shc = 1;			
    }
}

void hc595(unsigned char buffer1, unsigned char buffer2, unsigned char buffer3, unsigned char buffer4) {
    shiftOut(buffer1);
    shiftOut(buffer2);
    shiftOut(buffer3);
    shiftOut(buffer4);
    stc = 0;
		_nop_();
    stc = 1;
}

void display()
{ 
	P0=0x00;
	P2=0x00;
	switch(display_data)
	{
		case 35:
			for(j=0;j<16;j++)
		{
			hc595(table2[2*j+1],table2[2*j],table1[2*j+1],table1[2*j]);
			P1=table5[j];
			P2=table6[j];
			}
		
		break;
			
	
		
		case 49:
			for(s=0;s<16;s++)
		{
			if(s>=16)
				s=0;
			for(j=0;j<16;j++)
			{
				
				m=j+s;
				if(m>=16)
					m=m-16;
				P0=table5[m];
				P2=table6[m];
				hc595(table2[2*j+1],table2[2*j],table1[2*j+1],table1[2*j]);
				P0=0x00;
				P2=0x00;
				_nop_();
				_nop_();
				s++;
			}
		}
		break;
		case 50:
			for(s=0;s<16;s++)
			{
				for(j=0;j<16;j++)
			{
				P0=table5[m];
				P2=table6[m];
				hc595(table2[2*j+1]<<s,table2[2*j]<<s,table1[2*j+1]<<s,table1[2*j]<<s);
				P0=0x00;
				P2=0x00;
				_nop_();
				_nop_();
				s++;
			}
		break;
		case 51:break;
				
			}
			
			
			
		
		break;
			
	}
	
			
}
void uart_init(unsigned char b)
{
	TMOD|=0X20;	//设置计数器工作方式2:自动重装初值的 8 位计数器
	SCON=0X50;	//设置为工作方式1
	PCON=0X80;	//波特率加倍
  TH1=b;	//计数器初始值设置
	TL1=b;
	ES=1;		//打开接收中断
	EA=1;		//打开总中断
	TR1=1;		//打开计数器		
}
void uart() interrupt 4 //串口通信中断函数
{
	unsigned char rec_data;
	RI = 0;			//清除接收中断标志位
	rec_data=SBUF;	//存储接收到的数据
	display_data=rec_data;
}

void main()
{
	uart_init(0XFA);//波特率为9600
	
	while(1)
	{
		display();
	}
	
}

四、实验结果:

        此处仅示例静态显示

  • 42
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

三小只程序猿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值