前言 2
第1章 理论分析及总体方案 3
第1.1节 方案比较 3
第1.2节 总体设计方案 4
第2章 系统的硬件设计 6
第2.1节 控制电路设计 6
第2.2节 对射红外检测电路设计 11
第2.3节 液晶显示电路设计 13
第2.4节 继电器开关电路与报警电路的设计 15
第2.5节 按键电路设计 17
第3章 系统的程序设计 18
第3.1节 主程序设计 18
第3.2节 数据采集模块程序设计 19
第3.3节 液晶显示程序设计 20
第4章 系统测试 22
第4.1节 系统的硬件调试 22
第4.2节 系统的软件调试 22
第4.3节 测试及结果 22
结论 23
参考文献 23
致谢 24
附录 24
附录1:原理图及实物照片说明 25
附录2:部分源程序 25
基于单片机的停车场计数系统设计
【摘 要】以STC89C52单片机为核心,利用红外对射式传感器电路作为信号的输入模块,设计了一个基于单片机的停车场计数系统。对射式光电传感器由发射器和接收器组成,当有物体经过发射器和接收器之间阻断光线时,形成电平信号,经过放大、整流并送入单片机控制模块进行控制计数。通过液晶显示电路、继电器电路和蜂鸣器电路构成系统的输出模块,实现了对停车场内汽车数量的计数、显示、停车场进出门以及报警的控制。
【关键词】:单片机;红外对射式传感器;继电器;液晶显示;
[Abstract]: In this paper, the STC89C52 microcontroller as the core of the control circuit, the signal output module is used infrared photoelectric couple, designed a parking lot counting system that based on a microcontroller. Infrared photoelectric couple by the transmitter and the receiver is composed of two parts. When an object through the transmitter and the receiver will break the light beams, and produce level signal, amplified, rectified and finally put into microcontroller to control counting. Via Liquid Crystal Display circuit, relay circuit and buzzer circuit form the output module. So this system achieves counting of cars, display, alarm and the controller of pulling or pushing the door in the parking lot.
[Key words]: microcontroller; infrared photoelectric couple; relay; Liquid Crystal Display;
前言
在当今社会经济飞速发展的格局下,越来越多的厂家采用流水线技术进行产品生产作业,而怎样对其线上的产品进行实时的、有效率的、精确的计数成为广大生产厂家十分关注的问题。而基于单片机为核心控制的计数器有着能够实时,精确,可靠,稳定等计数优点已成为广大厂家的首选自动计数的装置。
当今,单片微型计算机技术迅速发展,基于单片机技术开发的计数设备和产品广泛应用到各个领域,单片机技术产品和设备促进了生产技术水平的提高,企业迫切需要大量熟练掌握单片机技术并能开发、应用和维护管理这些智能化产品的高级工程技术人才。单片机以体积小、功能强、可靠性高、性能价格比高等特点,已成为实现工业生产技术进步和开发机电一体化和智能化测控产品的重要手段。电子计数器是一种多功能的电子测量仪器,它利用电子学的方法测出一定时间内输入的脉冲数目,并将结果以数字形式显示出来。而基于单片机的红外线计数器能够满足广大厂家的要求,它拥有实时,精确,可靠,稳定等特点。
对射式传感器计数是一种多功能的电子测量仪器。它利用对射式传感器发射红外线,当有车辆阻挡红外线,红外线中断并转换为电脉冲,并由放大电路进行放大,通过单片机分析,计算出进出车辆的次数,通过液晶显示方式显示进出车辆数从而进行计数。随着红外技术的提高,用于存在状态的传感,位置编码极限传感,运动检测和计数(如风速仪、数控机床等)。典型应用:光栅尺、编码器、邦定机、压焊机、火花机、医疗仪器、atm取款机、自动售货机、收款机、复印机、打印机、磁带驱动、转球式鼠标、工业设备、胶片感测、邮件存在/分拣、料位监控、输送带控制、过程控制、物料的到位监控等。随着传感器的不断改进,抗干扰能力增强,可以在许多恶劣的地方代替科研人员进行科学工作。
本设计主要任务是以STC89C52单片机为核心,利用红外对射式传感器电路作为信号的输入模块进行车辆计数。基于单片机构成的车辆计数研究的主要内容包括:如对射式传感器的应用以及发展、STC89C52单片机用何种方式对外部计数脉冲进行计数显示控制、LCD显示驱动模块的选择、STC89C52单片机的扩展、74LS245如何驱动继电器与蜂鸣器工作的。
主要技术指标:
1.整个系统的抗干扰能力强
2.计数范围广:0000~9999
3.车辆计数值精确
第1章 理论分析及总体方案第1.1节 方案比较
三种不同设计方案:
方案一:如图1-1所示:
图1-1 红外线计数器硬件框图
原理阐述:专业检测芯片形成计数脉冲后送给控制单元AT89C2051单片机。
通过对它片内计数、显示编程。PS7219是专用LED显示驱动芯片可以同时驱动8个7段数码管。 X2504P是一块有电源电压监控、EEPROM 和看门狗定时器电路三种功能于一体的芯片,它保证了在电源接通、关断、瞬间电源电压不稳时,不会造成系统死机、数据误写或误动作,大大提高了系统的可靠性和抗干扰能力.HT7044A能够保证系统突然掉电后保护数据。
方案二:如图1-2所示:
图1-2 红外线计数器硬件框图
原理阐述:通过红外发射与接收对信号采集,使用了四合一芯片CL102计数控制显示,它是集译码、驱动、锁存、显示一体。
方案三:如图1-3所示:
图1-3 对射式红外传感器计数硬件框图
原理阐述:当有通过发射器发出的光线直接进入接收器,当被检测物体经过发射器和接收器之前阻断光线时,并将其放大、整流形成高电平信号送入控制单元。
方案一既可准确的实现车辆计数功能且能让系统处于异常状态和抗干扰时通过外围专用芯片得到非常好的解决。外围电路架设相对简单、在市场上属于高端计数产品,同时它也暴露出了一个重大问题:由于成本太贵的原因此类产品并没有得到普及,故虽然这个方案只有舍弃。
方案二是一个简易的产品自动计数器,价格低廉、计数精确。但在系统处于异常状态时工作十分不稳定、也是属于现在计数市场上的淘汰产品。仅用于在计数要求不高的场合中,这个方案太过于简单故不选用。
方案三便是这次毕业设计选用的方案。之所以选用主要是这个方案涉及面广、输出有效信号为低电平、可辨别不透明的反光物体、有效距离大、不易受干扰、高灵敏度、高解析、高亮度、低功耗、响应时间快、使用寿命长、无铅、应用广泛等特点。
第1.2节 总体设计方案
以STC89C52单片机为核心,利用红外对射式传感器电路作为信号的输入模块。按照设计的基本要求,可分为三个模块,即数据采集模块、控制器模块、数据显示模块。其中数据采集模块由红外对射式传感器组成,光线中断后将信号送给控制模块,由单片机完成对该信号的处理,由数据显示模块完成信息交换。在扩展功能上,本设计增加了一个继电器电路、按键电路和过载报警电路。系统设计框图,如图1-4所示:
图1-4 系统总体设计框图
第2章 系统的硬件设计第2.1节 控制电路设计2.1.1. 单片机的发展及趋势
1.CPU的改进
(1)增加CPU的数据总线宽度。例如,各种16位单片机和32位单片机,其数据处理能力要优于8位单片机。另外,8位单片机内部采用16位数据总线,其数据处理能力明显优于一般8位单片机。
(2)采用双CPU结构,以提高数据处理能力。
2.存储器的发展
(1)片内的程序存储器现在普遍采用闪速(Flash)存储器。Flash存储器能在+5V下读/写,既有静态RAM的读/写操作简便,又有在掉电时数据不会丢失的优点。使用片内Flash存储器,单片机可不用片外扩展程序存储器,大大简化了其应用系统结构。
(2)加大存储容量。目前有的单片机片内程序存储器容量可达128 KB甚至更多。
3.片内I/O的改进
(1)增加并行口的驱动能力,以减少外部驱动芯片。有的单片机可以直接输出大电流和高电压,以便能直接驱动LED和VFD(荧光显示器)。
(2)有些单片机设置了一些特殊的串行I/O功能,为构成分布式、网络化系统提供了方便条件。
4.低功耗化
8位单片机产品已CMOS化,CMOS芯片的单片机具有功耗小的优点,而且为了充分发挥低功耗。
特点,这类单片机普遍配置有等待状态、睡眠状态、关闭状态等工作方式。在这些状态下低电压工作作的单片机,其消耗的电流仅在μA或nA量级,非常适合于电池供电的便携式、手持式的仪器仪表以及其他消费类电子产品。
5.外围电路内装化
随着集成电路技术及工艺的不断发展,把所需的众多外围电路全部装入单片机内,即系统的单片化是目前单片机发展趋势之一。例如,美国Cygnal公司的C8051F020 8位单片机,内部采用流水线结构,大部分指令的完成时间为1或2个时钟周期,峰值处理能力为25MIPS。片上集成有8通道A/D、两路D/A、两路电压比较器,内置温度传感器、定时器、可编程数字交叉开关和64个通用I/O口、电源监测、看门狗、多种类型的串行接口(两个UART、SPI)等。一片芯片就是一个“测控”系统。
综上所述,单片机正在向多功能、高性能、高速度(时钟达40MHz)、低电压(2.7V即可工作)、低功耗、低价格(几元钱)、外围电路内装化以及片内程序存储器和数据存储器容量不断增大的方向发展。
2.1.2. 主控芯片简介
本设计上网主控芯片由单片机STC89C52控制完成。基本原理为当对射式红外传感器检测部分检测到有车辆经过时,红外对射传感器被中断即产生一个低电平信号,这个信号将供给单片机进行计数控制。
计数控制部分是将计数脉冲送入单片机STC89C52两个中断入口的INT0入口,经过单片机内部对这个中断信号进行计数编程。
单片机的引脚图如图2-1所示:
图2-1 STC89C52RC引脚图
主要特性如下:
1.时钟电路
STC89C52内部有一个用于构成振荡器的高增益反相放大器,引脚RXD和TXD分别是此放大器的输入端和输出端。时钟可以由内部方式产生或外部方式产生。内部方式的时钟电路如图2—2(a) 所示,在RXD和TXD引脚上外接定时元件,内部振荡器就产生自激振荡。定时元件通常采用石英晶体和电容组成的并联谐振回路。晶体振荡频率可以在1.2~12MHz之间选择,电容值在5~30pF之间选择,电容值的大小可对频率起微调的作用。
外部方式的时钟电路如图2—2(b)所示,RXD接地,TXD接外部振荡器。对外部振荡信号无特殊要求,只要求保证脉冲宽度,一般采用频率低于12MHz的方波信号。片内时钟发生器把振荡频率两分频,产生一个两相时钟P1和P2,供单片机使用。
(a)内部方式时钟电路 (b)外部方式时钟电路
图2—2时钟电路
2.复位及复位电路
(1)复位操作
复位是单片机的初始化操作。其主要功能是把PC初始化为0000H,使单片机从0000H单元开始执行程序。除了进入系统的正常初始化之外,当由于程序运行出错或操作错误使系统处于死锁状态时,为摆脱困境,也需按复位键重新启动。
除PC之外,复位操作还对其他一些寄存器有影响,它们的复位状态如表2-1所示:
表2-1 一些寄存器的复位状态
(2)复位信号及其产生
RST引脚是复位信号的输入端。复位信号是高电平有效,其有效时间应持续24个振荡周期(即二个机器周期)以上。若使用颇率为6MHz的晶振,则复位信号持续时间应超过4us才能完成复位操作。
产生复位信号的电路逻辑如图2—3所示:
图2—3复位信号的电路逻辑图
整个复位电路包括芯片内、外两部分。外部电路产生的复位信号(RST)送至施密特触发器,再由片内复位电路在每个机器周期的S5P2时刻对施密特触发器的输出进行采样,然后才得到内部复位操作所需要的信号。
复位操作有上电自动复位相按键手动复位两种方式。
上电自动复位是通过外部复位电路的电容充电来实现的,其电路如图2—4(a)所示。这佯,只要电源Vcc的上升时间不超过1ms,就可以实现自动上电复位,即接通电源就成了系统的复位初始化。
按键手动复位有电平方式和脉冲方式两种。其中,按键电平复位是通过使复位端经电阻与Vcc电源接通而实现的,其电路如图2—4(b)所示;而按键脉冲复位则是利用RC微分电路产生的正脉冲来实现的。
其电路如图2—4(c)所示:
(a)上电复位 (b)按键电平复位 (c)按键脉冲复位
图2—4复位电路
上述电路图中的电阻、电容参数适用于6MHz晶振,能保证复位信号高电平持续时间大于1个机器周期。
STC89C52具体介绍如下:
① 主电源引脚(2根)
VCC(Pin40):电源输入,接+5V电源
GND(Pin20):接地线
②外接晶振引脚(2根)
XTAL1(Pin19):片内振荡电路的输入端
XTAL2(Pin20):片内振荡电路的输出端
③控制引脚(4根)
RST/VPP(Pin9):复位引脚,引脚上出现2个机器周期的高电平将使单片机复位。
ALE/PROG(Pin30):地址锁存允许信号
PSEN(Pin29):外部存储器读选通信号
EA/VPP(Pin31):程序存储器的内外部选通,接低电平从外部程序存储器读指令,如果接高电平则从内部程序存储器读指令。
④可编程输入/输出引脚(32根)
STC89C52单片机有4组8位的可编程I/O口,分别位P0、P1、P2、P3口,每个口有8位(8根引脚),共32根。
PO口(Pin39~Pin32):8位双向I/O口线,名称为P0.0~P0.7
P1口(Pin1~Pin8):8位准双向I/O口线,名称为P1.0~P1.7
P2口(Pin21~Pin28):8位准双向I/O口线,名称为P2.0~P2.7
P3口(Pin10~Pin17):8位准双向I/O口线,名称为P3.0~P3.7
STC89C52主要功能如表2-2所示:
表2-2 STC89C52主要功能
主要功能特性
兼容MCS51指令系统
8K可反复擦写Flash ROM
32个双向I/O口
256x8bit内部RAM
3个16位可编程定时/计数器中断
时钟频率0-24MHz
2个串行中断
可编程UART串行通道
2个外部中断源
共6个中断源
2个读写中断口线
3级加密位
低功耗空闲和掉电模式
软件设置睡眠和唤醒功能
2.1.3. 单片机最小系统的设计
STC89C52单片机的最小系统设计如图2-5所示:
图2-5 单片机最小系统图
STC89C52单片机的最小系统由单片机、晶振电路、复位电路组成。其介绍如下:
(1)晶振电路为单片机提供时序使单片机能够正常工作,在图2-5中采用单片机内部振荡方式。此时,只要接上两个电容和一个晶振即可。电容的大小影响着振荡的稳定性和起振的快速性,通常选择10~30pF的相等的两个瓷片电容。
(2)C3和R1构成了复位电路。刚开始上电时时,C3瞬间相当于短路,C3两端保持0V电压,VCC的电源电压就都加在了R1上,因此在单片机9脚RST上变成了高电平,此后C3上逐渐充电,即在C3上出现电压,R1上的电压开始下降,最后单片机9脚RST上变成了低电平。在此过程中只要满足单片机9脚RST上的高电平持续24个振荡周期即可使单片机复位。
第2.2节 对射红外检测电路设计
对射红外检测电路由红外对射式传感器完成,对射式红外传感器由发射器和接收器组成,其工作原理是:通过发射器发出的光线直接进入接收器,当被检测物体经过发射器和接收器之前阻断光线时,产生电平信号,通过介质完成。对射式红外传感器的特点在于:可辨别不透明的反光物体,有效距离大,不易受干扰,高灵敏度,高解析,高亮度,低功耗,响应时间快,使用寿命长,无铅,应用广泛。当接收器接通工作电压后,发射端上的红色电源指示二极管就会点亮。接收端上有一个红色的输出状态指示LED,正常情况下接收器能持续收到发射器发出的红外信号,此时接收端上的输出状态指示LED熄灭,接收器的耗电保持在5毫安的低水平。在门开启或关闭的过程中,若意外地有行人或车辆从门间通过,则从发射器发出的红外信号被遮挡,接收器在此瞬间无法接收到该红外信号。此时,接收端上的输出状态指示LED立即被点亮,导致接收器的耗电因此而上升到15毫安,此电流变化促使接收板上的输出继电器吸合,通过接线柱输出一个闭合信号,对开门机发出停止运转的指令。
图2-6 红外对射电路
如图2-6所示,红外线发射电路以时钟定时集成芯片LM393AD为核心,可以将模拟量转化为数字量。LM393是由两个独立的、高精度电压比较器组成的集成电路,失调电压低,最大为2.0mV。它专为获得宽电压范围、单电源供电而设计,也可以以双电源供电;而且无论电源电压大小,电源消耗的电流都很低。它还有一个特性:即使是单电源供电,比较器的共模输入电压范围接近地电平。
主要应用于限幅器、简单的模/数转换器、脉冲发生器、延时发生器、宽频压控振荡器、MOS时钟计时器、多频振荡器和高电平数字逻辑门电路。393被设计成能直接连接TTL和CMOS;当用双电源供电时,它能兼容MOS逻辑电路——这是低功耗的393相较于标准比较器的独特优势。其管脚图,如图2-7所示:
管脚排列图解(顶视) 管脚排列图解(俯视)
图2-7 LM393管脚图
表2-3 管脚功能表
电源电压
管脚功能,如表2-3:
应用说明:
LM393是高增益,宽频带器件,象大多数比较器一样,如果输出端到输入端有寄生电容而产生耦合,则很容易产生振荡。这种现象仅仅出现在当比较器改变状态时,输出电压过渡的间隙。电源加旁路滤波并不能解决这个问题,标准PC板的设计对减小输入—输出寄生电容耦合是有助的。减小输入电阻至小于10K将减小反馈信号,而且增加甚至很小的正反馈量(滞回1.0~10mV)能导致快速转换,使得不可能产生由于寄生电容引起的振荡。除非利用滞后,否则直接插入IC并在引脚上加上电阻将引起输入—输出在很短的转换周期内振荡,如果输入信号是脉冲波形,并且上升和下降时间相当快,则滞回将不需要。比较器的所有没有用的引脚必须接地。
LM393偏置网络确立了其静态电流与电源电压范围 2.0~30V无关。
通常电源不需要加旁路电容。
差分输入电压可以大于Vcc并不损坏器件.保护部分必须能阻止输入电压向负端超过-0.3V。LM393的输出部分是集电极开路,发射极接地的 NPN输出晶体管,可以用多集电极输出提供。
功能:输出负载电阻能衔接在可允许电源电压范围内的任何电源电压上,不受 Vcc端电压值的限制.此输出能作为一个简单的对地SPS开路(当不用负载电阻没被运用),输出部分的陷电流被可能得到的驱动和器件的β值所限制,当达到极限电流(16mA)时,输出晶体管将退出而且输出电压将很快上升,输出饱和电压被输出晶体管大约60ohm 的γSAT限制。当负载电流很小时,输出晶体管的低失调电压(约1.0mV)允许 输出箝位在零电平。
第2.3节 液晶显示电路设计
液晶显示屏的英文名称是Liquid Crystal Display(Device),简称LCD。根据LCD所采用的材料构造,可把液晶分为TN、STN、TFT等三大类,而据目前的技术原理又可以将它们再次分为TN、STN、FSTN、DSTN、TFT等诸多类别:
LCD的特点是体积小、形状薄、重量轻、耗能少(1~10微瓦/平方厘米)、低发热、工作电压低(1.5~6伏)、无污染,无辐射、无静电感应,尤其是视域宽、显示信息量大、无闪烁,并能直接与CMOS集成电路相匹配,同时还是真正的“平板”式显示设备。这些特点正在使显示领域从传统CRT走向LCD。本设计选择的是诺基亚5110液晶显示器,其原理图如图2-8所示,各个引脚功能说明如表2-4所示:
图2-8诺基亚5110液晶显示器原理图
表2-4各个引脚功能说明
对应背光板上2个定位柱
该液晶具有以下特点:
●84x48 的点阵LCD,可以显示4 行汉字,
●采用串行接口与主处理器进行通信,接口信号线数量大幅度减少,包括电源和地在内的信号线仅有9 条。支持多种串行通信协议(如AVR 单片机的SPI、MCS51 的串口模式0等),传输速率高达4Mbps,可全速写入显示数据,无等待时间。
●可通过导电胶连接模块与印制版,而不用连接电缆,用模块上的金属钩可将模块固定到印制板上,因而非常便于安装和更换。
●LCD 控制器/驱动器芯片已绑定到LCD 晶片上,模块的体积很小。
●采用低电压供电,正常显示时的工作电流在200μA 以下,且具有掉电模式。连线图如图2-9所示:
图2-9 诺基亚5110液晶显示器连线图
第2.4节 继电器开关电路与报警电路的设计2.4.1. 74LS245芯片介绍
74LS245是我们常用的芯片,本设计采用来驱动继电器和蜂鸣器,它是8路同相三态双向总线收发器,可双向传输数据。
74LS245还具有双向三态功能,既可以输出,也可以输入数据。 当单片机的P0口总线负载达到或超过P0最大负载能力时,必须接入74LS245等总线驱动器。
图2-10 74LS245引脚图
如图2-10所示,当片选端/CE低电平有效时,DIR=“0”,信号由 B 向 A 传输;(接收)。DIR=“1”,信号由 A 向 B 传输;(发送)当/CE为高电平时,A、B均为高阻态。由于P2口始终输出地址的高8位,接口时74LS245的三态控制端/1G和/2G接地,P2口与驱动器输入线对应相连。
P0口与74LS245输入端相连,/E端接地,保证数据现畅通。8051的/RD和/PSEN相与后接DIR,使得/RD或/PSEN有效时,74LS245输入(P0.i←Di),其它时间处于输出(P0.i→Di)。
2.4.2. 继电器开关电路设计
为了驱动继电器导通时线圈有足够的磁力,在继电器之前加了74LS245驱动。继电器一般由铁芯、线圈、衔铁、触点簧片等组成的。只要在线圈两端加上一定的电压,线圈中就会流过一定的电流,从而产生电磁效应,衔铁就会在电磁力吸引的作用下克服返回弹簧的拉力吸向铁芯,从而带动衔铁的动触点与静触点(常开触点)吸合。当线圈断电后,电磁的吸力也随之消失,衔铁就会在弹簧的反作用力返回原来的位置,使动触点与原来的静触点(常闭触点)释放。这样吸合、释放,从而达到了在电路中的导通、切断的目的。对于继电器的“常开、常闭”触点,可以这样来区分:继电器线圈未通电时处于断开状态的静触点,称为“常开触点”;处于接通状态的静触点称为“常闭触点”。继电器一般有两股电路,为低压控制电路和高压工作电路,其原理图如图2-11所示,继电器A1恒为高电平,当74LS245的relay为低电平时,继电器的A2为低电平,继电器处于通电状态,开关闭合,B0、B1处于导通状态,发光二级管点亮。
图2-11继电器连线图
2.4.3. 蜂鸣器报警电路设计
为了保证蜂鸣器足够的响亮,在蜂鸣器之前也加了74LS245驱动。本设计采用软件处理报警,利用有源蜂鸣器进行报警输出,采用直流供电。蜂鸣器的A0也恒为高电平,当74LS245的buzzer为低电平时,蜂鸣器的A1为低电平,此时蜂鸣器报警。报警电路硬件连接见下图2-12所示:
图2-12 蜂鸣器电路连接图
第2.5节 按键电路设计
为了使设计操作更加方便,设计了按键电路,这样就可以人为设定车辆进出值。图2-13为设计的按键电路图。S1、S2按键按下,车辆加、减”1”;S3按键按一次,S1、S2按键按下,车辆数加、减“10”;S3按键按二次,S1、S2按键按下,车辆数加、减“100”;S3按键按三次,系统复位。S3按键按四次,恢复到复位前的车辆数,开始接着计数。
图2-13按键电路图
第3章 系统的程序设计第3.1节 主程序设计
STC89C52RC单片机可以用汇编语言和C语言进行编程。汇编语言与机器指令一一对应,所以用汇编语言编写的程序在单片机里运行起来效率较高,而且对于对射式红外计数器数据的读写上,所用到的语句比较简单易懂。而C语言程序可读性高,更便于理解。本设计使用C语言编程。
第一次开机,系统进行初始化,LCD显示初始数字,对停车场内的车辆数进行设定一个初值N,并开始运行。如果有物体通过进入对射式红外传感器时,继电器开关打开,LED灯点亮,LCD的最后一位开始累加。如果这个时候有物体通过驶出红外对射式传感器时,另一继电器开关打开,LED点亮,LCD的最后一位开始累减。如果这个时候有两个物体同时通过驶出和驶入对射式红外传感器时,两个继电器开关同时打开,两个发光二极管LED同时点亮,LCD的最后一位开始累加。当此停车场车辆数大于500时,蜂鸣器报警,等待复位命令重新进行计数。
图3-1 主程序流程图
第3.2节 数据采集模块程序设计
数据采集模块主要是指在系统开始运行时,当有车辆经过红外对射式传感器时,红外传感器的发射器和接收器之间阻断光线时,形成电平信号,经过放大、整流并送入单片机控制模块进行控制计数。开始,首先是接通电源对设备初始化,启动红外对射式传感器,判断光线是否被阻断,若光线被阻断将数据储存转化并送入单片机控制系统,最后返回到主程序,其流程图如图3-2:
图3-2 数据采集流程图
第3.3节 液晶显示程序设计
显示程序设计主要显示当前车辆数:首先,开始显示初始化界面,显示“停车场计数、作者:韩年猛”、“当前车辆数: 100”,完后判断有无车辆通过红外对射式传感器,如果没有返回到上一步,如果有车辆通过则经单片机控制后显示控制后的当前车辆数,超出500辆车,则蜂鸣器报警,结束返回。其流程图如图3-3:
图3-3 液晶显示流程图
第4章 系统测试
调试工作可分硬件调试和软件调试两个部分,调试方法如下:
第4.1节 系统的硬件调试
首先,软件调试之前主要是先制作硬件电路板,然后用万用表等工具对电路检查,最后应用程序进行功能调试。硬件调试比较费时,需要细心和耐心,也需要熟练掌握电路原理。
然后,用仿真软件keil进行软件调试,该软件提供一个集成开发环境u-Vision,它包括C编辑器、宏编辑器、连接器、库管理和一个功能强大的仿真调试器。通过编译、运行,可以检查程序错误。但应用此方法,仍需要十分了解所使用元器件的工作方式和管脚连接方式。
第4.2节 系统的软件调试
本次设计则是直接完成电路的硬件设计,出现的硬件问题基本解决,主要在软件的程序上进行调试。
在软件调试过程中,曾遇到以下问题:
当硬件初次开机的时候,发现LCD亮度不够均匀。进行分析,是程序设里面对显示程序的延时不够造成的。对于本系统的硬件调试中,对于单个端口(进口或者出口,另一个端口不接通)进行仿真调试可以实现,然而两个端口同时接通,系统却不进行工作,经分析,是程序编辑问题。
在调试按键的时候,当按下S1按键,系统显示正常,再按下S2按键则没有任何反应。查询程序,由于端口编写有误。
第4.3节 测试及结果
给电路供电后,LCD上显示:“停车场计数”,“作者:韩年猛”, “当前车辆数:100”。表示等待车辆进入,当有车辆进出时,继电器打开,LED点亮,车辆数超过500时,系统报警。S3按钮按一次,S1、S2按下,车辆加减”1”;S3按钮按二次,S1、S2按下,车辆数加减“10”;S3按钮按三次,S1、S2按下,车辆数加减“100”;S3按钮按四次,系统复位。测试结果见附件一。
结论
经过几个月的努力设计出基于单片机的停车场计数功能,基本符合设计要求。基于单片机构成的计数器能够实现实时、稳定、精确的计数。对这个课题进行深入的研究。采用STC89C52为控制单元的车辆计数器就可以很好的提高整个系统的抗干扰能力。
通过本次设计,对单片机的内部模块更加熟悉,使用上也更加的清晰,对于今后用单片机设计产品提供了极大的帮助,并且培养了良好的编程习惯,对子程序命名的规范。对传感器的选择使用上,有了一定的良好意识。对液晶显示屏与数码管的区别有了一定的认识,理解两者之间的差别。
参考文献
[1]. 王松德、朱小龙,对射式红外线计数器的设计[J],农业机械学报,2005,36卷 7期
[2]. 刘向宇、秦龙,PIC单片机C语言[M],电子工业出版社,2010
[3]. 金杰,单片机技术应用项目教程[M],电子工业出版社,2010
[4]. 来清民,传感器与单片机接口及实例[M],北京航空航天大学出版社,2008
[5]. 王庆友,光电传感器应用技术[M],机械工业出版社,2007
[6]. 林雪梅,热释电红外传感器及其应用[J],甘肃科技纵横,2005
[7]. 艾红、孙硕.,红外测量在车流量监测中的应用,北京信息科技大学自动化学院控制工程系,北京 100085
[8]. 肖兴达、李继方,基于热释电红外传感器的车流检测装置[J] 激光与红外 2005
[9]. 张洪润等,传感器技术大全(上册)[M],北京航空航天大学出版社,2007
[10]. 江晓军,光电传感与检测技术[M], 机械工业出版社,2011
致谢
感谢学院给我提供了一个展现自己的平台,给了我一次煅炼机会,提高我的动手能力和并把知识付诸于实践。本设计的完成是在彭静玉老师的细心指导下进行的,每次设计遇到问题时彭老师不辞辛苦的讲解才使得我的设计顺利的进行。从设计的选题到资料的搜集直至最后设计的修改的整个过程中,花费了彭老师很多的宝贵时间和精力,在此向彭老师表示衷心地感谢!彭老师严谨的治学态度,开拓进取的精神和高度的责任心都将使我受益终生!还要感谢我的几位同学,是你们在我平时设计中和我一起探讨问题,并指出我设计上的误区,使我能及时的发现问题把设计顺利的进行下去,没有你们的帮助我不可能这样顺利地结稿,在此表示深深的谢意。
附录
附录1:原理图及实物照片说明
附录2:部分源程序
主文件程序
#include <reg51.h>
sbit SCLK = P2^5;
sbit SDIN = P2^4;
sbit LCD_DC = P2^3;
sbit LCD_CE = P2^2;
sbit LCD_RST = P2^1;
void LCD_init(void);
void LCD_clear(void);
void LCD_move_chinese_string(unsigned char X, unsigned char Y, unsigned char T);
void LCD_write_english_string(unsigned char X,unsigned char Y,char *s);
void LCD_write_chinese_string(unsigned char X, unsigned char Y,unsigned char ch_with,unsigned char num,unsigned char line,unsigned char row);
void chinese_string(unsigned char X, unsigned char Y, unsigned char T);
void LCD_write_char(unsigned char c);
void LCD_draw_bmp_pixel(unsigned char X,unsigned char Y,unsigned char *map,unsigned char Pix_x,unsigned char Pix_y);
void LCD_write_byte(unsigned char dat, unsigned char dc);
void LCD_set_XY(unsigned char X, unsigned char Y);
void delay_1us(void);
extern void delay_nms(unsigned int n) ;
void LCD_write_number(unsigned char x);
void number_saved();
unsigned int x;
sbit count_in=P1^0;
sbit count_out=P1^1;
#define delay_time 25767
void main(void)
{
LCD_init(); //初始化液晶
LCD_clear();
LCD_write_chinese_string(6,2,12,5,6,4); //停车场计数
LCD_write_chinese_string(2,4,12,6,0,0); //作者:哈年猛
delay_nms(380);
LCD_clear();
LCD_write_chinese_string(0,1,12,6,11,0);//当前车辆数
x=100;
number_saved() ;
while(1)
{
if(count_in )//如果有车辆,则执行下面的
{
delay_nms(2);//消斗
if(count_in)
{
x++;
number_saved(); while(count_in);//松开有效
}
}
if(count_out )
{
delay_nms(2);
if(count_out )
{
x--;
number_saved(); while(count_out);
}
}
}
}
void LCD_write_number(unsigned char x)
{
switch(x)
{
case 0: LCD_write_char('0');break;
case 1: LCD_write_char('1');break;
case 2: LCD_write_char('2');break;
case 3: LCD_write_char('3');break;
case 4: LCD_write_char('4');break;
case 5: LCD_write_char('5');break;
case 6: LCD_write_char('6');break;
case 7: LCD_write_char('7');break;
case 8: LCD_write_char('8');break;
case 9: LCD_write_char('9');break;
}
}
void number_saved()
{
LCD_set_XY(48,4);
LCD_write_number(x/1000);
LCD_set_XY(54,4);
LCD_write_number(x%1000/100);
LCD_set_XY(60,4);
LCD_write_number(x%100/10);
LCD_set_XY(66,4);
LCD_write_number(x%10);
}
/****************以下是液晶驱动函数*****************/
#include <reg51.h>
sbit SCLK = P2^5;
sbit SDIN = P2^4;
sbit LCD_DC = P2^3;
sbit LCD_CE = P2^2;
sbit LCD_RST = P2^1;
void LCD_init(void);
void LCD_clear(void);
void LCD_move_chinese_string(unsigned char X, unsigned char Y, unsigned char T);
void LCD_write_english_string(unsigned char X,unsigned char Y,char *s);
void LCD_write_chinese_string(unsigned char X, unsigned char Y,unsigned char ch_with,unsigned char num,unsigned char line,unsigned char row);
void chinese_string(unsigned char X, unsigned char Y, unsigned char T);
void LCD_write_char(unsigned char c);
void LCD_draw_bmp_pixel(unsigned char X,unsigned char Y,unsigned char *map,unsigned char Pix_x,unsigned char Pix_y);
void LCD_write_byte(unsigned char dat, unsigned char dc);
void LCD_set_XY(unsigned char X, unsigned char Y);
void delay_1us(void);
code unsigned char write_chinese[][24]={
/*-- 文字: 作 --*/
/*-- 宋体9; 此字体下对应的点阵为:宽x高=12x12 --*/
/*-- 高度不是8的倍数,现调整为:宽度x高度=12x16 --*/
0x10,0x08,0xFC,0x13,0x08,0x04,0xFF,0x24,0x24,0x24,0x04,0x00,0x00,0x00,0x07,0x00,
0x00,0x00,0x07,0x01,0x01,0x01,0x01,0x00,
/*-- 文字: 者 --*/
/*-- 宋体9; 此字体下对应的点阵为:宽x高=12x12 --*/
/*-- 高度不是8的倍数,现调整为:宽度x高度=12x16 --*/
0x10,0x12,0x92,0xD2,0x7F,0x52,0x5A,0x56,0xD2,0x19,0x10,0x00,0x01,0x01,0x00,0x07,
0x05,0x05,0x05,0x05,0x07,0x00,0x00,0x00,
/*-- 文字: : --*/
/*-- 宋体9; 此字体下对应的点阵为:宽x高=12x12 --*/
/*-- 高度不是8的倍数,现调整为:宽度x高度=12x16 --*/
0x00,0x00,0x00,0x00,0x8C,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
/*-- 文字: 韩 --*/
/*-- 宋体9; 此字体下对应的点阵为:宽x高=12x12 --*/
/*-- 高度不是8的倍数,现调整为:宽度x高度=12x16 --*/
0x02,0xFA,0xAF,0xAA,0xFA,0x20,0x2A,0xFF,0x2A,0x2A,0xEA,0x00,0x02,0x02,0x07,0x02,
0x02,0x02,0x00,0x07,0x01,0x02,0x01,0x00,
/*-- 文字: 年 --*/
/*-- 宋体9; 此字体下对应的点阵为:宽x高=12x12 --*/
/*-- 高度不是8的倍数,现调整为:宽度x高度=12x16 --*/
0x88,0x84,0xF3,0x92,0x92,0x92,0xFE,0x92,0x92,0x92,0x82,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
/*-- 文字: 猛 --*/
/*-- 宋体9; 此字体下对应的点阵为:宽x高=12x12 --*/
/*-- 高度不是8的倍数,现调整为:宽度x高度=12x16 --*/
0x8A,0x44,0xFA,0x01,0x88,0xA9,0xA9,0xBD,0x8B,0x89,0x88,0x00,0x04,0x04,0x03,0x04,
0x07,0x04,0x07,0x04,0x07,0x04,0x07,0x00,
/*-- 文字: 停 --*/
/*-- 宋体9; 此字体下对应的点阵为:宽x高=12x12 --*/
/*-- 高度不是8的倍数,现调整为:宽度x高度=12x16 --*/
0x10,0xFC,0x03,0x62,0xBA,0xAA,0xAB,0xAA,0xAA,0xBA,0x62,0x00,0x00,0x07,0x00,0x00,
0x00,0x04,0x04,0x07,0x00,0x00,0x00,0x00,
/*-- 文字: 车 --*/
/*-- 宋体9; 此字体下对应的点阵为:宽x高=12x12 --*/
/*-- 高度不是8的倍数,现调整为:宽度x高度=12x16 --*/
0x02,0x22,0x32,0x2E,0x23,0xFA,0x22,0x22,0x22,0x22,0x02,0x00,0x01,0x01,0x01,0x01,
0x01,0x07,0x01,0x01,0x01,0x01,0x01,0x00,
/*-- 文字: 场 --*/
/*-- 宋体9; 此字体下对应的点阵为:宽x高=12x12 --*/
/*-- 高度不是8的倍数,现调整为:宽度x高度=12x16 --*/
0x08,0x08,0xFF,0x88,0x49,0x91,0x79,0x95,0x73,0x11,0xF0,0x00,0x03,0x01,0x00,0x00,
0x05,0x02,0x01,0x04,0x04,0x06,0x01,0x00,
/*-- 文字: 计 --*/
/*-- 宋体9; 此字体下对应的点阵为:宽x高=12x12 --*/
/*-- 高度不是8的倍数,现调整为:宽度x高度=12x16 --*/
0x10,0xF1,0x02,0x00,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x00,0x00,0x07,0x02,0x01,
0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,
/*-- 文字: 数 --*/
/*-- 宋体9; 此字体下对应的点阵为:宽x高=12x12 --*/
/*-- 高度不是8的倍数,现调整为:宽度x高度=12x16 --*/
0xA5,0x96,0xCC,0xBF,0x96,0xA5,0x18,0x67,0x84,0x7C,0x04,0x00,0x04,0x05,0x02,0x02,
0x03,0x04,0x04,0x02,0x01,0x02,0x04,0x00,
/*-- 文字: 当 --*/
/*-- 宋体9; 此字体下对应的点阵为:宽x高=12x12 --*/
/*-- 高度不是8的倍数,现调整为:宽度x高度=12x16 --*/
0x10,0x92,0x94,0x90,0x90,0x9F,0x90,0x98,0x94,0xF2,0x00,0x00,0x04,0x04,0x04,0x04,
0x04,0x04,0x04,0x04,0x04,0x07,0x00,0x00,
/*-- 文字: 前 --*/
/*-- 宋体9; 此字体下对应的点阵为:宽x高=12x12 --*/
/*-- 高度不是8的倍数,现调整为:宽度x高度=12x16 --*/
0x04,0xF4,0x54,0x55,0xF6,0x04,0x06,0xF5,0x04,0xF6,0x04,0x00,0x00,0x07,0x01,0x05,
0x07,0x00,0x00,0x05,0x04,0x07,0x00,0x00,
/*-- 文字: 车 --*/
/*-- 宋体9; 此字体下对应的点阵为:宽x高=12x12 --*/
/*-- 高度不是8的倍数,现调整为:宽度x高度=12x16 --*/
0x02,0x22,0x32,0x2E,0x23,0xFA,0x22,0x22,0x22,0x22,0x02,0x00,0x01,0x01,0x01,0x01,
0x01,0x07,0x01,0x01,0x01,0x01,0x01,0x00,
/*-- 文字: 辆 --*/
/*-- 宋体9; 此字体下对应的点阵为:宽x高=12x12 --*/
/*-- 高度不是8的倍数,现调整为:宽度x高度=12x16 --*/
0x3A,0x27,0xFA,0xA2,0xFA,0x8A,0x7E,0x8A,0x7E,0x8B,0xFA,0x00,0x01,0x01,0x07,0x00,
0x07,0x00,0x00,0x01,0x04,0x04,0x07,0x00,
/*-- 文字: 数 --*/
/*-- 宋体9; 此字体下对应的点阵为:宽x高=12x12 --*/
/*-- 高度不是8的倍数,现调整为:宽度x高度=12x16 --*/
0xA5,0x96,0xCC,0xBF,0x96,0xA5,0x18,0x67,0x84,0x7C,0x04,0x00,0x04,0x05,0x02,0x02,
0x03,0x04,0x04,0x02,0x01,0x02,0x04,0x00,
/*-- 文字: : --*/
/*-- 宋体9; 此字体下对应的点阵为:宽x高=12x12 --*/
/*-- 高度不是8的倍数,现调整为:宽度x高度=12x16 --*/
0x00,0x00,0x00,0x00,0x8C,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
};
code unsigned char font6x8[][6] =
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // sp
{ 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 }, // !
{ 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 }, // "
{ 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // #
{ 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $
{ 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 }, // %
{ 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 }, // &
{ 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 }, // '
{ 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 }, // (
{ 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 }, // )
{ 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 }, // *
{ 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 }, // +
{ 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 }, // ,
{ 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 }, // -
{ 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 }, // .
{ 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 }, // /
{ 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0
{ 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1
{ 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2
{ 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3
{ 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4
{ 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5
{ 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6
{ 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7
{ 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8
{ 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9
{ 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 }, // :
{ 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 }, // ;
{ 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 }, // <
{ 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 }, // =
{ 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 }, // >
{ 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 }, // ?
{ 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E }, // @
{ 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C }, // A
{ 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B
{ 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C
{ 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D
{ 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E
{ 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 }, // F
{ 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A }, // G
{ 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H
{ 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I
{ 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J
{ 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K
{ 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L
{ 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // M
{ 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N
{ 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O
{ 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P
{ 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q
{ 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R
{ 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 }, // S
{ 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T
{ 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U
{ 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V
{ 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W
{ 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 }, // X
{ 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y
{ 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z
{ 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [
{ 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55 }, // 55
{ 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^
{ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 }, // _
{ 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 }, // '
{ 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 }, // a
{ 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b
{ 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 }, // c
{ 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F }, // d
{ 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 }, // e
{ 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f
{ 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C }, // g
{ 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h
{ 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i
{ 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 }, // j
{ 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k
{ 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l
{ 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m
{ 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n
{ 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 }, // o
{ 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 }, // p
{ 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC }, // q
{ 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r
{ 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 }, // s
{ 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t
{ 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u
{ 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v
{ 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w
{ 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 }, // x
{ 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C }, // y
{ 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z
{ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 } // horiz lines
};
void delay_1us(void) //1us延时函数
{
unsigned int i;
for(i=0;i<1000;i++);
}
void delay_1ms(void) //1ms延时函数
{
unsigned int i;
for (i=0;i<1140;i++);
}
void delay_nms(unsigned int n) //N ms延时函数
{
unsigned int i=0;
for (i=0;i<n;i++)
delay_1ms();
}
void LCD_init(void)
{
// 产生一个让LCD复位的低电平脉冲
LCD_RST = 0;
delay_1us();
LCD_RST = 1;
// 关闭LCD
LCD_CE = 0;
delay_1us();
// 使能LCD
LCD_CE = 1;
delay_1us();
LCD_write_byte(0x21, 0); // 使用扩展命令设置LCD模式
LCD_write_byte(0xc8, 0); // 设置偏置电压
LCD_write_byte(0x06, 0); // 温度校正
LCD_write_byte(0x13, 0); // 1:48
LCD_write_byte(0x20, 0); // 使用基本命令
LCD_clear(); // 清屏
LCD_write_byte(0x0c, 0); // 设定显示模式,正常显示
// 关闭LCD
LCD_CE = 0;
}
void LCD_clear(void)
{
unsigned int i;
LCD_write_byte(0x0c, 0);
LCD_write_byte(0x80, 0);
for (i=0; i<504; i++)
LCD_write_byte(0, 1);
}
/*-----------------------------------------------------------------------
LCD_set_XY : 设置LCD坐标函数
输入参数:X :0-83
Y :0-5
-----------------------------------------------------------------------*/
void LCD_set_XY(unsigned char X, unsigned char Y)
{
LCD_write_byte(0x40 | Y, 0); // column
LCD_write_byte(0x80 | X, 0); // row
}
/*-----------------------------------------------------------------------
LCD_write_char : 显示英文字符
输入参数:c :显示的字符;
-----------------------------------------------------------------------*/
void LCD_write_char(unsigned char c)
{
unsigned char line;
c -= 32;
for (line=0; line<6; line++)
LCD_write_byte(font6x8[c][line], 1);
}
/*-----------------------------------------------------------------------
LCD_write_english_String : 英文字符串显示函数
输入参数:*s :英文字符串指针;
X、Y : 显示字符串的位置,x 0-83 ,y 0-5
-----------------------------------------------------------------------*/
void LCD_write_english_string(unsigned char X,unsigned char Y,char *s)
{
LCD_set_XY(X,Y);
while (*s)
{
LCD_write_char(*s);
s++;
}
}
/*-----------------------------------------------------------------------
LCD_write_chinese_string: 在LCD上显示汉字
输入参数:X、Y :显示汉字的起始X、Y坐标;
ch_with :汉字点阵的宽度
num :显示汉字的个数;
line :汉字点阵数组中的起始行数
row :汉字显示的行间距
测试:
LCD_write_chi(0,0,12,7,0,0);
LCD_write_chi(0,2,12,7,0,0);
LCD_write_chi(0,4,12,7,0,0);
-----------------------------------------------------------------------*/
void LCD_write_chinese_string(unsigned char X, unsigned char Y,
unsigned char ch_with,unsigned char num,
unsigned char line,unsigned char row)
{
unsigned char i,n;
LCD_set_XY(X,Y); //设置初始位置
for (i=0;i<num;)
{
for (n=0; n<ch_with*2; n++) //写一个汉字
{
if (n==ch_with) //写汉字的下半部分
{
if (i==0) LCD_set_XY(X,Y+1);
else
LCD_set_XY((X+(ch_with+row)*i),Y+1);
}
LCD_write_byte(write_chinese[line+i][n],1);
}
i++;
LCD_set_XY((X+(ch_with+row)*i),Y);
}
}
/*-----------------------------------------------------------------------
LCD_draw_map : 位图绘制函数
输入参数:X、Y :位图绘制的起始X、Y坐标;
*map :位图点阵数据;
Pix_x :位图像素(长)
Pix_y :位图像素(宽)
-----------------------------------------------------------------------*/
void LCD_draw_bmp_pixel(unsigned char X,unsigned char Y,unsigned char *map,
unsigned char Pix_x,unsigned char Pix_y)
{
unsigned int i,n;
unsigned char row;
if (Pix_y%8==0) row=Pix_y/8; //计算位图所占行数
else
row=Pix_y/8+1;
for (n=0;n<row;n++)
{
LCD_set_XY(X,Y);
for(i=0; i<Pix_x; i++)
{
LCD_write_byte(map[i+n*Pix_x], 1);
}
Y++; //换行
}
}
void LCD_write_byte(unsigned char dat, unsigned char command)
{
unsigned char i;
//PORTB &= ~LCD_CE ; // 使能LCD
LCD_CE = 0;
if (command == 0)
// PORTB &= ~LCD_DC ; // 传送命令
LCD_DC = 0;
else
// PORTB |= LCD_DC ; // 传送数据
LCD_DC = 1;
for(i=0;i<8;i++)
{
if(dat&0x80)
SDIN = 1;
else
SDIN = 0;
SCLK = 0;
dat = dat << 1;
SCLK = 1;
}
// SPDR = data; // 传送数据到SPI寄存器
//while ((SPSR & 0x80) == 0); // 等待数据传送完毕
//PORTB |= LCD_CE ; // 关闭LCD
LCD_CE = 1;
}
|