项目二:LED点阵实验

摘要:

本项目以AT89C52为基础,使用74HC138和74HC595控制8*8LED点阵显示拟定的内容,可以进行和静态显示和动态显示,并能够控制显示的方向,同时使用lcd1602作为辅助功能,显示相关的内容

一.主体思路

使用MATRIX-8*8LED点阵,由74HC138控制列(行),74HC595显示数据,从而将指定的数据输入点阵显示

静态显示,每次输出前8个数据的后8个数据,逐帧显示

动态显示,每次输出前8个数据的后7个数据+第9个数据,以此类推,达到动画的效果

二.主要内容

1.主要功能

(一)静态显示姓名首字母以及姓名

(二)动态显示姓名首字母以及姓名

(三)LCD1602显示模式,不同模式代表不同功能

2.硬件电路设计

2.1 元件选取

如上图所示,选取AT89C52开发板,74HC138、74HC595模块,MATRIX-8*8绿色点阵屏,LM016L(LCD1602)、按钮BUTTON以及电阻RES和排阻RESPACK-8以及复位所需元器件

2.2 单片机IO口选取

如上图所示,使用了P1的0~3,5~7IO口,使用了P2全部IO口,使用了P3的0~5IO口以及复位所需IO口

2.3 硬件部分作用

(一)74HC595模块

该模块的作用是将数组内提前拟定好的数据进行输出。

SH_CP是控制数据左移位,高电平有效

ST_CP是数据输出,高电平有效

MR和OE分别是移位寄存器清零和输出使能,均为低电平有效

DS是串口输入,一次输入一位

Q0~Q7为并行输出(此处不考虑第9输出引脚)

使用过程:

1.先全部置低电平,即DS=0,SH_CP=0,ST_CP=0

2.DS置高电平,输入1,若为低电平则输入0

3.SH_CP置高电平,产生一个上升电平>2us

4.SH_CP置低电平

以上4步重复8次,即完成一个字节的传输

5.ST_CP置高电平,产生一个上升电平>2us

6.ST_CP置低电平
(二)74HC138模块

该模块的作用是选取行(列),使数据在该行(列)中输出。

A、B、C是输入端,分别代表二进制中的最低位,中间位和最高位

E1、E2、E3是使能控制端,E2,E3低电平有效,E1高电平有效

Y0~Y7是输出端,对应输入端(0~7)

(三)LED点阵模块

该模块的作用是显示输出的数据,显示名称首字母以及名称,动画等

初始点阵的上半部分引脚设为B0~B7,从B0开始从左往右,分别代表1~8列,下半引脚设为A0~A7,从A7开始从左到右分别代表1~8行,此时所有引脚均为高电平有效

将该点阵进行X翻转后,上半引脚从B7开始从左到右分别代表1~8行,下半引脚从A0开始分别代表1~8列,此时B0~7引脚低电平有效,A0~7引脚高电平有效

为了让点阵能更好的显示,对翻转后的点阵进行两次X镜像,逆转90°,再Y镜像,完成操作

(四)LCD1602模块

该模块的作用是显示模式,方便使用者查看功能

(五)按键模块

该模块的作用是切换模式,使LED点阵显示不同的内容

(六)复位模块

该模块的作用是使系统复位,从而切换其他模式

3.软件设计

先进行模块化编程

如上图所示,将整体程序分为主函数main,延时函数delay,按键模块key,显示模块led,模式模块lcd,控制模块74HC

(一)74HC模块

首先使用sbit定义相关引脚,如上图所示

定义col函数,对列进行选取,在上述点阵中从左到右分别代表1~8列,

使用switch函数,对传入的形参进行判断,若形参为1,则代表第一列,使L1,L2,L3均为0,即均为低电平,从而控制74HC138进行列的选择,如下图所示

其余7列类同

定义display显示函数,在选取好的列上显示数组中的数据

先使L4和L6置于低电平,然后将8位数据一位一位传入,传入过程要将L4置为高电平再恢复为低电平

传入一字节的数据后,将L6置为高电平,开启并行输出,一次输出该数据,将其显示到对应的列上

(二)LCD1602模块

首先使用sbit定义相关引脚,如上图所示

定义数据输出口P2

#define out P2

编写写入命令函数writecom,写入数据函数writedat,LCD初始化函数initial

以及字符串显示函数lcd_string

(三)led模块

首先使用取字摸软件将想要显示的数据转化为十六进制编码,如上图所示

在动态显示过程中,需要定义计数变量cnt以及count

使用for循环每次选取指定的8位数据,先选取列col(i+1),再使该列显示相关的数据display(tab[i+cnt]),然后使count加1,delay延时并且清屏,判断count是否大于指定数字,如果大于使cnt加1,在下次循环中显示后7位+第9位数据,如果数据已经显示到最后8位,使cnt=0,重新循环

使动画改变方向,只需要改变cnt(例共40个元素,将cnt初始化为32),使点阵一开始显示最后8位数据,在count越界后使cnt减1,当cnt<0时,重新初始化为32

(四)key模块

通过控制按钮改变点阵中所显示的内容

首先使用sbit定义相关引脚,如上图所示

不断扫描是否有按键按下,若有按键按下,则该引脚变为低电平,对其进行消除抖动,并判断是否松开,若松开,进行二次消除抖动,并传回相关按键的值

(五)delay模块

编写能够延时1ms的函数

(六)main模块

首先对初始化LCD1602,然后显示相关的字符串

在循环中不断扫描key的按键值,不同的按键值代表点阵显示不同的模式,每个模式点阵都会显示不同的内容,LCD1602会显示是模式几

4.源程序代码

(一)main模块

#include <reg52.h>
#include "74HC.h"
#include "delay.h"
#include "key.h"
#include "led.h"
#include "lcd1602.h"
#define uchar unsigned char
#define uint unsigned int
uchar KeyNum;
void main(){
    initlcd();
    lcd_string(0x85,"PROJECT2");
    lcd_string(0xC0,"WELCOME");
    while(1){
        KeyNum=key();
        if(KeyNum==1){
            while(1){
                lcd_string(0xC8,"mode A");
                fun();
            }
        }
        else if(KeyNum==2){
            while(1){
                lcd_string(0xC8,"mode B");
                fun2();
            }
        }
        else if(KeyNum==3){
            while(1){
                lcd_string(0xC8,"mode C");
                fun3();
            }
        }
        else if(KeyNum==4){
            while(1){
                lcd_string(0xC8,"mode D");
                fun4();
            }
        }
    }
}
(二)delay模块
#define uchar unsigned char
#define uint unsigned int
void delay(uint x){
	uchar i,j;
	while(x--){
		i=2;
		j=239;
		do{
			while(--j);
		}while(--i);
	}
}
(三)key模块
#include <reg52.h>
#include "delay.h"
#define uchar unsigned char
#define uint unsigned int
sbit K0=P1^0;
sbit K1=P1^1;
sbit K2=P1^2;
sbit K3=P1^3;
uchar key(){
	uchar KeyNumber=0;
	if(K0==0){delay(20);while(K0==0);delay(20);KeyNumber=1;}
	if(K1==0){delay(20);while(K1==0);delay(20);KeyNumber=2;}
	if(K2==0){delay(20);while(K2==0);delay(20);KeyNumber=3;}
	if(K3==0){delay(20);while(K3==0);delay(20);KeyNumber=4;}	
	return KeyNumber;
}
(四)LED模块
#include <reg52.h>
#include "74HC.h"
#include "delay.h"
#define uchar unsigned char
#define uint unsigned int
uchar cnt1,cnt2;
uchar tabA[]={
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0xFF,0x01,0x01,0x01,0x01,0x01,0x01,0x00,
	0x00,0x80,0x40,0x20,0x1F,0x20,0x40,0x80,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
uchar tabC[]={
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x54,0x6E,0xFB,0x6C,0x54,0x40,0x01,0x0F,
	0xE2,0xBE,0xEB,0x0D,0x55,0xF9,0x95,0x05,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
void fun(uchar a){
	uchar i;
	uchar cnt,count;
	while(1){
		for(i=0;i<8;i++){
			col(i+1);
			display(tabA[i+cnt]);
			count++;
			delay(4);
			display(0);         //清屏
			if(count>22){
				count=0;
				cnt++;
				if(cnt>32){
				cnt=0;
				}
			}
		}
	}
}
void fun2(uchar a){
	uchar i;
	uchar cnt,count;
	while(1){
		for(i=0;i<8;i++){
			col(i+1);
			display(tabC[i+cnt]);
			count++;
			delay(4);
			display(0);         //清屏
			if(count>22){
				count=0;
				cnt++;
				if(cnt>32){
				cnt=0;
				}
			}
		}
	}
}
void fun3(uchar a){
	uchar i;
	uchar cnt=32,count;
	while(1){
		for(i=0;i<8;i++){
			col(i+1);
			display(tabA[i+cnt]);
			count++;
			delay(4);
			display(0);         //清屏
			if(count>22){
				count=0;
				cnt--;
				if(cnt<0){
				cnt=32;
				}
			}
		}
	}
}
void fun4(uchar a){
	uchar i;
	uchar cnt=32,count;
	while(1){
		for(i=0;i<8;i++){
			col(i+1);
			display(tabC[i+cnt]);
			count++;
			delay(4);
			display(0);         //清屏
			if(count>22){
				count=0;
				cnt--;
				if(cnt<0){
				cnt=32;
				}
			}
		}
	}
}
(五)LCD模块
#include <reg52.h>
#include <intrins.h>
#include "delay.h"
#define uchar unsigned char
#define uint unsigned int
#define out P2
sbit RS=P3^3;
sbit RW=P3^4;
sbit E=P3^5;
//有重复功能函数,选取部分函数即可
void writedat(unsigned char dat){
	RS=1;
	RW=0;
	E=0;
	P2=dat;
	delay(5);
	E=1;
	E=0;
}
void writecom(unsigned char com){
	RS=0;
	RW=0;
	E=0;
	P2=com;
	delay(5);
	E=1;
	E=0;
}
void initlcd(){
	writecom(0x38);
	writecom(0x0c);
	writecom(0x06);
	writecom(0x01);
}
void check_busy(){
	uchar dt;
	do{
	dt=0xff;
	E=0;
	RS=0;
	RW=1;
	E=1;
	dt=out;
	}while(dt&0x80);
	E=0;
}
void write_data(uchar dat){
	check_busy();
	E=0;
	RS=1;
	RW=0;
	out=dat;
	E=1;
	_nop_();
	E=0;
	delay(1);
}
void write_command(uchar com){
	check_busy();
	E=0;
	RS=0;
	RW=0;
	out=com;
	E=1;
	_nop_();
	E=0;
	delay(1);
}
void lcd_initial(){
	write_command(0x38);
	write_command(0x0C);
	write_command(0x05);
	write_command(0x01);
}
void lcd_string(uchar ad,uchar *s){
	write_command(ad);
	while(*s>0){
		write_data(*s++);
		delay(100);
	}
}
void LCD_WriteData(unsigned char dat){
 RS=1;
 RW=0;
 out=dat;
 E=1;
 delay(5);
 E=0;
 delay(5);
}
void LCD_WriteCommand(unsigned char com){
 RS=0;
 RW=0;
 out=com;
 E=1;
 delay(5);
 E=0; 
 delay(5);
}
void LCD_SetCursor(unsigned char Line,unsigned char Column){
 LCD_WriteCommand(Line==1?0x80+(Column-1):0x80+(Column-1+0x40));
}
void LCD_ShowString(uchar Line,uchar Column,char *String){
	uchar i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
	{
		LCD_WriteData(String[i]);
	}
}
(六)74HC模块
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit L1=P3^0;
sbit L2=P3^1;
sbit L3=P3^2;
sbit L5=P1^5;
sbit L4=P1^6;
sbit L6=P1^7;
void wrong(uint i){
	if(i)
	P0=0xFF;
}
//注意col函数取的是列
void col(uchar i){
	switch(i){
		case 1:{
			L1=1;
			L2=1;
			L3=1;
		}break;
		case 2:{
			L1=0;
			L2=1;
			L3=1;
		}break;
		case 3:{
			L1=1;
			L2=0;
			L3=1;
		}break;
		case 4:{
			L1=0;
			L2=0;
			L3=1;
		}break;
		case 5:{
			L1=1;
			L2=1;
			L3=0;
		}break;
		case 6:{
			L1=0;
			L2=1;
			L3=0;
		}break;
		case 7:{
			L1=1;
			L2=0;
			L3=0;
		}break;
		case 8:{
			L1=0;
			L2=0;
			L3=0;
		}break;
		default:wrong(1);break;
	}
}
void display(uchar a){
	uint i;
	L4=L6=0;
	for(i=0;i<8;i++){
	L5=a>>7;
	a<<=1;
	L4=1;
	_nop_();
	_nop_();
	L4=0;
	}
	L6=1;
	_nop_();
	_nop_();
	L6=0;
}

至此,我们已经基本完成了整个项目,.h文件自然不必多说,相信各位读者的能力。

相信大家对点阵的使用更加熟练,也更多的了解到了AT89C52单片机,欢迎各位一起讨论和交流。

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值