(整理)LED点阵书写显示屏.

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

LED点阵显示屏的设计
摘要
本设计是基于16 ×16 点阵 LED 电子显示屏的设计。

设计以STC89C52RC 为核心,介绍了以它为控制系统的LED 点阵电子显示屏的动态设计和开发过程。

本设计主要模块组成:主控CPU模块、按键输入模块,光笔检测电路,LCD信息显示器,16 ×16 点阵 LED点阵显示与驱动模块。

设计中16 ×16 点阵 LED点阵显示与驱动模块中,CPU输出信号先经74HC245进行锁存,再输出信号经由38译码器74HC138译码选通APM4953驱动行,由移位寄存器74HC595作为列驱动,单片机控制系统程序采用C语言进行模块化编程,控制各显示点对应 LED 阳极和阴极端的电平,就可以有效的控制各显示点的亮灭。

文中详细介绍了 LED 点阵显示的硬件设计思路、硬件电路各个部分的功能及原理、相应软件的程序设计,以及使用说明等。

所显示字符的点阵数据可以自行编写(即直接点阵画图),也可从标准字库中提取。

经实践证明,该系统显示误差小,性能稳定,结构合理,扩展能力强。

关键词: STC89C52单片机; LED ;点阵书写显示;动态显示; C语言。

一、技术指标
1.1设计意义
LED显示屏是一种通过控制半导体发光二极管的显示方式,用来显示文字、图形、图像、
动画、行情、视频、录像信号等各种信息的显示屏幕。

图文显示屏可与计算机同步显示汉字、英文文本和图形;视频显示屏采用微型计算机进行控制,图文、图像并茂,以实时、同步、清晰的信息传播方式播放各种信息,还可显示二维、三维动画、录像、电视、VCD节目以及现场实况。

LED显示屏显示画面色彩鲜艳,立体感强,静如油画,动如电影,广泛应用于车站、码头、机场、商场、医院、宾馆、银行、证券市场、建筑市场、拍卖行、工业企业管理和其它公共场所。

本设计基于LED点阵的普通显示效果加上光笔检测模块,实现自由书写显示功能。

它的优点:亮度高、工作电压低、功耗小、微型化、易与集成电路匹配、驱动简单、寿命长、耐冲击、性能稳定。

1.2 功能实现
(1)在“点亮”功能下,当光笔接触屏上某点LED时,能即时点亮该点LED,并在控制器上同步显示该点LED的行列坐标值(左上角定为行列坐标原点)。

(2)在“划亮”功能下,当光笔在屏上快速划过时,能同步点亮划过的各点LED,其速度要求2s内能划过并点亮20点LED。

(3)在“反显”功能下,能对屏上显示的信息实现反相显示(即:字体笔画处不亮,无笔画处高亮)。

(4)在“整屏擦除”功能下,能实现对屏上所显示信息的整屏擦除。

(5)自定义显示字符。

二、方案论证
2.1 主控CPU的选择与比较
1、STM 32(STM32F103VCT6):具有多功能定时器,低功耗,速度高,256KHz嵌入式闪存寄存器,稳定性强等特点,具有最高72MHz的CPU工作频率和很强的控制和运算能力,能够实现点阵屏的高速扫描的一些复杂的控制和运算功能。

但相比于STC89C58其功能实现复杂。

2、CPLD(EPM240T100C5):具有丰富的I/O口、内部逻辑和连线资源、运行速度快、能够显示大量的信息,但CPLD实现运算功能复杂,在该系统中,需要显示的信息量较少,但是控制和运算功能较多,用CPLD实现一些运算功能复杂。

3、STC89C52:CPU采用低成本、多功能的STC89C52单片机。

STC89C52是一种低功耗、高性能CMOS 8位微控制器,具有以下标准功能: 8k字节Flash,512字节RAM, 32 位I/O 口线,看门狗定时器,内置4KB EEPROM,MAX810复位电路,3个16 位定时器/计数器,4个外部中断,一个7向量4级中断结构(兼容传统51的5向量2级中断结构),全双工串行口。

该单片机性价比
很高,且相对容易控制,基本能够实现所需功能。

经比较,选择STC89C52作为主控芯片。

2.2 光笔检测的选择与比较
1、光敏电阻:光谱响应范围宽,体积小,但灵敏度低,响应速度慢,受温度影响大,很难确
定点亮点坐标。

2、光敏二极管(2CU2B ):光电流小,响应时间短,使用于要求光电流与照度成线性关系或要求工作频率高的电路,但其灵敏度较低,光电流较小,不易判断所在处LED 在点阵屏中的坐标。

光敏三极管(3DU35C ):光电流大,响应时间短,且其灵敏度非常高,易判断所在处LED 在点阵屏中的坐标。

经比较,选择光敏三极管作为光笔检测敏感器件。

2.3 LCD 显示屏的选择
考虑到有系统低功耗的要求,采用价格低廉的1602液晶作为显示。

LCD 功耗比较低,不需要循环扫描,且信息量大,能灵活多变的显示多种信息。

2.4 键盘输入模块的选择
键盘采用4×4标准矩阵键盘,用8个I/O 口控制16个键,4个I/O 口接4行,另外4个接4列,通过行列扫描获得按键值。

2.5 16×16点阵屏模块的选择
由4块8×8单色LED 点阵(红色)模块组合成16×16的LED 点阵屏。

用红外光电三极管自制光笔。

在检测时依次点亮红色LED ,当点亮到某个LED 时,如果此时光笔放在该LED 时,这时红外光电三极管的阻值会发生变化,通过相应的检测电路可以得出一个高低电平的变化,单片机检测到信号变化时就可以判断光笔的当前位置。

该方案简单易行,对光笔位置判断的灵敏度较高,抗外界干扰能力强。

采用红色点阵和红外光电三极管能够有效地减少环境可见光对光笔中光电三极管的干扰。

三、系统简述
本设计主要模块组成:主控CPU 模块、按键输入模块,光笔检测电路,LCD 信息显示器,16 ×16 点阵 LED 点阵显示与驱动模块。

使用具有价廉易购的STC89C52单片机编程控制,通过修改程序可方便实现系统升级。

系统的框图结构如下:
四、硬件设计
LCD 信息显示器
按键输入模块
16×16点阵LED 显示与驱动模块
光笔检测电路
主控
CPU 模块
图1 系统原理框图
系统主要部件包括8×8的LED点阵屏、STC89C52RC单片机、方向可控的八路缓冲器
74HC245、38译码器74HC138、P沟道的增强型场效应管APM4953、移位寄存器74HC595、液晶显示器1602,双电压比较器LM393,光敏三极管3DU5C。

辅助元件包括电阻、电容、晶振、电源、按键等。

4.1 系统各器件简介
4.1.1 STC89C52RC单片机
STC89C52RC单片机是宏晶科技推出的新一代高速/低功耗/超强抗干扰的单片机,指令代码完全兼容传统8051单片机,12时钟/机器周期和6时钟/机器周期可以任意选择。

图STC89C52RC引脚图
STC89C52RC引脚功能说明
VCC(40引脚):电源电压
VSS(20引脚):接地
P0端口(P0.0~P0.7,39~32引脚):P0口是一个漏极开路的8位双向I/O口。

作为输出端口,每个引脚能驱动8个TTL负载,对端口P0写入“1”时,可以作为高阻抗输入。

在访问外部程序和数据存储器时,P0口也可以提供低8位地址和8位数据的复用总线。

此时,P0口内部上拉电阻有效。

在Flash ROM编程时,P0端口接收指令字节;而在校验程序时,则输出指令字节。

验证时,要求外接上拉电阻。

P1端口(P1.0~P1.7,1~8引脚):P1口是一个带内部上拉电阻的8位双向I/O口。

P1的输出缓冲器可驱动(吸收或者输出电流方式)4个TTL输入。

对端口写入1时,通过内部的上拉电阻把端口拉到高电位,这是可用作输入口。

P1口作输入口使用时,因为有内部上拉
电阻,那些被外部拉低的引脚会输出一个电流()。

P2端口(P2.0~P2.7,21~28引脚):P2口是一个带内部上拉电阻的8位双向I/O端口。

P2的输出缓冲器可以驱动(吸收或输出电流方式)4个TTL输入。

对端口写入1时,通过内部的上拉电阻把端口拉到高电平,这时可用作输入口。

P2作为输入口使用时,因为有内部的
上拉电阻,那些被外部信号拉低的引脚会输出一个电流()。

在对Flash ROM编程和程序校验期间,P2也接收高位地址和一些控制信号。

P3端口(P3.0~P3.7,10~17引脚):P3是一个带内部上拉电阻的8位双向I/O端口。

P3的输出缓冲器可驱动(吸收或输出电流方式)4个TTL输入。

对端口写入1时,通过内部的上拉电阻把端口拉到高电位,这时可用作输入口。

P3做输入口使用时,因为有内部的上拉
电阻,那些被外部信号拉低的引脚会输入一个电流()。

在对Flash ROM编程或程序校验时,P3还接收一些控制信号。

P3口除作为一般I/O口外,还有其他一些复用功能,如下表所示:
P3口引脚复用功能
引脚号复用功能
P3.0 RXD(串行输入口)
P3.1 TXD(串行输出口)
P3.2 (外部中断0)
P3.3 (外部中断1)
P3.4 T0(定时器0的外部输入)
P3.5 T1(定时器1的外部输入)
P3.6 (外部数据存储器写选通)
P3.7 (外部数据存储器读选通)
XTAL1(19引脚):振荡器反相放大器和内部时钟发生电路的输入端。

XTAL2(18引脚):振荡器反相放大器的输入端。

4.1.2 方向可控的八路缓冲器74HC245
总线收发器,典型的CMOS型三态缓冲门电路。

由于单片机或CPU的数据/地址/控制总线端口都有一定的负载能力,如果负载超过其负载能力,一般应加驱动器。

主要用于实现数据总线的双向异步通信。

为了保护脆弱的主控芯片,通常在主控芯片的并行
接口与外部受控设备的并行接口间添加缓冲器。

当主控芯片与受控设备之间需要实现双向异步通信时,自然就得选用双向的八路缓冲器了,245就是面向这种需求的。

常见于同并口液晶屏、并口打印机、并口传感器或通讯模块等设备的接口上。

图3 74HC595引脚图
引脚定义:
第1脚DIR,为输入输出端口转换用,DIR=“1”高电平时信号由“A”端输入“B”端输出,DIR=“0”低电平时信号由“B”端输入“A”端输出。

第2~9脚“A”信号输入输出端,A0=B0,A7=B7,A0与B0是一组,如果DIR=“1”OE=“0”则A1输入B1输出,其它类同。

如果DIR=“0”OE=“0”则B1输入A1输出,其它类同。

第11~18脚“B”信号输入输出端,功能与“A”端一样,不再描述。

第19脚OE,使能端,若该脚为“1”A/B端的信号将不导通,只有为“0”时A/B端才被启用,该脚也就是起到开关的作用。

第10脚GND,电源地。

第20脚VCC,电源正极。

真值表
控制输入运行
G DIR
L L B 数据到A 总线
L H A 数据到B 总线
H X 隔开
H=高电平 L=低电平×=不定
4.1.3 38译码器74HC138
74HC138是一款高速CMOS器件,74HC138引脚兼容低功耗肖特基TTL(LSTTL)系列。

可接受3
位二进制加权地址输入(A0, A1和A2),并当使能时,提供8个互斥的低有效输出(Y0至Y7)。

74HC138特有3个使能输入端:两个低有效(E1和E2)和一个高有效(E3)。

除非E1和E2置低且E3置高,否则74HC138将保持所有输出为高。

图4 74HC138引脚图
4.1.4 P沟道的增强型场效应管APM4953
行驱动管,功率管。

每一显示行需要的电流是比较大的,要使用行驱动管,每片4953可以驱动2个显示行。

其内部是两个CMOS管,1、3脚VCC,2、4脚控制脚,2脚控制7、8脚的输出,4脚控制5、6脚的输出,只有当2、4脚为“0”时,7、8、5、6才会输出,否则输出为高阻状态。

图5 4953引脚图及内部结构
4.1.5 移位寄存器74HC595
74HC595是硅结构的CMOS器件,兼容低电压TTL电路。

具有8位移位寄存器和一个存储器,三态输出功能。

移位寄存器和存储器是分别的时钟。

数据在SHcp的上升沿输入到移位寄存器中,在STcp的上升沿输入到存储寄存器中去。

如果两个时钟连在一起,则移位寄存器总是比存储寄存器早一个脉冲。

移位寄存器有一个串行移位输入(Ds),和一个串行输出(Q7’),和一个异步的低电平复位,存储寄存器有一个并行8位的,具备三态的总线输出,当使能OE
时(为低电平),存储寄存器的数据输出到总线。

8位串行输入/输出或者并行输出移位寄存器,具有高阻关断三态。

图6 74HC595引脚图
表2 74HC595功能表
输入输出功能
SHCP STCP OE MR DS Q7’Qn
××L ↓×L NC MR为低电平时仅仅影响移位寄存器
×↑L L ×L L 空移位寄存器到输出寄存器
××H L ×L Z 清空移位寄存器,并行输出为高阻状态
↑×L H H Q6 NC 逻辑高电平移入移位寄存器状态0,包含所有的移位寄存器状态移入
×↑L H ×NC Qn’移位寄存器的内容到达保持寄存器并从并口输出
↑↑L H ×Q6’Qn’移位寄存器内容移入,先前的移位寄存器的内容到达保持寄存器并出
4.1.6 液晶显示器1602
液晶显示器以其微功耗、体积小、显示内容丰富、超薄轻巧的诸多优点,在各类仪表和低功耗系统中得到广泛的应用。

功能:位数多,可显示32位;显示内容丰富,可显示所有数字和大、小写字母;程序简单,如果用数码管动态显示,会占用很多时间来刷新显示,而1602自动完成此功能。

4.1.7 双电压比较器LM393
LM393 是双电压比较器集成电路。

该电路的特点如下:工作温度范围:0°C -- +70°C;工作电源电压范围宽,单电源、双电源均可工作,单电源:2~36V,双电源:±1~±18V;消耗电流小, ICC=0.8mA;输入失调电压小, VIO=±2mV;共模输入电压范围宽, VIC=0~VCC-1.5V;输出与TTL,DTL,MOS,CMOS 等兼容;输出可以用开路集电极连接“或”门。

图7 LM393内部结构图
4.1.8 硅光敏三极管3DU5C
结构:NPN扩散型光敏三极管是具有放大能力的光电转换三极管,广泛应用与各种高空电路中。

在无光照射时,光敏三极管处于截止状态,无电信号输出。

当有光信号照射其基极(受光窗口)时,光敏三极管导通,从发射极或集电极输出放大后的电信号。

其主要技术参数为:
反向击穿电压:15V;
最高工作电压:10V;
暗电流:0.3uA;
光电流:0.5—1mA;
功耗:30mW;
峰值波长:880nm。

图8 光敏三极管等效电路
4.2各部分电路设计
4.2.1 主控模块
主控模块包括LCD液晶显示,键盘扫描模块及CPU控制模块。

通过通过编程,当按下相应按键时,LCD模块实现相应功能及LED扫描点坐标的显示。

控制模块有晶振电路及复位电路构成。

图9
4.2.2 LED点阵显示模块
LED模块为本设计的主要模块。

由锁存器、行驱动及列驱动组成。

其中,所有了LED灯驱动信号由控制模块P2口送出,经锁存器74HC245锁存再送至4块移位寄存器74HC595的4个公共控制端,驱动列;锁存器的另外三个输出接至38译码器74HC138,经译码后的信号通过P沟道的增强型场效应管APM4953驱动相应的行。

图10
4.2.3 光笔模块
光笔模块主要由光敏三极管3DU5C及电压比较器LM393组成。

用红外光电三极管自制光笔,光笔检测电路如图所示。

图中Q1是用红外光电三极管,用来完成对16×16点阵红色LED灯点亮或熄灭的检测;R4、R6用于对Q2进行限流,另外还可以调节R6来提高或减小输出的电压值;R1、R3是用于给U1(比较器)的同相端提供基准电压值,通过它跟采集信息输出来的电压值进行比较(U2>U3,Uout=Umin),R2是U1的输出上拉电阻。

工作原理如下:当红光照到红外光电三极管上时,红外光电三极管的电阻变小,其射极电压升高,此时2脚电压比3脚电压高,比较器1端输出为低电平。

当电容C1充电一段时间之后,比较器2脚电压比3脚电压低,比较器1端输出为高电平。

由此,当检测到光信号时,该电路将产生一个脉冲信号。

由于在电路中加了耦合电容,可有效地防止环境对光笔的影响。

图11
五、软件设计
程序采用模块化编程方式,分为主程序,按键扫描程序,LED扫描程序,LCD1602液晶显示程序,延时程序,点亮模式程序,反显模式程序,整屏擦除及显示自定义字符程序。

5.1 主程序
主程序中主要执行键盘扫描程序。

5.2 键盘扫描程序
在键盘扫描程序中进行键盘扫描,当键盘扫描到某个按键按下时,1602显示相应功能模式,同时对应模式的LED点阵执行相应功能。

5.3 1602液晶显示程序
主要为液晶的初始化,及定义相关模式显示。

5.4 延时程序
将所有全局变量及数组的定义全都放在这个.h文件中,同时定义50us延时和50ms延时。

5.5 点亮模式程序
按行逐列扫描(即点亮),当光笔检测到信号时,停止扫描,根据具体功能将此时的点延时显示相应时间(控制扫描速度),并将此点的行列值赋给全局变量x1、x2,用于1602中的坐标显示。

5.6 画线模式程序
检测信号方式同点亮模式。

此模式中点显示为50ms,实现快速扫描的要求。

先定义4个全局数组liea[],lieb[],liec[],lied[]保存列值,初值全设为0xff(即相应列灭),当扫描
到信号时,将扫描到的点赋给相应的全局数组(即检测到的信号保存在这四个数值中)。

此程序用用定时器中断来计时检测光笔信号,进入中断时开始计时count0,当光笔检测到信号时,计时count0清零(即光笔画线为完成),否则当count0计时到100(即5秒,表明光笔已完成画线)时显示检测到的信号,延时显示3s,只有当键盘检测到整屏擦除功能按键按下时才结束并清除检测到的信号以便下一次的画线。

5.7 整屏擦除模式程序
当键盘检测到整屏擦除功能按键按下时清除画线模式下检测检测到的信号并显示“NO”。

5.8 反显模式程序
在画线模式下,将检测到的信号点反显。

5.9 自定义字符显示程序
相应键按下时显示相应字符。

六、安装调试
将本电路用硬件做出来,用编程器将KEIL软件对源程序编译生成的.HEX文件烧入52单片机,将单片机插入到目标板中,连好线。

在各模式下,基本能实现相应功能,光笔检测到信号时1602实时显示亮点坐标。

测试结果表明,本系统实现了预期功能。

附录1 程序流程图
图12 主程序流程图
附录2 源程序
//************** .h头文件 ******************************* //LED点阵书写显示屏
////////////1.延时//////////////////////////////
//将所有全局变量及数组的定义全都放在这个.h文件中
#ifndef __DELAY_H__
#define __DELAY_H__
#define uchar unsigned char
#define uint unsigned int
extern uchar x1,x2; //行列坐标点
extern uchar keyx; //用于判断键盘是否有按下,在超时关显示用
extern uchar code dot[]; //保存哪一列亮,作扫描用
extern uchar liea[]; //保存扫描到的列,作显示用
extern uchar lieb[];
extern uchar liec[];
extern uchar lied[];
void delay_50us(uint t);
void delay_50ms(uint t);
#endif
//////////////2.LCD1602//////////////////////
#ifndef __LCD1602_H__
#define __LCD1602_H__
#include "delay.h"
#define lcd P1 //2.lcd模块
sbit rs=P2^3;
sbit rw=P3^2;
sbit elcd=P3^3;
void init(void); //lcd初始化函数
void wr_1602com(uchar com); //1602写指令函数
void wr_1602dat(uchar dat); //1602写数据函数
#endif
/////////////////3.LED//////////////////////////////
#ifndef __LED_H__
#define __LED_H__
#include "delay.h"
sbit aled=P2^0;
sbit bled=P2^1;
sbit cled=P2^2;
sbit ser=P2^4;
sbit srclk=P2^5;
sbit eled=P2^6;
sbit rclk=P2^7;
sbit gb=P3^7;
void display_595();//送显示
void wr_595(uchar);//写数据
void ledscan1(void);
#endif
//////////////////4.键盘/////////////////////////
#ifndef __KEYBOARD_H__
#define __KEYBOARD_H__
#include "delay.h"
void key_scan(void);
void xianshi(uchar *p1,uchar *p2);
void display_zb(void);
#endif
////////////整屏擦除//////////////////////////////
#ifndef __eraall_H__
#define __eraall_H__
void eraall(void);
void dis_led(uchar p[][9]);
#endif
////////////反显//////////////////////////////
#ifndef __ECHO_H__
#define __ECHO_H__
void e_cho(void);
#endif
//////////////////5.亮模式///////////////////////////// #ifndef __LIGHT_H__
#define __LIGHT_H__
#include "delay.h"
#include "led.h"
void lie0(uchar z,uchar x,uchar y);
void light(uchar k);
#endif
/////////////////延时函数////////////////////////
#include "delay.h"
void delay_50us(uint t) //延时50us函数
{
uchar j;
for(;t>0;t--)
for(j=19;j>0;j--);
}
void delay_50ms(uint t) //延时50ms函数
{
uint j;
for(;t>0;t--)
for(j=6245;j>0;j--);
}
/////////////////////lcd声明部分//////////////////////// #include <reg52.h>
#include "delay.h"
#include "lcd1602.h"
void init(void) //lcd初始化函数
{
delay_50us(30);
wr_1602com(0x38);
delay_50us(10);
wr_1602com(0x38);
delay_50us(10);
wr_1602com(0x38);
wr_1602com(0x38);
wr_1602com(0x08);
wr_1602com(0x01);
wr_1602com(0x06);
wr_1602com(0x0c);
}
void wr_1602com(uchar com) //1602写指令函数{
elcd=0;
rs=0;
rw=0;
lcd=com;
delay_50us(10);
elcd=1;
delay_50us(20);
elcd=0;
}
void wr_1602dat(uchar dat) //1602写数据函数{
elcd=0;
rs=1;
rw=0;
lcd=dat;
delay_50us(10);
elcd=1;
delay_50us(20);
elcd=0;
}
////////////LED程序////////////////////// #include <reg52.h>
#include <intrins.h>
#include "delay.h"
#include "led.h"
void wr_595(uchar dat)
{
uchar a;
for(a=8;a>0;a--)
{
srclk=0;
ser=dat&0x80;
dat<<=1;
srclk=1;
_nop_();
_nop_();
}
}
void display_595()
{
rclk=0;
_nop_();
_nop_();
rclk=1;
}
//////////////////键盘扫描模块///////////////////////////
#include <reg52.h>
#include "delay.h"
#include "lcd1602.h"
#include "keyboard.h"
#include "led.h"
#include "light.h"
#include "eraall.h"
#include "echo.h"
uchar code heart[][9]={0xff,0xff,0xff,0x8f,0x07,0x03,0x03,0x03,0xff, //显示心
0xff,0xff,0xff,0xf1,0xe0,0xc0,0xc0,0xc0,0xff,
0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff,0xff,0x03,
0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,0xff,0xc0};
uchar code wel[][9]={0xff,0xef,0x00,0x52,0xdd,0xca,0xb7,0xfb,0xff, //显示“欢迎光临”
0xff,0xfd,0x04,0x55,0x45,0x55,0xdd,0x00,0xff,
0xef,0xab,0x01,0xd7,0xd7,0x5b,0x3d,0xff,0xef,
0xef,0x8b,0xcb,0x01,0x51,0x53,0x03,0xfb,0xef};
uchar code big[][9]={0xff,0xff,0x7f,0x7f,0x7f,0x7f,0x7f,0x03,0xff, //显示“大”字
0xff,0xff,0xfe,0xfe,0xfe,0xfe,0xfe,0xc0,0xff,
0x03,0x3f,0x9f,0xcf,0xe7,0xf3,0xff,0xff,0x03,
0xc0,0xfc,0xf9,0xf3,0xe7,0xcf,0xff,0xff,0xc0};
uchar code smile[][9]={0xff,0xff,0xff,0xe3,0xdd,0xbd,0xff,0xff,0xff, //显示笑脸
0xff,0xff,0xff,0xc7,0xbb,0xbd,0xff,0xff,0xff,
0xff,0xff,0xf7,0xf7,0xef,0xdf,0x3f,0xff,0xff,
0xff,0xff,0xef,0xef,0xf7,0xfb,0xfc,0xff,0xff};
//定义lcd显示内容
uchar code light_dot[]= "MODE1: LIGHT_DOT";//点亮模式1
uchar code light_line[]="MODE2:LIGHT_LINE";//划亮模式2
uchar code echo[] = "MODE3: ECHO ";//反显模式3
uchar code era_all[]= "MODE4: ERA_ALL ";//整屏擦除模式4
uchar code coordinate[]="Lacation:( , )";//坐标位置显示,第11,12
显示第一个坐标,第13,14显示第二个坐标
uchar code kong[]= " "; //当执行整屏擦除时,第二
行显示为空
uchar code welcome1[]= " WELCOME ";//进入时欢迎界面
uchar code welcome2[]= " LED DIANZHEN ";//进入时欢迎界面
uchar code smile1[]= " SMILE "; //显示笑脸
uchar code big1[]= " BIG "; //显示“大”
uchar code heart1[]= " HEART "; //显示心
uchar code wel1[]= " WELCOME "; //显示“欢迎光临”
uchar code zuobiao[]= "01020304050607080910111213141516";
void key_scan(void)
{
uchar key_l,key_h; //行值及列值,列为高四位,行为低四位
uchar key; //真正的键值
P0=0xf0;
key_l=P0;
key_l=key_l&0xf0;
if(key_l!=0xf0)
{
delay_50us(100); //消抖
if(key_l!=0xf0) //1110 0000
{
key_l=P0&0xf0; //再读一次键值
key_l=key_l|0x0f;//1110 1111
P0=key_l; //P0口输出
key_h=P0; //读P3口
key_h=key_h&0x0f;//0000 1110,屏蔽高四位
key_l=key_l&0xf0;//1110 0000
key=key_l+key_h;
keyx=key;
}
}
//检测到某一个按键按下的时候lcd执行相应的功能,同时当光笔有扫描到信号时,显示相应内容
switch (key)
{
case 0xee:
light(20);
xianshi(light_dot,coordinate);
break;
case 0xed:
light(1);
xianshi(light_line,coordinate);
break;
case 0xeb:
e_cho();
xianshi(echo,coordinate);
break;
case 0xe7:
eraall();
xianshi(era_all,kong);
break;//按键1~4
case 0xde:
dis_led(smile);
xianshi(smile1,kong);
break;
case 0xdd:
dis_led(big);
xianshi(big1,kong);
break;
case 0xdb:
dis_led(heart);
xianshi(heart1,kong);
break;
case 0xd7:
dis_led(wel);
// xianshi(wel1,kong);
break;//按键5~8
/* case 0xbe: ;break;
case 0xbd: ;break;
case 0xbb: ;break;
case 0xb7: ;break;//按键9~12
case 0x7e: ;break;
case 0x7d: ;break;
case 0x7b: ;break;
case 0x77: ;break;//按键13~16 */ //功能扩展default: eled=1;
xianshi(welcome1,welcome2);
break;
}
}
void xianshi(uchar *p1,uchar *p2)
{
uchar k;
wr_1602com(0x80);
for(k=0;k<16;k++)
wr_1602dat(*p1++);
wr_1602com(0x80+0x40);
for(k=0;k<16;k++)
wr_1602dat(*p2++);
}
void display_zb(void)
{
if(x2<16)
{
wr_1602com(0x80+0x40+10); //显示行坐标
wr_1602dat(zuobiao[2*x1]);
wr_1602com(0x80+0x40+11);
wr_1602dat(zuobiao[2*x1+1]);
wr_1602com(0x80+0x40+13); //显示列坐标
wr_1602dat(zuobiao[2*x2]);
wr_1602com(0x80+0x40+14);
wr_1602dat(zuobiao[2*x2+1]);
}
else
{
wr_1602com(0x80+0x40+10); //显示行坐标
wr_1602dat(zuobiao[2*x1+16]);
wr_1602com(0x80+0x40+11);
wr_1602dat(zuobiao[2*x1+17]);
wr_1602com(0x80+0x40+13); //显示列坐标
wr_1602dat(zuobiao[2*(x2-16)]);
wr_1602com(0x80+0x40+14);
wr_1602dat(zuobiao[2*(x2-16)+1]);
}
}
//////////////整屏擦除/////////////////////////
//在划亮及写字模式下,当有按键按下时,擦除lie[][8]数组中保存的内容,
并显示LED三个字母
#include <reg52.h>
#include "delay.h"
#include "led.h"
#include "eraall.h"
#include "keyboard.h"
uchar code no[][9]={0x7f,0x3f,0x5f,0x6f,0x77,0x7b,0x7d,0x7e,0x7f, //显示“NO”
0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe,0xc3,0xbf,
0xff,0xff,0x7f,0xbf,0xdf,0xdf,0x3f,0xff,0xff,
0xbd,0xbe,0xbf,0xdf,0xef,0xf7,0xf8,0xff,0xbd};
//将之前定义的列显示全部清除,并在屏幕上显示“NO”
void eraall(void)
{
uchar j=0;
for(j=0;j<8;j++)
{
liea[j]=0xff;
lieb[j]=0xff;
liec[j]=0xff;
lied[j]=0xff;
}
dis_led(no);
}
void dis_led(uchar p[][9])
{
uchar i;
for(i=0;i<8;i++)
{
eled=0;
P2=i;
display_595();
wr_595(p[3][i+1]);//第四块
wr_595(p[2][i+1]);//第三块
wr_595(p[1][i+1]);//第二块
wr_595(p[0][i+1]);//第一块
delay_50us(100);
}
}
//////////////////////////反显//////////////////////// //在写字功能下实现反显功能
#include <reg52.h>
#include "echo.h"
#include "delay.h"
#include "led.h"
void e_cho()
{
uchar j;
eled=0;
for(j=0;j<8;j++) //第j列亮
{
eled=0;
P2=j;
wr_595(~lied[j]);//第四块
wr_595(~liec[j]);//第三块
wr_595(~lieb[j]);//第二块
wr_595(~liea[j]);//第一块
display_595();
delay_50us(100);
}
}
////////////////画线模式////////////////////////
#include<reg52.h>
#include<intrins.h>
#include "delay.h"
#include "led.h"
#include "lightdot.h"
#include "keyboard.h"
#include "light.h"
#define count 50000 //定时器0用于超时关显示mode1工作方式
#define TH0_M1 (65535-count)/256
#define TL0_M1 (65535-count)%256
uchar count0=0;
uchar i,j;
sbit ass=P3^6;
void light(uchar k)
{
eled=1;
gb=1;
//进行逐行逐列扫描,当光笔检测到信号是,将检测到的点赋给全局数组进行
保存
for(i=0;i<8;i++)
{
for(j=0;j<=7;j++)
{
lie0(j,i,dot[j]);
while(gb==0)
{
liea[i]&=dot[j];
lie0(j,i,dot[j]);
x1=i;
x2=j;
display_zb();
delay_50ms(k);
break;
}
}
while(gb==0)
break;
for(j=8;j<=15;j++)
{
lie0(j,i,dot[j]);
while(gb==0)
{
lieb[i]&=dot[j];
lie0(j,i,dot[j]);
x1=i;
x2=j;
display_zb();
delay_50ms(k);
break;
}
}
for(j=16;j<=23;j++)
{
lie0(j,i,dot[j]);
while(gb==0)
{
liec[i]&=dot[j];
lie0(j,i,dot[j]);
x1=i;
x2=j;
display_zb();
delay_50ms(k);
break;
}
}
while(gb==0)
break;
for(j=24;j<=31;j++)
{
lie0(j,i,dot[j]);
while(gb==0)
{
lied[i]&=dot[j];
lie0(j,i,dot[j]);
x1=i;
x2=j;
display_zb();
delay_50ms(k);
break;
}
}
}
}
}
//用定时器中断来计时检测光笔信号,进入中断时开始计时count0,当光笔检测到信号时,
//计时count0清零,否则当count0计时到60(即3秒)时显示检测到的信号。

void timer0(void) interrupt 1
{
TH0=TH0_M1;TL0=TL0_M1;
count0+=1;
if(gb==0)
count0=0;
else if(count0==60)
{
count0=0;
for(j=0;j<8;j++)
{
eled=0;
P2=j;
wr_595(lied[j]);//第四块
wr_595(liec[j]);//第三块
wr_595(lieb[j]);//第二块
wr_595(liea[j]);//第一块
display_595();
} delay_50ms(100);//延时显示5秒
}
void lie0(uchar z,uchar x,uchar y)//第4块的某列亮{
P2=x;
if(z<8)
{
wr_595(0xff);//第四块
wr_595(0xff);//第三块
wr_595(0xff);//第二块
wr_595(y);//第一块
}
else if(z<15)
{
wr_595(0xff);//第四块
wr_595(0xff);//第三块
wr_595(y);//第二块
wr_595(0xff);//第一块
}
else if(z<23)
{
wr_595(0xff);//第四块
wr_595(y);//第三块
wr_595(0xff);//第二块
wr_595(0xff);//第一块
}
else if(z<31)
{
wr_595(y);//第四块
wr_595(0xff);//第三块
wr_595(0xff);//第二块
wr_595(0xff);//第一块
}
display_595();
}
void lie0(uchar z,uchar x,uchar y)//定义哪个点被点亮{
P2=x;
if(z<8)
{
wr_595(0xff);//第四块
wr_595(0xff);//第三块
wr_595(0xff);//第二块
wr_595(y);//第一块
}
else if(z<15)
{
wr_595(0xff);//第四块
wr_595(0xff);//第三块
wr_595(y);//第二块
wr_595(0xff);//第一块
}
else if(z<23)
{
wr_595(0xff);//第四块
wr_595(y);//第三块
wr_595(0xff);//第二块
wr_595(0xff);//第一块
}
else if(z<31)
{
wr_595(y);//第四块
wr_595(0xff);//第三块
wr_595(0xff);//第二块
wr_595(0xff);//第一块
}
display_595();
}
/////////////////main函数/////////////////////
#include <reg52.h>
#include "delay.h"
#include "keyboard.h"
#include "lcd1602.h"
#include "led.h"
#include "lightdot.h"
#include "lightline.h"
uchar keyx;
uchar x1=0,x2=0;
uchar code dot[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f, //第1块 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f, //第2块/*定义某一列亮*/ 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f, //第3块 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //第4块
uchar liea[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; //保存列,定义一个数组,保存光笔点亮的点
uchar lieb[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
uchar liec[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
uchar lied[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
main()
{
init();
while(1)
{
key_scan();
}
}
参考文献
[1] 张义和,王敏男,许宏昌,余长春.例说51单片机.北京:人民邮电出版社,2011
[2]郁有文,常建,程继红.传感器原理及工程应用.江苏:西安电子科技大学出版社,2008
[3]靳栀,邬芝权,李骐,刘全.基于51系列单片机的LED显示屏开发技术.北京:北京航空
航天大学出版社,2011
[4] 王化详,张淑英.传感器原理.天津:天津大学出版社,2002
[5] 胡汉才.单片机原理及其接口技术.北京:清华大学出版社,2004。

相关文档
最新文档