【毕设】基于单片机的智能晾衣架控制系统设计+电路图片+程序源码

摘  要

物联网伴随着现代社会的发展取得了极大的进步,各种智能化产品的兴起也使得现代人们的生活越来越便捷。其中衍生了诸如智能窗户,智能台灯,智能窗帘之类的产品。而智能晾衣架却是人们忽略的一点,市场上的智能晾衣架也比较少。传统的人们晾衣服通常都是手动,半自动的方式进行。传统的晾衣架具有较大的局限性。现代人们的生活基本都是忙于工作,常常由于各种原因无法及时收晾衣服,而这常常导致衣物晾不干,受潮,过度曝晒的问题。这对于人们的穿衣质量造成了极大的影响。关于这个问题,本文针对智能晾衣架进行了深刻的研究。本文运用的STC89C52RC单片机作为控制元件,用雨滴传感器以及GY-302模块分别进行雨滴和光照强度的数据测量,经过程序判断,控制直流电机正反转,从而控制晾衣架的伸缩。除此之外,还可以在手动模式下通过按钮或者遥控器控制晾衣架伸出和收回,以及手动设置光照阈值,方便人们选择不同光照强度下晾晒衣物,并且具有限位开关控制晾衣架的位置,防止超程。

关键词智能晾衣架;单片机;直流电机;传感器;遥控器

Abstract

With the development of modern society, the Internet of Things has made great progress. The rise of various intelligent products also makes modern people's life more and more convenient. Products such as smart Windows, smart desk lamps, and smart curtains have been derived. The smart clothes rack is ignored by people, and there are few smart clothes racks on the market. Traditionally, people hang clothes in a manual, semi-automatic way. The traditional clothes rack has great limitation. Modern people's life is basically busy with work, often due to various reasons can not be timely collection and drying clothes, and this often leads to clothes drying, damp, excessive exposure to the sun. This has a great impact on the quality of people's clothing. About this problem, this paper makes a deep research on the intelligent clothes rack. In this paper, STC89C52RC single chip microcomputer as a control element, raindrop sensor and GY-302 module respectively for raindrop and light intensity data measurement, through the program judgment, control DC motor positive and negative rotation, so as to control the clothes rack telescopic. In addition, it can also control the extension and withdrawal of the clothes rack through the button or remote control in manual mode, and manually set the light threshold, which is convenient for people to choose different light intensity to dry clothes, and has a limit switch to control the position of the clothes rack, to prevent overdrive.

Key words: Intelligent clothes rack; Single chip microcomputer; Dc motor; Sensor; Remote control

目录

1. 绪论

1.1 概述

1.2 课题研究背景及意义

1.2.1 课题研究背景

1.2.2 课题研究目的与意义

1.3 国内外发展的历史与现状

1.3.1 国内研究现状

1.3.2 国外研究现状

2. 系统总体设计

2.1 系统基本功能

2.2 系统机构设计

2.3 智能晾衣架传动方案的设计

2.4 系统硬件电路选择

2.5 系统软件结构设计

3. 晾衣架控制系统的硬件设计

3.1 单片机的介绍及其工作系统设计

3.1.1 STC89C52RC主要特点

3.1.2 单片机的工作系统设计

3.2 电源模块设计

3.2.1 LM7805芯片

3.2.2 LM7805电路图

3.3 电机驱动模块设计

3.4 LCD显示模块设计

3.5 红外遥控模块设计

3.5.1 NEC协议介绍

3.5.2 红外硬件电路

3.6 雨滴传感器模块

3.7 光照传感器模块

3.7.1 IIC通信协议

3.7.2 GY-302 模块介绍

3.7.3 GY-302 模块原理图

3.8 按键电路、限位开关及其指示灯

3.9 电路原理图

4. 晾衣架PCB布线图设计

5. 晾衣架控制系统的软件设计

5.1 延时函数模块

5.2 BH1750程序模块

5.3 雨滴传感器函数模块

5.4 外部中断、定时器函数模块

5.4.1 外部中断函数

5.4.2 定时器函数

5.5 红外解码模块

5.5.1 LCD显示程序模块

5.6 函数声明

5.7 主程序模块

结束语

致谢

参考文献

附录

 

  1.  绪论

    1.  概述

“晾衣架的起源由来已久,最早可以追溯到周朝,下部是两根稍宽的木墩作为底座支撑,两根木墩分别支撑着两根立柱,立柱中部也有一根木杆用以稳定整个结构,立柱最顶部有一根用来晾衣服的横杆,古时候称为“桁”或者“木施”。桁的两头略微上翘。随后的朝代里的晾衣架都保持着这个模式,并在此基础上雕刻修饰美化。直到20世纪初,晾衣架的材质和设计才发生了变化,晾衣架开始使用铝制或者塑料制作。材料的变化使得晾衣架耐用性和清洁性得到了极大的提升。而更为紧凑精巧的结构设计也越来越符合现代住宅,公寓的有限空间的使用需求。而随着智能家居的发展,现代人们的晾衣服观念也发生了变化,开始追求自动升降,数码遥控控制等方向。因此,智能晾衣架的发展得到了极大的助力。

随着物联网,人工智能的发展,智能晾衣架也成为了人们研究的对象之一。人们对晾衣架的智能化也提出了更高的要求。基于单片机的智能晾衣架系统有手动和自动两种模式,手动模式与传统晾衣架功能一样,自动模式能自动识别白天和夜晚,雨天与晴天,使衣物在干燥晴天得到晾晒,夜晚或阴雨天自动收回,也可在一定距离内通过遥控来控制晾衣架伸缩,通过限位开关将晾衣架的伸缩控制在合理的范围之内[1]。

    1.  课题研究背景及意义
      1.  课题研究背景

2022年8月底,我国移动物联网连接数已达16.98亿, 首次超出代表“人与人”连接的移动电话用户数,迈入“物超人”的万物智联时代。此外,IoT Analytics 数据显示,2022年后物联网市场将进一步加速发展,全球物联网连接数将达到144亿,同比增长18%,2025年全球物联网连接数有望达270亿[2]。

“十四五”规划中明确要求加快数字化发展,建设数字中国。首次将智慧家居纳入规划纲要。提出应用感应控制、语音控制、远程控制等技术手段,发展智能家电、智能照明、智能安防监控、智能音箱、新型穿戴设备、服务机器人等。现在已有31省市将智能家居纳入发展纲要。目前已经形成了以长三角和珠三角为中心的产业集群,全国有100多家相关企业。

      1.  课题研究目的与意义

目前的普通晾衣架存在诸多缺点。首先,市场上的晾衣架大多为手动装置,无法根据实时的天气情况自主伸缩,造成了一定的不便:如下雨时无法及时收回,导致衣物淋湿;或晴朗时无法伸出,效率低下;手动控制升降费时费力。其次,普通晾衣架缺乏安全保护功能,不能根据光照强度变化自动调节晾晒时间,导致衣物容易受到暴晒等因素的影响,损害衣物的质量。此外,普通晾衣架需要耗费人力去收衣服和晾衣服,造成人们在日常小事中许多不便并且花费一定精力去处理晾衣服和收衣服这件小事[3]。

研究和开发智能晾衣架有利于促进现代科技的发展。首先,智能晾衣架可以提高人们的生活质量,通过自动化的晾衣系统,减少人工的劳动力,提高工作效率。其次,研究和开发智能晾衣架有助于推动智能家居行业的发展。智能晾衣架的推出,为智能家居行业提供了新的发展方向,也为消费者提供了更多的选择。

此外,研究和开发智能晾衣架还有利于促进微控制技术的发展。智能晾衣架通过使用单片机技术,实现了对晾衣过程的智能控制,这不仅需要先进的微控制技术,也有助于推动该技术的发展。总的来说,研究和开发智能晾衣架对现代科技的发展具有重要的促进作用,有助于推动智能家居行业的发展,也有利于促进微控制技术的发展。

    1.  国内外发展的历史与现状
      1.  国内研究现状

在国内,研究人员提出了多种智能晾衣架的设计方案。有的设计方案采用了智能语音控制,可以方便用户通过语音操作;有的设计方案则采用了手机APP控制,可以实现远程操作;还有的研究人员开发了能自动追光的控制系统。例如:李素梅研究了“基于语音识别的智能晾衣系统设计”;吕晓颖研究了“基于手机APP的WiFi智能晾衣架设计”;张玉磊等人进行了“全自动追光多功能晾衣架的设计与应用前景研究”。

      1.  国外研究现状

国外,智能晾衣架的研究也受到了广泛关注。例如,国外的研究人员通过对智能晾衣架的智能控制、实时监测环境参数、衣物干燥等方面进行了更加系统和全面的研究。此外,国外研究人员还积极探索智能晾衣架的应用领域,例如利用智能晾衣架来改善室内空气质量、减少家庭用电量等。这些研究成果不仅对于提高家居生活质量具有重要意义,也对于保护环境和节约资源具有积极的社会效益。

总的来说,国外的智能晾衣架研究具有很高的科学价值和社会价值,为国内的研究工作提供了很好的参考和借鉴。随着科技的不断发展,国外的智能晾衣架研究仍然具有很大的潜力,将在未来取得更加显著的成果。

  1.   系统总体设计
    1.  系统基本功能

具有自动和手动模式。自动模式下可以通过雨滴监测模块与光照检测模块共同检测外界环境的湿度和光照情况,由单片机判断是否降雨,是否有太阳光,并驱动直流电机控制晾衣架的伸缩,由按键设定光照的阈值。手动模式下可以通过遥控远程控制晾衣架的伸缩。

    1.  系统机构设计

本晾衣架控制系统主要包括有:电源、传感器、按钮、电机、LCD显示屏、指示灯、限位开关等模块,其系统机构如图2-1:

图 21系统结构图

从系统构图可以看出,自动模式下雨滴传感器和光照传感器将采集到的数据发送到单片机处理,而后单片机将光照值显示在LCD显示屏上面,单片机将根据收到的数据进行处理,然后控制电机进行正反转以控制晾衣架收缩。

在手动模式下可以通过独立按键已经红外遥控发送指令给单片机,从而使得单片机控制电机转动。而电机的运动行程将收到限位开关的限制。

    1.  智能晾衣架传动方案的设计

本设计的传动方案为丝杆传动机构,通过电机带动丝杆转动,丝杆上的滑块进行竖直运动,从而带动连杆运动,晾衣架伸缩。在丝杆两端分别有两个限位开关,可以避免运动超程。本结构运动简单可靠,使用寿命长。

图 22智能晾衣架模型结构图

    1.  系统硬件电路选择

本系统的控制核心是采用由国内厂商STC(深圳市宏晶微电子科技有限公司)生产的的STC89C52RC单片机,其封装类型为PDIP。该单片机是基于8051架构的单片机,具有低功耗、高集成度、高可靠性、可编程性好等优点。此外,STC89C52RC还具有低功耗模式,包括Idle Mode(空闲模式)和Power Down Mode(掉电模式),能够有效降低功耗,十分适用于晾衣架这类需要长时间待机的产品。

系统的检测部分由雨滴传感器和GY-30模块组成。雨滴传感器适用于检测雨水的设备,通常被用于智能家居、自动浇水系统等场合。其原理是通过检测雨滴与传感器之间的接触,来判断是否下雨。雨滴传感器模块灵敏度高,由于其通过检测电阻值的变化来判断是否降雨,所以其稳定性强。雨滴传感器只有在检测到雨水时才会工作,其余时间处于低功耗状态,所以其也具备节能环保的优点。光照强度检测通过GY-302模块实现,GY-302模块是一款数字光强度光感器模块。是基于BH1750FVI芯片制造的。该模块能实现高分辨率,大范围测量。且可以通过IIC总线与单片机直接通信。两个模块可直接通过排针与单片机连接,十分方便。

红外模块使用HS0038红外一体化接收头,这是一款常见的红外接收头,由红外接收器和解码器组成,可以直接接收38KHz的载波信号,我们只需要在程序中对其解码就行。

电机驱动方面使用两个继电器驱动,其优势在于成本低廉,结构简单,易于实现。

    1.  系统软件结构设计

系统设计用模块化,结构化设计。分为红外解码模块,BH1750模块,LCD显示模块,定时器模块,外部中断模块,雨滴传感器模块,按键及LED模块。

图 23软件程序结构示意图

  1.   晾衣架控制系统的硬件设计

在完成了硬件的总体设计后,接下来针对每个模块进行硬件设计。包括核心元件的选型和电路的具体设计。而针对雨滴传感器和GY-30模块直接购买成品模块,只需要围绕其与单片机IO口连接进行设计。其他器件主要是单片机芯片、电源芯片、红外接收头、电机驱动模块和各个按键及其指示灯进行设计。

    1.  单片机的介绍及其工作系统设计
      1.  STC89C52RC主要特点

STC89C52RC是宏晶科技推出的新一代高速/低功耗/超强抗干扰的单片机,它的指令代码完全兼容传统的8051单片机。其主要特性如下:

·工作电压:5.5V~3.3V/3.8V~2.0V

·工作频率:0~40MHz,实际频率可达48MHz

·具有8K用户应用程序(Flash),512B的RAM

·工作温度为-40~+80摄氏度。

·有3个十六位的定时器/计数器,T0、T1、T2

·PDIP封装。

·具有EEPROM功能

·具有看门狗功能

其引脚结构图如下:

图 31单片机引脚结构图

STC89C52RC单片机有40个引脚,从左上方逆时针排序。

·VCC:电源正极

·GND:电源负极

·P0口:P0口是一个8位漏极开路的双向I/O口。其为开漏输出,其作为总线扩展时不需要接上拉电阻,作为I/O口使用时需要外接上拉电阻。

·P1口:P1的8个I/O口是具有内部上拉电阻的双向I/O口,可以直接接外部硬件输出逻辑电平。其中P1.0和P1.1具有第二功能,分别为T2(定时器/计数器T2的外部计数输入),时钟输出和T2EX(定时器/计数器T2的捕捉/重载触发信号和方向控制)

·P2口:P2口与P1口类似,其内部具有上拉电阻,可以直接控制器内部寄存器输出逻辑电平。

·P3口亦作为STC89C52第二功能使用。

31  P3口第二功能表

引脚号

第二功能

P3.0

RXD (串行输入)

P3.1

TXD (串行输出)

P3.2

(外部中断0)

P3.3

(外部中断0)

P3.4

T0 (定时器0外部输入)

P3.5

T1 (定时器1外部输入)

P3.6

(外部数据存储器写选通)

P3.7

(外部数据存储器写选通)

除此之外还有8个功能引脚:

·9脚是复位引脚RST,当输入高电平时实现复位。

·18和19脚接晶振,用来提供给单片机一个适当的时钟信号。

·20和40脚是两个供电引脚,代号是GND和VCC,分别接正极,负极。

·30引脚为输出地址锁定许可,根据该信号可以判定 MCU的工作状态。

·31脚是储存器选择引脚,使用内部存储接高电平,使用外部存储接低电平

      1.  单片机的工作系统设计

最小的单片机系统包括晶体振动电路和复位电路[4]。设计所选用单片机的晶振电路可为控制系统提供基准时钟信号,由外接晶振、片内振荡器和微调电容构成[5]。这里选择11.0592MHz晶振。这个晶振使用起来较为稳定、成本较低、兼容性好。由于晶体振荡器会产生高频的振荡信号,晶振还需要并联两个电容进行滤波。参考数据手册使用两个22pF的陶瓷电容。

复位电路是指将单片机中寄存器的值复位到初始值[6]。复位电路主要有两种方式,一个是按键复位,一个是上电复位。考虑家庭使用晾衣架的便捷性和硬件的结构性,选择上电复位模式。高电平上电复位本质上是RC串联充电电路。电路中电容容值和电阻阻值可以提高复位延迟时间,使得芯片内部电路能有效清零。其容值一般在0.1uf~10uf之间,阻值在1kΩ到100kΩ之间。本设计采用10uF的极性电容和10kΩ的电阻。当接上电源后,电容充电时间为10uF*10KΩ=0.1S,满足单片机复位条件。

图 32 单片机最小系统结构图

    1.  电源模块设计
      1.  LM7805芯片

LM7805是一款线性稳压器,其价格便宜,使用简单,输出电流较大。LM7805的稳压源电路并不需要很多外接的器件,有防止电流过大和热量过高的保护,方便可靠。这种集成稳压系列中的LM78xx的后两位数字显示这一电路的输出电压,即LM7805的输出电压是5V[7]。当外部输出电阻发送变化时候,内部通过一个同向放大器调节,可以稳定的输出5V的电压。其具备以下特点:

              1. 输出电压5V
              2. 工作时两端压差必须大于2V
              3. 最大输出电流1.5A,静态电流0.5mA
              4. 工作温度为0~+125摄氏度
              5. 具有热过载保护
              6. 具有短路保护
      1.  LM7805电路图

图 33电源模块电路图

参考数据手册,LM7805的输入和输出依次都并联两个0.1uF和10uF的滤波电容,其中10uF为极性电容。是因为10uF用作滤除低频噪音和瞬态干扰,极性电容低频属性更优。0.1uF用来滤除高频噪音和瞬态干扰。其中SW1为自锁开关,也是作为整个控制系统的电源开关,DC1为圆孔电源插口。

    1.  电机驱动模块设计

智能晾衣架电机所实现的动作较为简单,只需要实现正转和反转功能,本设计在此选择直流电机,它能实现电能和机械能的互相转化。内部有的定子和转子由铜线绕成的线圈和铁芯组成。其工作原理是当定子上面有电流通过时,会产生稳定磁场,转子通过电流时也会产生磁场,这个磁场时可变的,两个磁场相互作用场产生了转矩,使得电机转动。

本设计选择的电机型号为XD25GA-370YSY,这款电机自带减速器,空载转速为30r/min功率5W,负载力矩为1.56kgf/cm,其最大能带动11kg的重量。

图 34电机驱动模块电路图

当电流从正向流过电机时,电机正转,电流反向流过电机时电机反转,所以可以通过两个继电器的连接实现电流方向的切换。选择两个型号为SRD-5VDC-SL-C的继电器,在5V供电下线圈工作电流为71.4mA,继电器的最大输出电流为15A。

继电器的线圈处利用三极管作为开关管控制电流的通过,由于单片机上电默认高电平,为了保证其上电不会误触发,可以选择npn三极管。只有基极电平为低电平时三极管才会导通。以下是S8550三极管的电气性能:

32  S8550电气性能表

集电极-基极击穿电压集

40

V

集电极-发射极击穿电压集

25

V

发射极-基极击穿电压

5

V

集电极最大允许电流

1.5

A

结温

-55~150

为了避免三极管基极电流过大烧毁,需要串联一个限流电阻。从数据手册可得知继电器的线圈电流为71.4mA。三极管作为开关管要使其工作在深度饱和状态,此时三极管基极电流Ib约为集电极Ic的十分之一,即7.14mA。三极管饱和状态的压降为0.7V,则限流电阻阻值为:

                          

         (3-1)

为了留有余量,在此选择1k的阻值。

由于继电器是感性的,当电源断开时,线圈会产生很高的电动势,而且会和电源叠加。只要在其线圈两端并联二极管就可以解决,避免其他元器件被感应电压击穿,烧坏。续流二极管的型号为1N4007。其最大直流阻断电压为1KV。

电路中每个继电器还并联一个LED指示灯,指示继电器的工作状态。

    1.  LCD显示模块设计

图 35 LCD显示模块电路图

LCD1602是一款16字符*2行的液晶显示模块。常在电子产品中作为用户界面的输出设备,是一种字符型液晶显示模块,能够显示 字母、数字以及符号,主要由字符型液晶显示屏(LCD)、 控制驱动主电路(HD44780)、电阻、电容等组成[8]。可以设置为正常显示、反向显示、光标显示、光标闪烁等多种显示方式。具有标准的8位并行接口,可以通过单片机等控制器来控制。工作电压通常为5V,也可以根据实际需要选用3.3V或其他工作电压。其封装一般采用16针脚的直插式封装。在硬件连接上可以通过排母和LCD1602直接连接,便于安装拆卸显示屏。

    1. 红外遥控模块设计
      1.  NEC协议介绍

红外通信的本质是通过解码的红外线里的信息来获取按下了哪个遥控键,单片机在处理的时候处理的是二进制,所以,需要通过特殊的方法来把遥控的数据发送出去。遥控指令的发送与接收则只有遵守通信协议的约定规则,才能保证指令信息的准确无误。NEC协议是最常用的红外遥控通信协议之一[9]。 

图 36 NEC协议帧格式图

由图中可知:红外信号先是发送起始信号,然后发送数据,数据其中有4个字节32位的数据,分别为用户码,用户码反码,数据码,数据码反码。用户码是由遥控器厂商指定的,可以避免其他厂商的遥控误控制。数据码则是每个按键的键码,遥控器的每个按键都有其对应的键码值,通过解码数据码就可以得知按下了遥控器的哪个按键。而两个反码是用来校验的,可以通过判断用户码是否等于用户码反码,数据码是否等于数据码反码来判断是否接收出错。在32位数据后面还有重复信号,其作用主要用于长按遥控时候的操作。NEC协议的发送顺序为低位在前,高位在后。若程序判断为连续按键,则在发完一帧简码108ms后不断重复发送规定的尾码,直至按键松开[10]。

NEC协议采用的是PPM调制,每个信号类型通过高低电平的时间长短来分别。

图 37 数据电平时间图

需要注意的是,接收到的与发送的信号是相反的。

      1.  红外硬件电路

红外遥控系统采用发射和接收两个部分。红外遥控的发射电路是采用红外发光二极管,红外光经过调制的红外光波;红外接收电路由红外接收二极管、三极管或硅光电池组成,它们将红外发射器 发射的红外光转换为相应的电信号,再送后置放大器,以供后续电路进行解码等操作[11]。

红外发射器可以直接使用51开发板的遥控器,该遥控器能直接发送38K的载波信号。接收器采用HS0038红外一体化接收头,其内部直接集成了红外监测二极管、自动增益放大器、带通滤波器、解调器等电路,接收的信号经过二级调制后可以将光信号转化为电信号,最终输出可以被FPGA采集的TTL电平信号。

硬件原理图如下:

图 38 红外一体化接收头电路图

在程序中,用单片机的外部中断来检测下降沿信号,可以HS0038的输出接口连接P3.2口上。当有下降沿信号进去外部中断INT0时,在程序上通过计数器计数每个下降沿的间隔来判断电平时间,从而实现对红外信号的解码。

    1.  雨滴传感器模块

对于降雨情况的监测,可以直接采用雨滴传感器模块。雨滴传感器由电路板和感应板组成,电路板上面有两个指示灯,指示工作状态和信号状态。当感应板上没有水时,电阻较大,DO口会向单片机输出高电平, 同时会让LED灯灭掉;水滴滴在感应板上后,水滴导致电阻发生并联,电阻变小,DO口会向单片机输出低电平,LED灯亮。DO口可以与微处理器直接相连,由单片机检测高低电平来判断外面是否下雨[12]。

其原理图如下:

图 39 雨滴传感器电路图

该电路的的J2端子是连接一块电路板,其中上面布满镍线条.当有雨水时,由于雨水导电,导致相邻的镍线连接在了一起,导致电路板的电阻减小,从而使得电压减小,而电路板通过端子的1口与LM393连接,LM393是一个运算放大器,当LM393的3口的电压减小到小于2口的电压时,LM393的1口输出数字信号0,从而使得DO口输出低逻辑电平,与此同时LED5会导通点亮。LED4则是作为模块的工作指示灯。

    1.  光照传感器模块
      1.  IIC通信协议

IIC总线(Inter Integrate Circuit BUS)全称为芯片间总线,它是由 PHILIPS公司开发的两线式串行总线,用于连接CPU及其外围设备。I2C总线利用两根线实现全双工 同步数据传送,具有连线少、可靠性高、成本低、不需要片选信号、支持热插拔等优点[13]。

物理层上,IIC具有两根信号线,一根是时钟线SCL,一根是数据线SDA。IIC总线分为主机和从机,一般来说主机是控制单元(单片机),从机是被控制单元(BH1750FVI)。

图 310 IIC主从设备接线图

需要注意的是上图中的两个上拉电阻,一般取值为4.7K到10K。原因是IIC总线上的设备都是开漏输出,需要借助上拉电阻才能输出高电平。

协议层上,IIC是半双工通信,工作时三种信号进行配合。

·起始信号:SCL高电平时,SDA由高变低。

·停止信号:SCL高电平时,SDA由低变高。

·应答信号:0应答,继续发送,1不应答,停止发送。

图 311  IIC起始信号,停止信号时序图

当发送数据的时候,SCL变为高电平。为了避免数据出错,不能在SCL高电平时拉低或者拉高SDA。

图 312  IIC数据传输时序图

IIC的数据帧格式也有专门的定义:

当主机发送给从机时:起始信号+从机地址+信号位“0”+从机应答,应答完发送,每8位,从机应答一次,直到不应答,通讯停止。

当主机从从机读取时:起始信号+从机地址+信号位“1”+从机应答+主机要的内容,每8位,主机应答一次,直到不应答,通讯停止。

      1.  GY-302 模块介绍

GY-302光强传感器模块采用BH1750芯片组成电路。BH1750具有优良光谱灵敏度特性、16 bit串行输出的数字环境亮度传感器。芯片工作电压为3.3V,内置了16 bit AD转换器,可对广泛的亮度进行1勒克斯的高精度测定,实现了照明度数字值的直接输出。这也意味着可以省略一直以来必须进行的外部演算处理。无论是暗处还是在阳光直射下它都近似于人类视觉感应,能够进行大范围的亮度测定。该芯片的主要特点:①对应12C总线接口;②对应大范围的输入光(1 ~65,536勒克斯);③内置AD转换器,无需外接部件。④消耗功率低[14]。

表 33  BH1750FVI指令集表

指令

功能代码

注释

断电

0000_0000

无激活状态

通电

0000_0001

等待测量状态

重置

0000_0111

重置数字寄存器

连续H分辨率测量模式

0001_0000

在1lx分辨率下开始测量

测量是时间为120ms

连续H分辨率测量模式2

0001_0001

在0.5lx分辨率下开始测量,测量是时间为120ms

连续L分辨率测量模式

0001_0011

在4lx分辨率下开始测量

测量是时间为16ms

一次H分辨率测量模式

0010_0000

在1lx分辨率下开始测量

测量是时间为120ms,测量后自动断电

一次H分辨率测量模式2

00010_0001

在0.5lx分辨率下开始测量

测量是时间为120ms,测量后自动断电

一次L分辨率测量模式

0010_0011

在4lx分辨率下开始测量

测量是时间为16ms,测量后自动断电

改变测量时间(高位)

01000_MT[7,6,5]

改变测量时间

改变测量时间(低位)

011_MT[4,3,2,1,0]

改变测量时间

BH1750FVI芯片具有不同的工作模式和不同的测量精度测量时间,我们通过IIC协议写入不同的指令来配置BH1750FVI的工作模式。在IIC通讯期间,需要提供要写入的设备通讯地址,BH1750FVI的通信地址由其ADDR引脚决定。规定当ADDR引脚接地时地址为0x46,当ADDR引脚接电源时地址为0x8B。

根据数据说明手册,建议设定在连续H分辨率模式下测量,由于这个模式的测量时间足够长,可以对一些噪声有一定的抑制作用。此模式的测量时间需要120ms,因此在读取测量的光照值前,程序上需要延迟一定的时间来保证测量的数据的准确性,一般可在程序上进行180ms的延时。在读取BH1750FVI的光照值时一次只能读取一个字节,BH1750FVI的光照数据是一个16位2字节的数据,所以对于测得的光照值需要进行两次读取,分别读取高八位和低八位,最后进行测得的数据进行合并,对于合并后的数据先乘分辨率再除1.2。

       (3-2)

      1.  GY-302模块原理图

图 313  GY-302光照传感器电路图

U3块是GY-302模块内部的一个降压芯片,其作用是提供稳定的3.3V-5V的供电电压,每个厂家的不同其采用的降压芯片也不同。BH1750FVI芯片上,VCC和GND是电源引脚和接地引脚,ADDR连接一个限流电阻接地,所以BH1750FVI的通信地址在ADDR引脚浮空时,默认接地0x46。DVI引脚是数据有效中断引脚,当BH1750FVI测量到的光照强度数据有效时,DVI引脚会输出一个中断信号,通知主控制器或处理器,表示当前的测量结果可用。这样可以实现一种实时的光照强度数据获取方式,减少主控制器的轮询负担,提高系统效率。SCL和SDA是IIC通信的时钟线和数据线,直接连接单片机的IO口。需要注意的是,由于这两个引脚为开漏输出,没有输出高电平的能力,所以需要上拉电阻。该模块已经自带上拉电阻,所以在电路设计中只需要直接连接到单片机IO口即可。

    1.  按键电路、限位开关及其指示灯

按键可以分为独立按键和矩阵按键[15]。本系统采用独立按键,通过按键切换自动/手动模式,也可以控制电机正反转从而控制电机伸缩。此外,还能通过按键实现光照阈值的设定,从而实现控制晾衣服的时间。

独立按键控制电机状态和模式状态同时,电路还设计有相应的LED指示灯,通过单片机的IO口输出低电平,LED指示灯导通点亮。

为了防止晾衣架运动过度超程,在晾衣架两端设置了两个限位开关,当触碰到限位开关时,单片机IO口被拉低,当单片机检测到IO口被拉低时,发出信号控制电机停止转动。

图 314  按键电路、限位开关、LED指示灯电路图

为了避免LED因为电流过大烧毁,需要在LED前方加入限流电阻。限流电阻的阻值选取与LED的工作电流有关。不同颜色的LED压降不同。根据数据手册,红色:2.0-2.2V,黄:1.8-2.0V,绿色:3.0-3.2V,额定电流均为20mA。压降取平均值,分别为2.1V,1.9V,3.1V则LED的限流电阻:

红色:

                  (3-3)

黄色:

(3-4)

绿色:

(3-5)

因此,均选择100Ω的电阻作为限流电阻。

    1.  电路原理图

在设计好每个模块的电路图后绘制出电路原理图,为PCB制图做准备。

图 315  智能晾衣架原理图

  1.  晾衣架PCB布线图设计

印刷电路板PCB布线会影响到整体电路是否可以正常工作的重要一环。良好的PCB布线有助于电路性能,电磁兼容性的提升。且规范的布线也有助于电路板的制造,提高后面电路板的可维护性。

·在PCB设计中要遵循以下规则:

·合理的线宽和间距。

·信号线和电源线/地线要分离,避免产生干扰

·在布线中要合理安排地线和电源线,避免出现电路板热失控,烧毁。

·地线要尽量短,粗,减小接地电阻提高抗干扰能力。

在本设计中要考虑的地方主要有经过继电器给电机供电的部分,根据数据手册,电机的最大电流可达0.8A,留一定余量取1A,在35um的覆铜板厚度下,其线宽就要为0.4mm,约16mil,由于只是电源线,没有信号传输,间距大于0.5mm即可。其余线宽默认10mil。需要注意的是在元器件位置摆放时要注意继电器的电磁干扰对红外一体化接收头的影响,所以两者应该尽量远离。除此之外,单片机的晶振也要尽量靠近单片机的晶振引脚。原因是线路越短,时钟信号的传输损耗和其他电磁干扰越小,越短的线路温升也越小,由可以减小晶振因为温度升高带来的温漂。LM7805稳压芯片的小容值滤波电容也要尽量靠近其引脚,大滤波电容尽量靠近电源,小滤波电容其退耦作用,大滤波电容起滤波作用。应该尽量保证线路短来避免受到二次干扰。

图 4-1  PCB布线图

图 4-2  PCB三维预览图

  1.   晾衣架控制系统的软件设计

本控制系统的程序模块较多,程序编写的时候考虑到程序的结构性,易读性,可维护性等,采用模块化编程。程序分为七大模块,分别为主程序模块,延时函数模块,BH1750程序模块,雨滴传感器函数模块,外部中断、定时器函数模块。红外解码模块,LCD显示程序模块。

    1.  延时函数模块

void Delay(unsigned int xms)

{

unsigned char i, j;

while(xms--)

{

i = 2;

j = 239;

do

{

while (--j);

} while (--i);

}

}

该延时函数利用了whil,do while循环语句进行延时,最短可以进行1ms延时,其中x是一个int型数据类型,可以通过配置x的值来设置延时时间,x最长为65535,因此延时最长时间大约为65ms。

    1.  BH1750程序模块

BH1750FVI通过IIC协议与单片机互相传输数据。

图 5-1   BH1750FVI程序结构图

void Bh1750_Init(void)  //BH1750模式配置

{

  Write_BH1750(0x01);   

  Write_BH1750(0x10);   

  Delay(180);           

}

通过上述函数对BH17500FVI进行初始化操作,写入相关指令,其中0x01是上电指令,0x10是把BH1750FVI设置为连续测量高精度模式(1lx)。该模式下的测量时间为120ms,将其延时180ms避免数据出错。

unsigned int Bh1750_Data(void) //处理BH1750数据

{

  unsigned int light;

  Read_BH1750();         //调用读取BH1750FVI数据的函数

  light=Data0[0];

  light=(light<<8)+Data0[1]; //把高八位和低八位合并为十六位的数据

  light=(float)light/1.2;

  return light;

}

    1.  雨滴传感器函数模块

雨滴传感器的编程较为简便,由于其内部具有运算放大器LM393,所以其DO口可以直接输出高电平和低电平,通过检测DO口的引脚电平即可获得是否降雨。

图 5-2  雨滴传感器程序结构图

    1.  外部中断、定时器函数模块

在红外解码程序中需要利用外部中断进行检测是否有红外信号的输入,且通过定时器来进行红外高低电平信号的时间判断,所以先对外部中断和计数器进行配置。

      1.  外部中断函数

图 5-3  中断函数寄存器图

这是中断函数的寄存器图,由于HS0038红外接收头的输出引脚接单片机的P3.2口,也是外部中断0(INT0)口,所以在程序上针对INT0进行配置,图中IT0是中断方式。IE0是中断申请,由外部触发。EX0、中断0的开关。EA是总开关。PX0是配置优先级。外部中断代码:

void Int0_Init(void)

{

IT0=1 ; //下降沿触发

IE0=0;    

EX0=1;    //打开INT0中断

EA=1;     //开总中断

PX0=1;    //高优先级

}

      1.  定时器函数

在红外通信中利用定时器不中断来进行时间的计算。定时器需要配置TMOD寄存器和TCON寄存器,TMOD寄存器有8个位,前面四位用在T1,后面四位用在T0。在这里使用定时器0,只要设置后面四位。TMOD需要八个位一起设置,TCON的每个位都可以单独设置。

图 5-4  TMOD寄存器图

GATA是门控位,当其为0时,用TCON里的TR0来启动T0。

C/T是配置计数器模式和定时器模式,为0时是定时器模式。

定时器的工作方法是M1和M0决定的。

5-1  定时器工作方式

M1

M0

工作方式

0

0

方式0,由TH1(TH0)的8位和TL1(TL0)的低5位组成一个13位定时器

0

1

方式1,由TH1(TH0)的8位和TL1(TL0)的8位组成一个16位定时器

1

0

方式2, TL1(TL0)溢出后,TH1(TH0)的数值自动填充到TL1(TL0)

1

1

方式3,仅适用于T0,T0分成两个8位计数器,T1停止计数

5-2  TCON寄存器

名称

B7

B6

B5

B4

B3

B2

B1

B0

TCON

TF1

TR1

TF0

TR0

IE1

IE0

IE1

IT0

TF0:溢出中断请求标志位。当中断溢出时,发出请求中断信号。TF1类似

TR0:启动定时器,TR=1时计时,TR=0时不计时。TR1类似

IE0:中断申请标志位,当置1时请求单片机处理中断。IE1类似

IT0:设置触发方式,1位下降沿触发,2为低电平触发。IT1类似

定时器计时代码:

#include <REGX52.H>

void Timer0_Init(void)

{

TMOD &= 0xF0; //模式

TMOD |= 0x01; //模式

TL0 = 0; //定时初值

TH0 = 0; //定时初值

TF0 = 0; //中断标志

TR0 = 0; //不计时

}

    1.  红外解码模块

红外解码可以采用状态机的形式,判断状态转移条件是否满足。

图 5-5  红外解码程序结构图

代码编程思路是当第一次检测到下降沿时候,定时器开始计时,并且进入状态1,准备判断是否是起始信号,满足起始信号就进入状态2准备接收数据,此时要把定时器的值清零便于下次两个下降沿直接的时间的计时。不满足则返回状态0。接收数据的时候要循环接收33次,且进行数据校验,判断用户码是否等于用户反码,数据码是否等于数据反码,确保数据无误。接受完后要把数据接收完成标志位置1。

      1.  LCD显示程序模块

每个函数功能如下:

5-3  LCD1602函数定义

函数

作用

LCD_Init

初始化函数

LCD_ShowChar

显示一个字符

LCD_ShowString

显示字符串

LCD_ShowNum

显示十进制数字

LCD_ShowSignedNum

显示有符号的十进制数字

LCD_ShowHexNum

显示十六进制数字

LCD_ShowBinNum

显示二进制数字

    1. 函数声明

在各个函数模块的“.C”文件编写完成后,要在主程序调用模块函数里的函数,我们需要进行函数声明,在“.h”文件里面进行函数声明,把模块里面创建的函数放在“.h”文件进行声明,主程序才能调用其他模块的函数。函数声明的格式如下:

#ifndef __DELAY_H__

#define __DELAY_H__

函数体;

#endif

    1. 主程序模块

在编写完所以模块的指令后,把所有模块程序加入到同一个工程文件中去。当完成了所有的“.h”文件的函数声明后,直接在函数调用该模块的头文件方可调用每个模块的函数。

主函数结构如图2-3所示:

void main()

{

    LCD_Init();  //LCD初始化

    Bh1750_Init();  //BH1750初始化

    IR_Init();  //红外遥控初始化

    while(1)

    {

  Get_Data();

  sun_set();

    if(P3_2==0) //模式按钮

{

   Delay(20); //延时消抖

         while(P3_1==0);

         Delay(20);

      method=~method;  //切换模式

      LED1=~LED1;      //模式指示灯

  }  

  if(method==0)   //手动模式

   {

       manual_control();

   }

  else if(method==1)   //自动模式

  {

      automatic_control();

}

 在main函数中先电源模块的初始化函数进行各个模块初始化。Get_Data()和sun_set()函数中分别获取了测得的光照值和设定的光照阈值显示在LCD上。P3.2口是控制模式选择按钮,上电默认手动模式,手动模式执行手动操作manual_control(),只有按键按下执行自动模式automatic_control()。

手动模式下判断getDataflag()的值,来判断是否接收到遥控信号,如果没有就看哪个按键按下,按下相应的按键电机执行相应功能。

自动模式下则通过复合运算判断光照状态和天气情况来控制电机运动。利用if(Light>set&&P2_0==1)这条语句判断是否光照值大于设定值,且无雨,只有两个条件同时满足,电机正转,晾衣架伸出。else if(Light<set||P2_0!=1)利用这条语句判断是否光照低于设定值,或者有雨,当两个条件有一个符合则电机反转,晾衣架收回。

结束语

本设计时基于STC89C52RC单片机设计的智能晾衣架,该设计基本实现了雨天及阴天自动控制晾衣架伸缩的功能,还能通过遥控和按键控制晾衣架。操作简单,成本低廉,能够满足大多数人们的生活需求。但是,本设计还有一些潜在问题待解决,比如:没有考虑到湿度情况,特别是南方春季潮湿的季节。所设计的电机功率也不高,只适用于衣物较少,重量较轻的情况下使用。

通过本次设计,对智能家居领域有了更加深入的了解,并认识到了智能化技术在实际生活中的广泛应用和巨大潜力。未来,智能晾衣架作为智能家居领域的一部分,将会在未来的发展中得到更加广泛的应用和推广,为人们的生活带来更多便利和舒适。  

附录

主程序:

#include <REGX51.H>

#include "Delay.h"

#include "BH1750.h"

#include "lcd1602.h"

#include "IR.h"

sbit LED1=P1^0;

sbit LED2=P1^1;

sbit LED3=P1^2;

unsigned char Num;  //遥控键码

unsigned int Light=0;  //测量光照值

bit method=0;  //模式选择

static unsigned int set=500; //光照阈值  

void Get_Data();  //获取光照值

void zhengzhuan();  //正转

void fanzhuan();  //反转

void manual_control();  //手动控制

void automatic_control();  //自动控制

void sun_set();  //光照阈值设定

void main()

{

    LCD_Init();  //LCD初始化

    Bh1750_Init();  //BH1750初始化

    IR_Init();  //红外遥控初始化

    while(1)

    {

Get_Data();

sun_set();

        if(P3_2==0)

{

Delay(20); //延时消抖

         while(P3_1==0);

         Delay(20);

method=~method;

LED1=~LED1;

}  

if(method==0)   //手动模式

        {

             manual_control();

        }

    else if(method==1)   //自动模式

    {

      automatic_control();

    }

    }

}

void Get_Data() //获取光照值并显示

{

    static unsigned int count = 0;

    if (count++ > 3)

    {

        count = 0;

        Light = Bh1750_Data();

        LCD_ShowNum(1,1,Light,5);

    }

}

void zhengzhuan() //电机正转

{

    P1_5=0;

P1_6=1;

LED2=0;

if(P3_0==0) //到达限位开关

{

P1_5=1;

P1_6=1;

LED2=1;

}

    

}

void fanzhuan()    //电机反转

{

    P1_5=1;

P1_6=0;

LED3=0;

if(P3_1==0)    //到达限位开关

{

P1_5=1;

P1_6=1;

LED3=1;

}

    

}

void manual_control()    

{

    if(getDataflag())   //接收到遥控信号标志

    {

        Num=getCommand(); //接收遥控键码

        switch(Num)

        {

            case 0x44: P1_5=0;P1_6=1;break;

            case 0x40: P1_5=1;P1_6=0;break;

        }

    }

    else   //按键控制电机

    {

        if(P3_4==0)   //正转

        {

Delay(20); //延时消抖

         while(P3_1==0);

         Delay(20);

            zhengzhuan();

        }

        else if(P3_5==0)  //反转

        {

Delay(20); //延时消抖

         while(P3_1==0);

         Delay(20);

            fanzhuan();

        }

    }

}

void sun_set() //光照阈值设定

{

if(P3_3==0)

{

Delay(20); //延时消抖

        while(P3_3==0);

        Delay(20);

set=set+500;

if(set>2500)

{

set=0;

}

}

LCD_ShowNum(2,1,set,5);

}

void automatic_control()

{

    if(Light>set&&P2_0==1) //光照大于设定值且没有雨滴,电机正转

    {

        zhengzhuan();

    }

    else if(Light<set||P2_0!=1)   //光照小于设定值或者有雨滴,电机反转

    {

        fanzhuan();

    }

}

BH1750程序:

#ifndef __BH1750_H__

#define __BH1750_H__

void Bh1750_Init(void);

unsigned int Bh1750_Data(void);

#endif

#include <REGX51.H>

#include "BH1750.h"

#include "Delay.h"

unsigned char  Data0[2];

#define   device_address   0x46  //设备地址

sbit SCL=P1^0;      

sbit   SDA=P1^1;

void BH1750_Start()  //起始信号

{

    SDA = 1;                    

    SCL = 1;                    

    Delay(1);                 

    SDA = 0;                    

    Delay(1);                 

    SCL = 0;                    

}

void BH1750_Stop()  //停止信号

{

    SDA = 0;                    

    SCL = 1;                    

    Delay(1);                 

    SDA = 1;                    

    Delay(1);                 

}

void BH1750_SendACK(bit ack)  //发送应答信号

{

    SDA=ack;                  

    SCL=1;                    

    Delay(1);                 

    SCL=0;                    

    Delay(1);                 

}

bit BH1750_RecvACK()  //接收应答信号

{

    unsigned char Ack;

SDA=1;

Delay(1);

SCL=1;

Ack=SDA;   

Delay(1);

SCL=0;

return Ack;

}

void BH1750_SendByte(unsigned char dat) //发送数据

{

    unsigned char i;

for(i=0;i<8;i++)

{

SDA=dat&(0x80>>i);   

SCL=1;

SCL=0;

}  

    BH1750_RecvACK();  

}

unsigned char BH1750_RecvByte() //接收数据

{

    unsigned char i;

    unsigned char dat = 0;

    SDA = 1;                    

    for(i=0;i<8;i++)

{

SCL=1;

if(SDA)

{

dat|=(0x80>>i);

}

SCL=0;

}

    return dat;

}

void Write_BH1750(unsigned char command_Address)   //往BH1750写入数据

{

    BH1750_Start();                  

    BH1750_SendByte(device_address);   

    BH1750_SendByte(command_Address);    

    BH1750_Stop();                  

}

void Read_BH1750(void)  //读出BH1750的数据

{   

  unsigned char i;

  BH1750_Start();                          

  BH1750_SendByte(device_address+1);         

  for (i=0; i<2; i++)                      

  {

    Data0[i] = BH1750_RecvByte();          

    if (i == 1)

    {

      BH1750_SendACK(1);                

    }

    else

    {

      BH1750_SendACK(0);                

    }

  }

  BH1750_Stop();                         

  Delay(5);

}

void Bh1750_Init(void)  //BH1750初始化

{

  Write_BH1750(0x01);   

  Write_BH1750(0x10);   

  Delay(180);           

}

unsigned int Bh1750_Data(void) //处理BH1750数据

{

  unsigned int light;

  Read_BH1750();      

  light=Data0[0];

  light=(light<<8)+Data0[1];

  light=(float)light/1.2;

  return light;

}

红外解码程序:

#ifndef __IR_H__

#define __IR_H__

void IR_Init(void);

unsigned char getDataflag(void);

unsigned char getCommand(void);

#endif     

#include <REGX52.H>

#include "Timer0.h"

#include "Int0.h"

unsigned int Time;   //储存电平时间

unsigned char State;   //状态标志

unsigned char Data1[4];   //存储用户码,用户反码,数据码,数据反码

unsigned char pData;     //存储每一位数据,共33位

unsigned char Dataflag;   //数据接收完成标志

unsigned char Address;   //用户码

unsigned char Command;   //数据码

void IR_Init(void)   //红外解码初始化函数

{

Timer0_Init();

Int0_Init();

}

unsigned char getDataflag(void) //数据接收完成标志函数

{

if(Dataflag)

{

Dataflag=0;

return 1;

}

return 0;

}

unsigned char getCommand(void) //获取接受到的键码

{

return Command;

}

void Int0_Routine(void) interrupt 0

{

if(State==0) //状态0

{

TH0=0; //定时器清零

TL0=0; //定时器清零

TR0=1; //开始计时

State=1; //状态转移为1,准备判断是否起始信号

}

else if(State==1)

{

Time=(TH0<<8)|TL0; //把定时器值读取出来

TH0=0; //定时器清零准备下次计时

TL0=0; //定时器清零准备下次计时

if(Time>12442-500 && Time<12442+500)   //判断是否为起始信号,13.5ms/1.085us

{

State=2;   //是起始信号,状态转移准备接收数据

}

else

{

State=1;   //不是起始信号,返回状态1

}

}

else if(State==2)

{

Time=(TH0<<8)|TL0;   //把定时器的值读取出来

TH0=0;   //定时器清零准备下次计时

TL0=0;   //定时器清零准备下次计时

if(Time>1032-500&&Time<1032+500)   //判断两次下降沿时间是否为(560us+560us)/1.085us

{

Data1[pData/8]&=~(0x01<<(pData%8));   //满足数据0的电平时间把数据“0”存储

pData++;

}

else if(Time>2074-500&&Time<2074+500)   //满足数据0的电平时间把数据“1”存储

{

Data1[pData/8]|=(0x01<<(pData%8));

pData++;

}

else

{

pData=0;   //时间都不满足,返回状态1

State=1;

}

if(pData>=32)   //连续存储33位数据

{

pData=0;

if((Data1[0]==~Data1[1])&&Data1[2]==~(Data1[3])) //检验用户码和数据码

{

Address=Data1[0];   //用户码取出来

Command=Data1[2];   //数据码取出来

Dataflag=1;   //数据接收完成标志

}

TR0=0;   //停止计时

State=0;   //回到状态0

}

}

}

延时程序:

#ifndef __DELAY_H__

#define __DELAY_H__

void Delay(unsigned int xms);

#endif

void Delay(unsigned int xms)

{

unsigned char i, j;

while(xms--)

{

i = 2;

j = 239;

do

{

while (--j);

} while (--i);

}

}

外部中断配置程序:

void Int0_Init(void);

#endif

#include <REGX52.H>

void Int0_Init(void)

{

IT0=1 ;

IE0=0;

EX0=1;

EA=1;

PX0=1;

}

定时器配置程序:

#ifndef __TIMER0_H__

#define __TIMER0_H__

void Timer0_Init(void);

#endif

#include <REGX52.H>

void Timer0_Init(void)

{

TMOD &= 0xF0; //设置定时器模式

TMOD |= 0x01; //设置定时器模式

TL0 = 0; //设置定时初值

TH0 = 0; //设置定时初值

TF0 = 0; //清除TF0标志

TR0 = 0; //定时器0不计时

}

LCD1602显示程序:

#ifndef __LCD1602_H__

#define __LCD1602_H__

void LCD_Init();

void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);

void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);

void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);

void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

#endif

#include <REGX52.H>

sbit LCD_RS=P2^6;

sbit LCD_RW=P2^5;

sbit LCD_EN=P2^7;

#define LCD_DataPort P0

void LCD_Delay()

{

unsigned char i, j;

i = 2;

j = 239;

do

{

while (--j);

} while (--i);

}

void LCD_WriteCommand(unsigned char Command)

{

LCD_RS=0;

LCD_RW=0;

LCD_DataPort=Command;

LCD_EN=1;

LCD_Delay();

LCD_EN=0;

LCD_Delay();

}

void LCD_WriteData(unsigned char Data)

{

LCD_RS=1;

LCD_RW=0;

LCD_DataPort=Data;

LCD_EN=1;

LCD_Delay();

LCD_EN=0;

LCD_Delay();

}

void LCD_SetCursor(unsigned char Line,unsigned char Column)

{

if(Line==1)

{

LCD_WriteCommand(0x80|(Column-1));

}

else if(Line==2)

{

LCD_WriteCommand(0x80|(Column-1+0x40));

}

}

void LCD_Init()

{

LCD_WriteCommand(0x38);

LCD_WriteCommand(0x0c);

LCD_WriteCommand(0x06);

LCD_WriteCommand(0x01);

}

void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)

{

LCD_SetCursor(Line,Column);

LCD_WriteData(Char);

}

void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)

{

unsigned char i;

LCD_SetCursor(Line,Column);

for(i=0;String[i]!='\0';i++)

{

LCD_WriteData(String[i]);

}

}

int LCD_Pow(int X,int Y)

{

unsigned char i;

int Result=1;

for(i=0;i<Y;i++)

{

Result*=X;

}

return Result;

}

void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)

{

unsigned char i;

LCD_SetCursor(Line,Column);

for(i=Length;i>0;i--)

{

LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');

}

}

void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)

{

unsigned char i;

unsigned int Number1;

LCD_SetCursor(Line,Column);

if(Number>=0)

{

LCD_WriteData('+');

Number1=Number;

}

else

{

LCD_WriteData('-');

Number1=-Number;

}

for(i=Length;i>0;i--)

{

LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');

}

}

void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)

{

unsigned char i,SingleNumber;

LCD_SetCursor(Line,Column);

for(i=Length;i>0;i--)

{

SingleNumber=Number/LCD_Pow(16,i-1)%16;

if(SingleNumber<10)

{

LCD_WriteData(SingleNumber+'0');

}

else

{

LCD_WriteData(SingleNumber-10+'A');

}

}

}

void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)

{

unsigned char i;

LCD_SetCursor(Line,Column);

for(i=Length;i>0;i--)

{

LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值