基于单片机的自动窗帘控制系统毕业论文

时间:2020-05-10 22:00:18 浏览量:

 

  题目

 自动窗帘控制系统

 年

  月

  日

  摘 要

 自动控制属于电子及信息科学的一个重要分支,并且在现代家居中有着较好的目前发展前景。目前,家庭居住环境的采光及避光问题主要采用的是手动开闭窗帘,手动开闭不仅费力而且很多方面不够人性化,可能对用户造成一定的困扰,窗帘控制系统可以解决这些问题。本文综述了自动窗帘控制系统的设计与制作过程,介绍了设计制作一个完整的窗帘控制系统需要做的理论分析以及其制作过程。自动窗帘控制系统核心采用的是单片机AT89S52,其次利用了光照传感器、键盘显示接口电路以及信号调理电路等外围电路,整个系统在各模块的配合下可实现半自动控制、自动控制、定时控制等功能。该设计在理论层面上,用程序语言驱动各模块工作,实现系统的内在联系,在应用层面上则采用Protel软件进行原理图设计。

 自动窗帘控制系统的构成主要由光照传感电路、系统主控模块电路、电源转换电路、电机控制电路、键盘以及显示电路等组成,重点讨论了窗帘自动控制系统的设计过程、硬件选用和软件调试等问题,通过本系统可实现利用光照强度以及设置时间来控制窗帘自动开闭。

  关键字:单片机,自动控制,AT89C52,Protel

  ABSTRACT

  Electronics and automatic control is an important branch of information science, and they now have a better prospect. Now, According to the requirements of living environments, this design made full use of the SCM controlling system of AT89C52,followed by the sensor, keyboard and display interface circuit and the signal conditioning circuit.Based on the different controlling mode, we realize to control the curtain machine by mutual transformation of semiautomatic and automatic controlling and infrared remoter.

 Focusing on the curtain during automatic control system design, hardware and software debugging process and other issues, the system can be realized through the illumination intensity in accordancecontrol the curtains down.

 KEY WORDS:SCM, automatic control, AT89C52, Protel

  目录 前

 言 1 第1章 绪论 2 1.1 课题研究背景及意义 2 1.2 基本内容安排 2 1.3 设计思想及基本功能 3 第2章 总体电路设计及其原理说明 4 2.1 方案选取 4 2.2 系统总体结构设计 5

  2.2.1系统基本功能 5

  2.2.2系统总体结构设计 6 第3章 硬件分析与设计 7 3.1电源电路设计 7 3.2 89C52单片机及相关电路 8 3.2.189C52单片机概述 8 3.2.2晶振电路 8 3.2.3复位电路 9 3.2.4时钟电路 10 3.2.5键盘电路 12 3.2.6 显示电路 13 3.2.7 A\D转换电路 15 3.2.8光敏传感器 17 3.2.9 步进电机 18 3.2.10信号校正电路 19 第4章 程序分析与设计 21 4.1 主程序设计 21 4.2 主要子程序设计 22

  4.2.1 键盘程序设计 22

  4.2.2定时程序设计 24

 4.2.3步进电机程序设计 25 总结 26 致谢 27 参考文献 28 附录一 29 附录二 30

  前

 言

 伴随着信息化时代的到来,人们的生活速度以及对生活质量的追求也在大幅提高。电子产品智能化速度的加快,也使人们的工作、生活和通讯的关系日益紧密。智能化的产品设计在改变人们工作方式与生活习惯的同时,让人们对生活质量的提升提出了更高的要求,方便、舒适成了人们所追求的生活方式,在现代家庭生活环境中,居家环境早已不仅仅局限在物理空间上,人们更为关注的是一个安全、方便、舒适的环境。智能化的电子产品以及设计将以前的被动静止物体转变为人们能够方便操控的工具,这些产品具有提供全方位的信息交换的功能,不仅能够优化人们的生活方式,帮助人们合理的安排时间,增强居家环境的安全性,甚至还可以为各种能源费用节约资金。

 在智能化产品中,单片机的应用已经越来越广泛,单片机以它体积小、质量轻、耗电省、可靠性高、价格低等优点,开始不断发展,并广泛应用于仪器仪表、家用电器、医疗设备、航天航空领域、工业专用设备的管理及过程控制等领域,在很多的大中型的电气设备以及小型的电子产品中也用到了单片机进行控制。

 针对人们对智能化的需求以及对舒适生活的追求,窗帘自动控制系统改变了传统窗帘的劣势,它可以根据外界光照强度的不同而自动开闭窗帘,也可以根据人们设定的时间来控制窗帘。该系统利用光敏电阻检测光照强度的变化,并且将光敏检测模块的电阻变化转化为电压变化,然后将电压变化的信号送单片机,单片机通过电机驱动模块控制着步进电机的正反转实现窗帘的来回移动。本设计正是把利用AT89C52 单片机的优点以及简单实用性,顺利的完成了对智能控制的要求,并且为智能化的家居设备提供了良好的基础。此外,对该系统进行扩展,比如可以加上防火,防盗,甚至室内煤气浓度监测等功能,会使该系统更具有实用性,而且也完善了系统。

 第1章 绪论

 1.1 课题研究背景及意义 21世纪是信息化的时代,知识与科技成为时代的潮流,在它们的推动下,智能化也因此得到了很大的发展,其作用在社会生活中日益得到彰显。智能控制系统主要利用计算机技术、网络通信技术、综合布线技术等现代化技术的有机结合而发挥作用。在通信技术、计算机技术、网络技术、智能控制技术的迅猛发展潮流下,家庭生活实现了现代化与智能化,居家环境也变得更加舒适与安全。智能化控制的工作原理自然离不开运算和控制单元,而该系统采用的主控器件AT89C52,正是运算与控制单元的集合体。系统的整体主要由硬件和软件两部分组成。硬件部分由单片机扩展的外围电路以及各种实现单片机系统控制功能的接口电路组成;软件部分主要由单片机系统实现其特定控制功能的各种程序组成。本设计中介绍了自动窗帘控制系统的硬件构成以及软件设计过程,以尽最大可能满足不同人对窗帘开闭的不同需求。同时,系统在针对人们一般需求的设计开发外,还提出多种解决方案,在考虑到经济性和简便性的前提下,可以供日后对控制系统的功能进行扩展。

 1.2 基本内容安排 该设计通过分析电动窗帘的现状和人们对自动窗帘控制系统的功能的需求,从而对自动窗帘控制器进行总体的设计。系统的总体设计采用以步进电机作为单片机控制元件,执行窗帘开闭的主要任务;以光敏电阻作为检测元件,以提供单片机外界光照的变化;89C52单片机作为主控制芯片,控制着整个系统的运行,此外,辅助以键盘和显示电路,在各个电路模块的配合下最终实现了自动窗帘控制系统的智能化要求。

 自动窗帘控制系统设计过程主要分为一下几个章节:

 (1)绪论:介绍目前国内外电动窗帘的发展现状和研究的目的和意义。

 (2)总体设计方案:概括自动窗帘控制系统的的总体设计方案选取以及硬件设计的总况。

 (3)硬件设计:采用89C52单片机作为控制核心,并且辅助以外围电路,其中包括电源电路,定时电路,步进电机控制电路,键盘/显示电路等一系列相关电路。

 (4)软件设计:介绍各个功能模块的的设计流程以及设计思路。

 (5)总结:针对设计中的不足进行再思考以及提出自动窗帘控制系统功能的扩展。

  1.3

 设计思想及基本功能

 该系统具有一般的窗帘控制系统的最基本的功能,即通过电动按钮来开闭窗帘,在此基本功能的前提下,本设计根据需求还设计了可以根据光照强度和设定时间自动开闭窗帘的功能,在选取设计方案和采用元器件方面,该系统本着简单实用经济的思想,尽量简化电路设计,用最简单的电路布线和选用最经济实用的器件来达到设计要求。

 自动窗帘控制系统具有以下几个基本功能:

 (1)手动控制:该功能是根据用户的需求通过按键进行窗帘的开关,此功能可以使窗帘的开闭处于任何一种状态; (2)光照自动控制:系统可以根据用户设定的光照强度值通过感光器采集光照自动开光窗帘; (3)时间控制:此功能是根据用户设定的时间一次性开关窗帘,并显示当前温度。

  (4)温度报警系统:可以自行设置温度报警温度。

 (5)时间显示及闹钟系统:可以自行设置闹钟时间。

 (6)手动自动控制按键随时切换。

 第2章 总体电路设计及其原理说明 2.1 方案选取

  单片机在各种电子产品中的应用已经越来越广泛,很多的电子产品利用单片机所取得的便利性得到了人们的好评,针对单片机控制的自动窗帘控制系统的智能化要求,实现其自动控制的方案有两种:

 方案(一)基于温度检测以及声控检测器件的自动控制

  方案(二)基于光照强度器件的自动控制

  这二个方案都是基于单片机控制的,采用步进电机控制以及液晶显示,不同的设计部分在于检测器件的选取上。

 方案(一)的系统框图如图2.1:

 光检测

 键盘模块

  液晶模块 电源模块

  89C52

  温度检测

  图2.1

  方案(一)的原理框图

 方案(二)的系统框图如图2.2。

  光线采集模块 信号处理 DS1302时钟 DS18B20温度 手动按键输入 蜂鸣器报警 实时时钟显示 实时温度显示 电动机正反转 单片机

 图2.2

  方案(二)的原理框图

  方案(一)与方案(二)的区别主要在于检测器件的应用,方案(一)采用温度采集和声音检测元件,通过设定的温度来控制窗帘的开闭,以减少光照对室内的温度影响,利用声音控制虽然方便性有所提高,但是其误差较大。方案(二)采用的时钟模块实用性更强。综合考虑以上因素,系统设计采用方案(二)。

 2.2总体方案设计 自动窗帘控制系统总体方案设计是基于满足设计要求的前提并且根据理论上的可实现性和硬件上的经济实用性,而进行设计的重要环节。本章从人们对系统功能需求出发,在综合考虑各种因素的情况下,设计出自动控制系统的总体构架,并且在基本功能需求的基础上尽可能考虑系统的可扩展性。

 2.2.1系统基本功能 随着人民生活水平的不断提高,人们对家庭生活舒适性的需求越来越强烈,窗帘作为每个家庭生活中最必须的家居用品之一,自然也需要满足人民更舒适性的需求。窗帘最基本的作用无非是保护业主的个人隐私以及遮阳挡尘等功能,但传统的窗帘您必须手动去开关,每天早开晚关也是挺麻烦的,特别是别墅或复式房的大窗帘,比较长,而且重,用时需要很大的力才能开关窗帘,特别不方便;于是电动窗帘应运而生。现有的电动窗帘都可以自动开关闭窗帘,到了时间自动控制窗帘的开关,可以根据光的但是他们也有些缺点。窗帘控制器的自动开关如何让窗帘能够开关自如,停机的时间是否到位。

 电动窗帘主要有以下几大功能:(1)手动控制:该功能使电动窗帘具有手动正传、手动反转 和手动停止的功能。而且增加了工作状态指示,电机工作在正传、反转和停止状态的时候,发光二极管管均有不同工作状态指示。(2)自动控制:根据光照强弱来控制窗帘的打开与关闭。(3)时间控制 “天黑关闭,天亮打开”具有智能管理,不产生误动作。窗帘的正转、反转和停止功能可由单片机输出电平来控制步进电机的运转以实现。环境亮度的控制通过光敏电阻和运放组成的电路来控制单片机输出电平继而控制电机的正转和反转。时间自动控制可以由定时器来控制

 2.2.2系统总体结构设计 自动窗帘控制系统设计的总体框图如图2.3所示。

 光敏传感器 信号调节电路

 控制信号

 AT89C52 显示模块 键盘模块 步进电机

 图2.3

 电动窗帘控制器结构框图 根据光照来开闭窗帘主要原理是用光敏电阻采集外界的光强度,从光传感器采集的信号利用信号校正电路放大,滤波后输入单片机。传入的信号由89C52单片机来控制,并且做出响应,以实现电机的正转、反转与停止。显示模块是用来显示自动窗帘控制器的各种状态。键盘作为输入设备,通过不同按键来控制单片机进行各种运转状态。

  第3章 硬件分析与设计 3.1 AT89S52单片机及相关电路 3.1.1 AT89S52单片机概述 AT89S52的塑封图如图3.1所示,它为DIP40双列直插塑料封装。AT89S52作 为系统的核心控制元件,只有它能正常工作后才能使其它的元件进入正常工作状态。因此,下面对AT89S52进行必要的说明,AT89S52的管脚如图3.2所示。

  图3.1

 AT89C52封装图

 图3.2

 AT89s52引脚图 单片机电路在本系统中作为主控芯片首先对外部电路采集到的温度信号进行反应,发PWM信号给L297,然后通过L298驱动步进电机。同时按键扫描实现手动自动控制。

 用DS1302时钟芯片,DS18B20温度传感器,以及1602液晶,实现时间、温度的显示。以及闹钟、温度报警等功能。

 (1)VCC:40脚,供电电压,一般接+5V电压。

 (2)GND:20脚,接工作地。

 (3)P0口:1~8脚,P0口是一个8位漏极开路的双向I/O口。作为输出口,每位能驱动8个TTL逻辑电平。对P0端口写“1”时,引脚用作高阻抗输入。

 当访问外部程序和数据存储器时,P0口也被作为低8位地址/数据复用。在这种模式下,P0具有内部上电阻。但是P0口在程序校验作为输出指令字节时,需要外部加上拉电阻,一般上拉电阻选4.7K~10K为宜。本设计中用5.1K的排阻对P0口进行上拉电平。

 (4)P1口:32~39脚,P1口是一个内部具有上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4个TTL门电流。P1端口写入“1”后,被内部上拉电阻把端口拉高,此时可以作为作输入口使用。作为输入使用时,被外部拉低的引脚由于内部电阻的原因,将输出电流。

 (5)P2口:20~27脚,P2 口是一个具有内部上拉电阻的8 位双向I/O 口,P2 输出缓冲器能驱动4 个TTL 逻辑电平。对P2 端口写“1”时,内部上拉电阻把端口拉高,此时可以作为输入口使用。

 (6)P3口:10~17脚,P3 口是一个具有内部上拉电阻的8 位双向I/O 口,P3 输出缓冲器能驱动4 个TTL 逻辑电平。对P3 端口写“1”时,内部上拉电阻把端口拉高,此时可以作为输入口使用。

 (7)RESET:9脚,复位输入端。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。

 (8):30脚,当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于系统校验。

 (9)PSEN:29脚,外部程序存储器的选通信号。

 (10):31脚,访问外部程序存储器控制信号。当为低电平时,读取外部程序存储器;当端为高电平时,则读取内部程序存储器,设计中一般接高电平。

 (11)XTAL1:19脚,振荡器反相放大器和内部时钟发生电路的输入端。如采用外部时钟源时,XTAL1为输入端。

 (12)XTAL2:18脚,振荡器反相放大器的输出端。如采用外部时钟源时,XTAL2应悬空不接。

 3.2.2晶振电路 电路中的晶振即石英晶体震荡器。由于石英晶体震荡器具有非常好的频率稳定性和抗外界干扰的能力,所以,石英晶体震荡器是用来产生基准频率的。通过基准频率来控制电路中的频率的准确性。同时,它还可以产生振荡电流,向单片机发出时钟信号。

 图3.3是单片机的晶振电路。片内电路与片外器件就构成一个时钟产生电路,CPU的所有操作均在时钟脉冲同步下进行。片内振荡器的振荡频率非常接近晶振频率,一般多在1.2MHz~24MHz之间选取。C1、C2是反馈电容,其值在20pF~100pF之间选取,典型值为30pF。本电路选用的电容为30pF,晶振频率为12MHz。

 振荡周期=;

  机器周期

  指令周期T=。

  XTAL1接外部晶体的一个引脚,XTAL2接外晶体的另一端。在单片机内部,接至上述振荡器的反相放大器的输出端。采用外部振荡器时,对HMOS单片机,该引脚接外部振。在石英晶体的两个管脚加交变电场时,它将会产生一定频率的机械变形,而这种机械振动又会产生交变电场,上述物理现象称为压电效应。一般情况下,无论是机械振动的振幅,还是交变电场的振幅都非常小。但是,当交变电场的频率为某一特定值时,振幅骤然增大,产生共振,称之为压电振荡。这一特定频率就是石英晶体的固有频率,也称谐振频率。石英晶振起振后要能在XTAL2线上输出一个3V左右的正弦波,以便使MCS-51片内的OSC电路按石英晶振相同频率自激振荡。通常,OSC的输出时钟频率fOSC为0.5MHz-16MHz,典型值为12MHz或者11.0592MHz。电容C1和C2可以帮助起振,典型值为30pF,调节它们可以达到微调fOSC的目的。

  图3.3

 单片机晶振电路图 3.2.3复位电路 复位电路的主要功能是使单片机进行初始化,在初始化的过程中需要在复位引脚RST上加大于2个机器周期的高电平。复位后的单片机地址初始化为0000H,然后继续从0000H单元开始执行程序。在复位电路中提供复位信号,等到系统电源稳定后,再撤销复位信号。但是为了在复位按键稳定的前提下,电源稳定后还要经一定的延时才撤销复位信号,以防在按键过程中引起的抖动而影响复位。图3.4所示的 RST 复位电路可以实现上述基本功能。

  图3.4

 复位电路图 3.2.4时钟电路 DS1302芯片的接口电路如图3.5所示。

 图3.5

 时钟电路图 本设计使用的实时时钟电路芯片是美国DALLAS公司生产的一种高性能、低功耗、带RAM的实时时钟电路芯片DS1302,时钟芯片在本系统中除了起到时间的显示外,还在时间控制中起到重要作用,所以是必不可少的。

 其引脚如图3.14所示。VCC1为后备电源,VCC2为主电源。在主电源关闭的情况下,也能保持时钟的连续运行。DS1302由VCC1或VCC2两者中的较大者供电;当VCC2大于VCC1+0.2V时,VCC2给DS1302供电;当VCC2小于VCC1时,DS1302由VCC1供电。X1和X2是振荡源,外接32.768kHz晶振。是复位/片选线,通过把输 入驱动置高电平来启动所有的数据传送。

  3.14 DS1302引脚图 输入有两种功能。首先,接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,提供终止单字节或多字节数据的传送手段。当为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。如果在传送过程中置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。上电运行时在Vcc≥2.5V之前,必须保持低电平。只有在SCLK为低电平时,才能将置为高电平。I/O为串行数据输入输出端(双向),SCLK始终是输入端。本设计入端。本设计连接图如图3.15所示,其中C1和C2起微调晶振的作用。

 3.2.5温度检测器模块 温度是一种最基本的环境参数,人民的生活与环境的温度息息相关,DS18B20装置适用于人民的日常生活和工、农业生产用于温度测量。由半导体公司生产的DS18B20型单线智能温度传感器,属于新一代适配微处理器的智能温度传感器,可广泛用于工业、民用、军事等领域的温度测量及控制仪器、测控系统和大型设备中。它具有体积小,接口方便,传输距离远等特点。

  本系统中,DS18B20作为温度传感器,在本系统中可以实时的采集环境温度,并在液晶屏进行显示。当温度超过设定的上限时,进行温度报警。

 DS18B20的性能特点:①采用单总线专用技术,既可通过串行口线,也可通过其它I/O口线与微机接口,无须经过其它变换电路,直接输出被测温度值(9位二进制数,含符号位),②测温范围为-55℃-+125℃,测量分辨率为0.0625℃,③内含64位经过激光修正的只读存储器ROM,④适配各种单片机或系统机,⑤用户可分别设定各路温度的上、下限,⑥内含寄生电源。

  DS18B20内部结构主要由4部分组成:64位光刻ROM,温度传感器,非挥发的温度报警触发器TH和TL,配制寄存器。DS18B20的管脚排列如图2所示。

 光刻ROM中的64位序列号是出厂前被光刻好的,他可以看作是该DS18B20的地址序列码。64位光刻ROM的排列是:开始8位(28h)是产品类型标号,接着的48位是该DS18B20自身的序列号,最后8位是前面56位的循环冗余校验码(CRC=x8+x5+x4+1)。光刻ROM的作用是使每一个DS18B20都各不相同,这样就可以实现一根总线上挂接多个DS18B20的目的。

 采用数字温度传感器DS18B20,与传统的热敏电阻相比, 他能够直接读出被测温度并且可根据实际要求通过简单的编程实现9~12位的数字值读数方式。可以分别在93.75ms和750ms内完成9位和12位的数字量, 并且从DS18B20读出的信息或写入DS18B20的信息仅需要一根口线( 单线接口) 读写, 温度变换功率来源于数据总线, 总线本身也可以向所挂接的DS18B20供电, 而无需额外电源。因而使用DS18B20可使系统结构更趋简单,可靠性更高,成本更低。测量温度范围为~55℃~+125℃。C,在一10℃~+85℃。C范围内,精度为±0.5℃。DS1822的精度较差为±2℃。现场温度直接以“一线总线”的数字方式传输,大大提高了系统的抗干扰性。其引脚分布如图2-4所示

 图2-4 DS18B20引脚图 引脚功能如下: NC(1 、2 、6 、7 、8脚) :空引脚,悬空不使用。

 VDD(3脚):可选电源脚,电源电压范围3~5.5V。

 DQ(4脚):数据输入/输出脚,漏极开路,常态下高电平。

 3.2.5键盘电路 键盘在单片机应用系统中能实现向单片机输入数据,传送命令等功能,是人工干预单片机的主要手段。本设计中的键盘采用独立键盘式。SW1为调整时间以及温度、闹钟的进入、退出按键。SW2为选择调整时间、调整闹钟、调整温度报警上限。SW3为 加1键。SW4为 减 1 键。SW5为窗帘自动、手动控制切换。SW6为手动控制时打开与关闭的控制。

 如图3.6所示。

  图3.6 键盘接口电路 获取键盘信息的方法有2种,我们经常用到的是扫描法。在扫描法中,所有的行线固定为输出端口,并依次输出低电平;所有列线固定为输入端口,用来检测按键状态。当全部按键均松开时,从列线上检测不到行线输出的低电平。当某个按键按下时,只有在对应的行线输出低电平时才能在对应的列线端口检测到低电平。按键的触点在闭合和断开时均会产生抖动,这时触点的逻辑电平是不稳定的,如果不妥善处理,将会引起按键命令的错误执行或重复执行。一般消除抖动采用软件方法来解决,将在软件部分介绍这点。

 3.2.6 显示电路 液晶显示器以其微功耗、体积小、显示内容丰富、超薄轻巧的诸多优点,在各种小系统中得到了更广泛的应用。本设计中使用的液晶显示模块是LCD1602。图3.3所示为本设计LCD1602的连接图。

 图3.3 LCD1602连接图 LCD1602是一种用5x7点阵图形来显示字符的液晶显示器模块,它显示的容量为2行16个字。其实物如图3.4和图3.5所示,它的显示内容丰富、体积小、美观和易于控制都是本设计选择作为显示模块的原因。其引脚结构图如图3.6所示。

  图3.4

 LCD1602正面图

  图3.5

 LCD1602反面图

 图3.6

 LCD1602引脚结构图

 工作原理:线段的显示.点阵图形式液晶由 M 行×N 列个显示单元组成,假设 LCD 显示屏有64行,每行有 128列,每 8列对应 1 个字节的 8 个位,即每行由 16 字节,共 16×8=128个点组成,屏上 64×16 个显示单元和显示 RAM 区 1024 个字节相对应,每一字节的内容和屏上相应位置的亮暗对应。例如屏的第一行的亮暗由 RAM 区的 000H~00FH 的 16 个字节的内容决定,当(000)=FFH 时,则屏的左上角显示一条短亮线,长度为8个点;当(3FFH=FFH 时,则屏的右下角显示一短亮线;当(000H)=FFH,(001H)=00H,(002H)=FFH,(003H)=00H,…(00EH)=FFH,(00FH)=00H 时,则在屏的顶部显示一条由 8 段亮线和8 条暗线组成的虚线。这就是 LCD 显示的基本意思。

 字符的显示.当用 LCD 显示一个字符时就较复杂了,因为一个字符由 6×8 或 8×8点阵组成,即要找到和屏上某几个位置对应的显示 RAM区的 8 个字节,并且要使每个字节的不同的位为‘1’,其它的为‘0’,为‘1’的点亮,为‘0’的点暗,这样一来就组成某个字符。但对于内带字符发生器的控制器(如 T6963C)来说,显示字符就比较简单了,可让控制器工作在文本方式,根据在LCD 上开始显示的行列号及每行的列数找出显示 RAM对应的地址,设立光标,在此送上该字符对应的代码即可。

 汉字的显示.汉字的显示一般采用图形方式,事先从微机中提取要显示的汉字的点阵码,每个汉字占 32 字节,分左右两半部,各占 16 字节,左边为 1、3、5…,右边为 2、4、6…, 根据在 LCD 上开始显示的行列号及每行的列数可找出显示 RAM 对应的地址,设立光标,送上要显示的汉字的第一个字节,光标位置加 1,送第二字节,换行按列对齐,送第三字节…直到32字节显示完就可在 LCD 上得到一个完整的汉字。

 带中文字库的128X64是一种具有4位/8位并行、2线或3线串行多种接口方式,内部含有国标一级、二级简体中文字库的点阵图形液晶显示模块;其显示分辨率为128×64, 内置8192个16*16点汉字,和128个16*8点ASCII字符集.利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。可以显示8×4行16×16点阵的汉字. 也可完成图形显示.低电压低功耗是其又一显著特点。其中:

 第1脚:VSS为地电源。

 第2脚:VDD接5V正电源。

 第3脚:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。

 第4脚:RS为寄存器选择,高电平时选择数据寄存器,低电平时选择指令寄存器。

 第5脚:RW为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和RW共同为低电平时可以写入指令或者显示地址,当RS为低电平RW为高电平时可以读忙信号,当RS为高电平RW为低电平时可以写入数据。

 第6脚:E端为始能端,当E端由高电平变成低电平时,液晶模块执行命令。

 第7~14脚:D0~D7为8位双向数据线。

 第15~16脚:空脚。

 第17脚:复位端,低电平有效。

 第18脚:显示驱动电压输出端。

 第19脚:VDD背光电源正端+5V。

 第20脚:VDD背光电源负端。

 12864液晶模块内部的控制器共有11条控制指令,它的读写操作、屏幕和光标的操作都是通过指令编程来实现的。指令如下:

 指令1:清显示。指令码01H,光标复位到地址00H位置。

 指令2:光标复位。光标返回到地址00H。

 指令3:光标和现实模式设置I/D。光标移动方向,高电平右移,低电平左移 S:屏幕上所有文字是否左移或右移。高电平有效,低电平则无效。

 指令4:显示开关控制。D:控制整体显示的开与关,高电平表示开显示,低电平表示关显示C:控制光标的开与关,高电平表示有光标,低电平表示无光标 B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。

 指令5:光标或显示以为S/C。高电平时移动显示的文字,低电平时移动光标。

 指令6:功能设置命令 DL。高电平时为4位总线,低电平时为8位总线 N:低电平时为单行显示,高电平双行显示 。

 指令7:字符发生器RAM地址设置。

 指令8:DDRAM地址设置。

 指令9:读忙信号和光标地址 BF。为忙标志,高电平表示忙,此时模块不能接受命令或者数据,如果为低电平表示不忙。

 指令10:写数据。

 指令11:读数据。

  3.2.7光敏传感器 窗帘自动控制系统的光控功能是可以根据光照的强弱来自动控制窗帘的开闭的,因此需要用到光照传感元器件,在本设计中采用了光敏电阻。

 光敏电阻又称光导管,常用的制作材料为硫化镉,另外还有硒、硫化铝、硫化铅和硫化铋等材料。这些制作材料具有在特定波长的光照射下,其阻值迅速减小的特性。这是由于光照产生的载流子都参与导电,在外加电场的作用下作漂移运动,电子奔向电源的正极,空穴奔向电源的负极,从而使光敏电阻器的阻值迅速下降。光敏电阻属半导体光敏器件,除具灵敏度高,反应速度快,光谱特性及r值一致性好等特点外,在高温,多湿的恶劣环境下,还能保持高度的稳定性和可靠性,可广泛应用于照相机,太阳能庭院灯,草坪灯,验钞机,石英钟,音乐杯,礼品盒,迷你小夜灯,光声控开关,路灯自动开关以及各种光控玩具,光控灯饰,灯具等光自动开关控制领域。

 应用光控原理工作,天亮窗帘自动打开,天黑窗帘自动关闭。由运放组成比较电路,同向输入端有两个电阻分压得到一个电压值,作为基准电压进行比较,而反相输入端用一个光敏电阻对外部环境的光线进行采集,利用光敏电阻暗时电阻大,亮时电阻小的特点,来确定反向输入端的电压值。再两者进行比较,比较后的信号再送入单片机AT89S52的P1^3口,从而通过单片机来控制电机的正反转。来实现天亮窗帘自动打开,天黑窗帘自动关闭这一自动控制功能。

 。

 光敏电阻连接如图3.11所示。

 图3.11 光敏传感器 3.2.9 步进电机 步进电动机是一种将电脉冲信号转换成角位移或线位移的机电元件。步进电动机的输入量是脉冲序列,输出量则为相应的增量位移或步进运动。正常运动情况下,它每转一周具有固定的步数;做连续步进运动时,其旋转转速与输入脉冲的频率保持严格的对应关系,不受电压波动和负载变化的影响。下图为步进电机运行原理框图。

  控制 指令 脉冲控制单元 反馈与保护 功率驱动电路单元

  步进电机

 在步进电机控制电路中,步进控制器的作用是把输入脉冲转换成环型脉冲,以控制步进电机的转向。在实际应用中由软件代替步进控制器,其优点是使线路简化,降低成本,可靠性提高。在窗帘控制系统中选用了型号为130HZ308-450的三相反应式步进电机,其优点是力矩大,精度高,其步进角度是1.2°。步进电机电路与单片机的连接如图3.12。

 图3.12

 步进电机电路与单片机的连接

 第4章 程序分析与设计

 系统软件设计主要有几部分组成,其中包括显示子程序,按键子程序,定时时钟程序,步进电机控制程序等。本章介绍了自动窗帘控制系统的主程序以及各主要部分功能程序的设计过程,程序代码详见附录。

 4.1 主程序设计 主程序构成无限循环,主要完成单片机初始化,关中断,菜单显示内容初始化,按键扫描,电机运行,计时等功能。

 主程序的流程图如图4.1所示。

  图4.1

 主程序流程图

 启动主程序,先关中断并且设置堆栈,接着初始化寄存器,初始化显示内容;然后执行按键查询,执行相应的操作。如果是设定键,则设定时间,开始计时;到时间后步进电机开始相应的工作,工作完成后停机。如果是电机控制键,则也执行相应的工作。如果都不是,则是复位键,采取复位操作。

 4.2 主要功能子程序设计 4.2.1 步进电机程序设计

 步进电机程序设计的主要任务是:

  ★ 判断旋转方向; ★ 按顺序传送控制脉冲; ★ 判断所要求的控制步数是否传送完毕。

 图4.2.1

 步进电机工作流程图 4.2.2 显示程序 显示程序开始后,起始地址60H发送到R0,01H发送至显示位代码R2,再将位代码发送到单片机A口,,单片机取显示数据查表转换成显示代码发送至单片机B口,延时2ms,指针R0加1,然后判断6显示是否完成。如果完成则返回,没完成则位代码R2左移一位,继续显示查表,一直到6位显示完成后返回。

 显示子程序流程图如图4.2.2所示。

  图4.2.2

 显示部分流程图 4.2.3 键盘程序设计 按键的触点在闭合和断开时均会产生抖动,这时触点的逻辑电平是不稳定的,如不妥善处理,将会引起按键命令的错误执行或者重复执行。现在用软件延时的方法来避开抖动阶段。在判断是否有键闭合后都延时5ms,按下键后再延时12ms就可以避免键盘的抖动。然后键码分析,执行相应的模块,显示后返回。

 键盘子程序如图4.2.3所示。

  图4.2.3

 键盘程序流程图 4.2.4 定时程序设计 定时的主要功能是在设定时间单片机能够得到中断信号,从而控制窗帘的开关。时钟发出50ms的信号给单片机,计数器计数,当计数到20,则过了1秒,秒单元数值加1,当秒单元到达60,分单元数值加1,秒单元清零。当时单元到达24,时单元清零。标志1天时间计满,把他们的值放到存储单元的指定单元。图4.2.4是定时功能流程图。

  图4.2.4

 定时功能流程 4.2.6 DS18B20测温流程图 DS18B20的测温原理如图2-5所示,图中低温度系数晶振的振荡频率受温度影响很小,用于产生固定频率的脉冲信号送给计数器1。高温度系数晶振随温度变化其振荡率明显改变,所产生的信号作为计数器2的脉冲输入。计数器1和温度寄存器被预置在-55℃所对应的一个基数值。计数器1对低温度系数晶振产生的脉冲信号进行减法计数,当计数器1的预置值减到0时,温度寄存器的值将加1,计数器1的预置将重新被装入,计数器1重新开始对低温度系数晶振产生的脉冲信号进行计数,如此循环直到计数器2 计数到0时,停止温度寄存器值的累加,此时温度寄存器中的数值即为所测温度。斜率累加器用于补偿和修正测温过程中的非线性,其输出用于修正计数器1的预置值。DS18B20在正常使用时的测温分辨率为0.5℃,如果要更高的精度,则在对DS18B20测温原理进行详细分析的基础上,采取直接读取DS18B20内部暂存寄存器的方法,将DS18B20的测温分辨率提高到0.1~0.01℃。

 图2-5 测温流程图

  总结

 本次设计系统地介绍了自动窗帘控制系统的硬件电路设计以及软件设计。在总体方案设计中以光敏电阻作为传送信号的传感器,用步进电机作为信号输出的执行元件,89C52单片机作为主要的控制元器件,并且应用了按键以及和显示电路。应用89C52单片机的优势减少了硬件的复杂性,光敏电阻接收外界光照信号,经过A\D转换后,传送给单片机一个电信号,单片机经过处理后,控制步进电机做出相应的动作,以控制窗帘的开闭。在实现一般应用的基础上,又添加了定时元器件电路,使窗帘的自动化性能得到进一步提升。光敏电阻的良好感光性以及步进电机的结构简单,控制方便的优点使窗帘控制开关更加稳定。

 本次毕业设计的整个研究与设计过程包括选题、设计以及完善等。首先,在选题方面查阅了很多与题目有关的资料和课题并且制定设计方案,进行设计的总体规划,然后将这些方案落实到设计环节中。其次,在制定的方案基础上运用所学的知识对硬件以及软件进行设计,并用相关软件进行仿真设计。最后,对设计内容进一步修缮,以求达到最佳设计结果。虽然设计内容完成了基本的功能,但是其中还是存在一定欠缺,比如在设计中没有考虑到窗帘工作方式的显示以及没有添加类似红外遥控的设计等。

 此次设计过程中,在完成设计任务之外也让我系统性地认识和全面地掌握了单片机相关技术,从本次毕业设计中我更加深刻地认识到理念来源于实际的含义。在和同学以及老师的就相关问题的互相讨论交流中,我认识到自己的很多不足,但在这些不足中我又学到了很多知识,使我的综合应用能力有了很大提高。

  致 谢

 经过这么长时间的忙碌,毕业设计和论文已经接近尾声。在毕业设计的过程中,由于经验的缺乏以及知识的局限性,难免有许多考虑不周全的地方,在选题,设计等方面,如果没有导师的督促指导,没有同学们的支持和帮助,单独完成这个设计,其中还是有一定难度的。在论文完稿之际,我想借此机会对在完成毕业设计期间关心、帮助、支持和鼓励过我的老师、同学以及朋友们致以最诚挚的谢意和最衷心的祝福! 首先我要感谢的是我的导师老师,在完成整个毕业设计的过程中,老师给我提供了很大的帮助,在选题、设计以及修改论文的各个环节里老师给我指出了很多错误,提出了很多宝贵意见,对于设计中存在的问题也是耐心的回答和指导,让我能够顺利的完成毕业设计。在此谨向老师致以诚挚的谢意和崇高的敬意。

  其次要感谢的是所有在大学四年中教育指导过我的所有老师,你们传授给我的专业知识是我完成本设计的基础,也是日后踏入工作岗位的重要基石,对于老师们一丝不苟,兢兢业业的精神表示衷心的感谢。

 最后我还要向所有关心和支持我学习的朋友和同学们表示真挚的谢意!感谢你们对我的关心、关注和支持。

  参 考 文 献

 [1] 姚福安.电子电路设计与实践.济南:山东科学技术出版社,2005. [2] 何西才,杨静,任力英. 实用传感器接口电路实例. 北京:中国电力出版社,2007 [3] 刘守义. 单片机应用技术. 陕西:西安电子科技大学出版社,2007 [4] 李广第. 单片机基础. 北京:北京航空航天大学出版社,2001 [5] 瞿贵荣.电动窗帘红外遥控电路.家庭电子,2005,2:35-36 [6] 王丽君,杨伟丰. 电机无线遥控系统设计的研究大众科技,2009,11:124-125 [7] 张培志,陆伟. 仇芝基于单片机技术的无线遥控家居照明系统.仪器仪表用户,2008 [8] 刘大茂.智能仪器:单片机应用系统设计.北京:航空工业出版社,1998 [9] 周航慈,朱兆优. 智能仪器原理与设计. 北京:北京航空航天大学出版社,2005 [10] 刘印春. 传感器原理. 北京国防科技大学出版社,2006 [11] 孟志永.单片机外围电路设计.北京:电子工业出版社,2004 [12] 王晓明. 电动机的单片机控制. 北京:北京航空航天大学出版社,2002 [13] 沙占有. 中外集成传感器实用手册. 北京:电子工业出版社,2005 [14] 胡汉才. 单片机原理及其接口技术. 北京:清华大学出版社,2003 [15] 吕俊芳. 传感器接口与检测仪器电路. 北京:北京航空航天大学出版社,1995 [16]

 HI-TECH Software.PIC C User’s Manual.www.htsoft.com. [17]

 S.L.Loyka.A Simple Formula for the Ground Resistance Calculation. IEEE Trans.On

 Electromagnetic Compatibility, 1999, 41(2): 152-154. [18]

 Mocrochip Technology Inc. . Microchip 2006 Product Selector Guide. 2006. [19] W.Harold Parady, J.Howard Turnered. Electric Motors. Georgia:the american association For vocational instructional materials, 1978. [20] John B. Peatman.Design With PIC Microcontrollers.Prentice-Hall Inc, 1997. [21] Jullian , E,Electromagnetic radiation.RBM-Revue Europeenne de technologie Biomedicale,

 Vol.20 NO.4.June,1998.

 附录一:系统原理图

 附录二:程序清单 第一部分:

 /************使用LCD1602、DS1302时钟芯片、DS18B20温度传感器完成该日历**************/ #include<reg52.h>

 //以下的顺序不能任意放

 #define uint unsigned int //宏定义

 #define uchar unsigned char #include"LM016L.h"

 #include"DS1302.h" #include"DS18B20.h" #include"KeyScan.h" #include"MODE.h" #include"OPEN.h" #include"moter.h"

 ////////以下为几个标志位/////////// // flag,select,alarm,temperature,limit

 /*分别为模式标志位、功能选择标志位、闹钟、温度正负标志位以及温度上限值 (整型)

 其中alarm有三种状态:0为禁止进入,1为允许进入,2为正在闹钟模式下

 */

  void KeyScan();

  //键盘扫描

 void SetTime_Mode();

 //调时

 void SetRing_Mode();

 //闹钟设置

 void SetTemp_Mode();

 //温度上限设置模式

 /******************************日历主函数************************************/ void main() {

 a=0;

  n=1;

 mm=1;

 LED1=LED2=LED3=LED4=LED5=1;

 init();

 //初始化LCD

  Set_RTC(l_tmpdate1);//初始化时钟芯片

 LM297_Init();

 write_com(0x01);

  //清屏

  while(1)

  {

 mm=m_flag;

 time_date();

 //时间处理

  KeyScan();

  //键盘扫描

 MANATUO();

  openshart();

  if(MANATUO()==1)

  //

  手动

  {

 if(openshart()==1 && m_flag==0)

  //开启信号。并且 窗子是关闭的 则打开。

 {

  m_flag=1;

  EN=1;CW=1;

  for(m=0;m<500;m++)

  {

 CLK_Out();

 if(m>0&&m<100){ LED1=1;LED2=0;LED3=0;LED4=0;LED5=0;}

  if(m>100&&m<200){ LED1=1;LED2=1;LED3=0;LED4=0;LED5=0;}

  if(m>200&&m<300){ LED1=1;LED2=1;LED3=1;LED4=0;LED5=0;}

  if(m>300&&m<400){ LED1=1;LED2=1;LED3=1;LED4=1;LED5=0;}

  if(m>400&&m<500){ LED1=1;LED2=1;LED3=1;LED4=1;LED5=1;}

 }

  EN=0;

 }

 else if (openshart()==0&&m_flag==1)

 {

 m_flag=0;

 EN=1;CW=0;

 for(m=0;m<500;m++)

 {

 CLK_Out();

  if(m>0&&m<100){ LED1=1;LED2=1;LED3=1;LED4=1;LED5=0;}

  if(m>100&&m<200){ LED1=1;LED2=1;LED3=1;LED4=0;LED5=0;}

  if(m>200&&m<300){ LED1=1;LED2=1;LED3=0;LED4=0;LED5=0;}

  if(m>300&&m<400){ LED1=1;LED2=0;LED3=0;LED4=0;LED5=0;}

  if(m>400&&m<500){ LED1=0;LED2=0;LED3=0;LED4=0;LED5=0;}

  }

 EN=0;

  }

  }

  if(MANATUO()==0)

  //自动

  {

 if(time_flag==1&&m_flag==1)

  { m_flag=0;

 EN=1;CW=1;

  for(m=0;m<500;m++)

  {

 CLK_Out();

 if(m>50&&m<100){ LED1=1;LED2=1;LED3=1;LED4=1;LED5=0;}

  if(m>150&&m<200){ LED1=1;LED2=1;LED3=1;LED4=0;LED5=0;}

  if(m>250&&m<300){ LED1=1;LED2=1;LED3=0;LED4=0;LED5=0;}

  if(m>350&&m<400){ LED1=1;LED2=0;LED3=0;LED4=0;LED5=0;}

  if(m>450&&m<500){ LED1=0;LED2=0;LED3=0;LED4=0;LED5=0;}

  }

  EN=0;

  }

 if(m_flag==0&&m_flag==1)

  {

  }

  if(signal==1&&m_flag==1&&time_flag==0)

 //自动关闭

 { m_flag=0;

  EN=1;CW=1;

  for(m=0;m<500;m++)

  {

 CLK_Out();

 if(m>50&&m<100){ LED1=1;LED2=1;LED3=1;LED4=1;LED5=0;}

  if(m>150&&m<200){ LED1=1;LED2=1;LED3=1;LED4=0;LED5=0;}

  if(m>250&&m<300){ LED1=1;LED2=1;LED3=0;LED4=0;LED5=0;}

  if(m>350&&m<400){ LED1=1;LED2=0;LED3=0;LED4=0;LED5=0;}

  if(m>450&&m<500){ LED1=0;LED2=0;LED3=0;LED4=0;LED5=0;}

  }

  EN=0;

  }

  else if(signal==0&&m_flag==0&&time_flag==0)

 //自动打开窗帘

 { m_flag=1;

  EN=1;CW=0;

  for(m=0;m<500;m++)

 {

 CLK_Out();

 if(m>50&&m<100){ LED1=1;LED2=0;LED3=0;LED4=0;LED5=0;}

  if(m>150&&m<200){ LED1=1;LED2=1;LED3=0;LED4=0;LED5=0;}

  if(m>250&&m<300){ LED1=1;LED2=1;LED3=1;LED4=0;LED5=0;}

  if(m>350&&m<400){ LED1=1;LED2=1;LED3=1;LED4=1;LED5=0;}

  if(m>450&&m<500){ LED1=1;LED2=1;LED3=1;LED4=1;LED5=1;}

  }

 EN=0;

  }

  }

  if(ring_time[1]==l_tmpdate[1]&&ring_time[2]==l_tmpdate[2]&&flag==0&&alarm!=0)//判断是否到闹钟设置的时间,是的话执行相应动作

 {

 uchar i;

 alarm=2;

 //正在闹钟响应模式下

 if(ring_time[0]==l_tmpdate[0])

 //相等的一秒那一时刻清屏,循环清屏会导致闪烁

 write_com(0x01);

  for(k=0;k<500;k++)

  {led=0;

 // 蜂鸣器

 s_delay(1);

 led=1;

 s_delay(1);

  }

 write_com(0x80+0x01); //写入“Time To Get Up”

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

 {

  write_date(ringtable[i]);

  }

 if(l_tmpdate[0]==0x59) //自动退出闹钟模式时清屏

 write_com(0x01);

 continue;

  //跳出本次的While循环

  }

  if(flag==0)

 //正常显示模式下

 {

 tempchange();

 //温度转换命令

 display(l_tmpdisplay,8);//显示时间

  Temp_Display(); //显示温度

 deal();

 //温度处理

 }

  if(flag==1)

 //功能选择模式下

 {

  uchar i;

 write_com(0x80+0x4);

 //选择菜单

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

 {

  write_date(menu[select][i]);

  }

 if(select==0)

  //调试模式

  {

 SetTime_Mode();

 }

 if(select==1)

  //闹钟设置

  {

  SetRing_Mode();

 }

 if(select==2)

 //设置温度上限

  {

  SetTemp_Mode();

  }

  }

 }

  } /***************END***********END******************************/ 第二部分:

 /********************LCD相关程序***************************/

 sbit rs=P2^5; // LCD数据/命令选择端

 sbit rw=P2^6; //LCD读写选择端

 sbit e=P2^7; //LCD使能信号

 void

 delay(uchar z); //延时函数

 void init();

  // LCD初始化函数

 void write_com(uchar com); //LCD写命令

 void write_date(uchar date); //LCD写数据

 void init()

  //LCD初始化函数

 {

 e=0;

 write_com(0x38);//显示模式的设置

  delay(1);

 write_com(0x0c);//开显示,光标显示

  delay(1);

 write_com(0x06);//光标位置

  delay(1);

 write_com(0x01);

  //清显示

  delay(1); } void write_com(uchar com)

 //LCD写命令

 {

 rs=0;

 rw=0;

 P0=com;

 delay(1);

 e=1;

 delay(1);

 e=0;

 } void write_date(uchar date)

 //LCD写数据

 {

 rs=1;

 rw=0;

 P0=date;

 delay(1);

 e=1;

 delay(1);

 e=0;

 } void

 delay(uchar z) //延时函数

 {

 uchar x,y;

 for(x=0;x<z;x++)

  for(y=0;y<110;y++);

 }

 /***************END***********END******************************/ 第三部分:

 /***************时钟芯片相关程序*************************/

  char mm;

  char time_flag;

 sbit rst=P1^7; //时钟芯片复位端

 sbit sck=P1^5; // 时钟信号

 sbit io=P1^6; // 时钟输入/输出端

 void Write_Ds1302_Byte(uchar temp);//写入一个字节

 void Write_Ds1302(uchar address,uchar dat);//写入

 uchar Read_Ds1302 ( uchar address );

  //读取时间

  void Read_RTC(void);

 //读取日历

 void Set_RTC(uchar *p);

 //设定日历

 void time_date();

 //时间数据处理

 void display(uchar *lp,uchar lc); //显示时间

 uchar code table0[]="0123456789-"; uchar code table1[]="AUTOMANUOFON"; uchar code table2[]="0123456789:"; code uchar write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //写入时钟芯片的地址,顺序同上

 code uchar read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; //以上是读出数据的地址

 uchar code l_tmpdate1[7]={0x50,0x30,0x15,0x20,0x04,0x04,0x12}; /*初始化时钟芯片,依次是秒分时日月星期年,用16进制的BCD码表示 */ uchar

 l_tmpdate[7],l_tmpdisplay[18],SetTime[18],ring_time[7];

  void Write_Ds1302_Byte(uchar temp) //写入一字节数据

 {

 uchar i;

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

 //循环8次写入数据 ,上升沿写入

 {

  sck=0;

 io=temp&0x01;

 //每次传输低字节

  temp>>=1;

 //右移一位

 sck=1;

 } } void Write_Ds1302(uchar address,uchar dat)//写入

 {

 rst=0;

 delay(1);

  sck=0;

 delay(1);

  rst=1;

 delay(1);

  //启动

 Write_Ds1302_Byte(address); //发送地址

 Write_Ds1302_Byte(dat);

 //发送数据

 rst=0;

 //恢复

 } uchar Read_Ds1302 (uchar address)

  //读取时间

 {

  uchar i,time=0x00;

  rst=0;

 delay(1);

  sck=0;

 delay(1);

  rst=1;

 delay(1);

  Write_Ds1302_Byte(address);

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

  //循环8次 读取数据

 {

 if(io)

 time|=0x80;

  //每次传输低字节

 sck=1;

 //时钟下降沿读入数据

 time>>=1;

  //右移一位

 sck=0;

  }

 rst=0;

 delay(1);

 //以下为DS1302复位的稳定时间

 rst=0;

 sck=0;

 delay(1);

 sck=1;

 delay(1);

 io=0;

 delay(1);

 io=1;

 delay(1);

 return (time);

  }

  void Read_RTC()

 //读取 日历

 {

 uchar i,*p;

 p=read_rtc_address;

 //地址传递

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

 //分7次读取 年月日时分秒星期

  {

  l_tmpdate[i]=Read_Ds1302(*p);

  p++;

 } }

 void Set_RTC(uchar *P1302)

 //设定 日历

 {

 uchar i,*p;

  Write_Ds1302(0x8E,0X00);

  //允许写入

 p=write_rtc_address; //传地址

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

 //7次写入 年月日时分秒星期

 {

  Write_Ds1302(*p,P1302[i]);

  p++;

  }

  Write_Ds1302(0x8E,0x80); //禁止写入

 }

 void time_date()

 //时间数据处理

  {

 Read_RTC();

 l_tmpdisplay[0]=l_tmpdate[2]/16;//时

 l_tmpdisplay[1]=l_tmpdate[2]&0x0f;

 l_tmpdisplay[2]=10;

  //加入":"

 l_tmpdisplay[3]=l_tmpdate[1]/16;//分

  l_tmpdisplay[4]=l_tmpdate[1]&0x0f;

 l_tmpdisplay[5]=10;

 l_tmpdisplay[6]=l_tmpdate[0]/16;//秒

  l_tmpdisplay[7]=l_tmpdate[0]&0x0f;

  l_tmpdisplay[8]=2;

 //显示2008的2

 l_tmpdisplay[9]=0;

  //显示2008的第一个0

  l_tmpdisplay[10]=l_tmpdate[6]/16; //年

  l_tmpdisplay[11]=l_tmpdate[6]&0x0f;

 l_tmpdisplay[12]=10;

  //加入“-”

  l_tmpdisplay[13]=l_tmpdate[4]/16;//月

  l_tmpdisplay[14]=l_tmpdate[4]&0x0f;

 l_tmpdisplay[15]=10;

 l_tmpdisplay[16]=l_tmpdate[3]/16;//日

  l_tmpdisplay[17]=l_tmpdate[3]&0x0f;

  if(l_tmpdisplay[0]==0 && ( l_tmpdisplay[1]>=0&&l_tmpdisplay[1]<=5)||l_tmpdisplay[0]==2&&(l_tmpdisplay[1]>=0&&l_tmpdisplay[0]<=4))

 {

  time_flag=1;

 }

 else

  {time_flag=0;}

 }

 void display(uchar *lp,uchar lc)

  //显示时间

 {

 unsigned char i;

 //定义变量

  write_com(0x80);

 //液晶第一行显示时间和星期

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

 {

  write_date(table2[lp[i]]);

 delay(1);

 }

  write_com(0x80+0x09);

 switch(MANATUO())

  {

  case 0: write_date(table1[0]);

  write_date(table1[1]);

  write_date(table1[2]);

  write_date(table1[3]);

  break;

  case 1:

 write_date(table1[4]);

  write_date(table1[5]);

  write_date(table1[6]);

  write_date(table1[7]);

  break;

 }

 write_com(0x80+0x0e);

 switch(mm)

 {

  case 0:write_date(table1[8]);

 write_date(table1[9]);

  case 1: write_date(table1[10]);

 write_date(table1[11]);

 }

  write_com(0x80+0x40);

 //第二行显示年

  for(i=8;i<lc+10;i++)

 {

  write_date(table0[lp[i]]);

 delay(1);

 } } /***************END***********END******************************/ 第四部分:DS18B20.H /***************温度传感器相关程序******************/

 sbit ds=P1^4;

 //温度传感器信号线

 sbit led=P3^7;

 //小灯位定义

 uchar temperature; uint temp,limit=350;

 // 整型温度值

 float f_temp;

 //浮点型温度值

 uint get_temp();

 //获得温度

 void tempchange(void);

  //转换温度

 void dsreset(void);

 //DS18B20复位 bit tempreadbit(void);

  //读DS118B20一位 uchar tempreadbyte(void);

  //读DS18B20一个字节

 void tempwritebyte(uchar dat);

 //写入DS18B20一个字节

 void deal();

  //温度处理函数

  void Temp_Display();

  //温度显示

 uchar code table[]="0123456789.C ";

 uint

 k;

 void dsreset(void)

 //DS18B20复位,初始化函数

 {

 uint i;

 ds=0;

 i=103;

 while(i>0)i--;

 ds=1;

 i=4;

 while(i>0)i--;

 } bit tempreadbit(void) //读一位数据函数

 {

 uint i;

 bit dat;

 ds=0;i++;

  //i++起延时的作用

  ds=1;i++;i++;

 dat=ds;

 i=8;while(i>0)i--;

 return(dat);

 } uchar tempreadbyte(void) //读一个字节数据函数

 {

 uchar i,j,dat;

 dat=0;

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

 {

  j=tempreadbit();

  dat=(j<<7)|(dat>>1);

 //读出的数据最低位在最前面

  }

 return(dat); } void tempwritebyte(uchar dat) {

  //写一个字节数据函数

  uint i;

 char j;

 bit testb;

 for(j=1;j<=8;j++)

 {

  testb=dat&0x01;

  dat=dat>>1;

  if(testb)

  //写1

 {

 ds=0;

 i++;i++;

 ds=1;

 i=8;while(i>0)i--;

  }

  else

  //写0

 {

 ds=0;

 i=8;while(i>0)i--;

 ds=1;

 i++;i++;

  }

 }

 } void tempchange(void)

 //DS18B20开始获取温度并转换

 {

 dsreset();

 delay(1);

 tempwritebyte(0xcc);

  //写跳过读ROM指令

  tempwritebyte(0x44);

 //写温度转换指令

  } uint get_temp()

 //读取寄存器中存储的温度数据

 {

 uchar a,b;

 dsreset();

 delay(1);

 tempwritebyte(0xcc);

  //跳过RAM,适用于一个从机工作

  tempwritebyte(0xbe);

 //读RAM内部9字节的温度数据

  a=tempreadbyte();

 //读低8位

 b=tempreadbyte();

  //读高8位

 temp=b;

 temp<<=8;

 temp=temp|a;

  //两个字节组合为一个字

 if((b&0x80)!=0)

 //判断温度是否为负

  {

  temperature=1;

 //temperature为1表示温度为负

 temp=~temp+1;

 //若温度为负,则取其补

  }

 else temperature=0;

  f_temp=temp*0.0625;

 // 温度在寄存器中为12位,分辨率为0.0625

 temp=f_temp*10+0.5;

 //乘以10表示小数点后面只取1位,加0.5是四舍五入

 // f_temp=f_temp+0.05;

 return temp;

 } void Temp_Display()

 //温度显示函数

 {

 if(get_temp()/1000==1)

 //温度上百时

  {

 write_com(0x80+0x40+0x0a); //温度的百位

  write_date(table[get_temp()/1000]);

 write_com(0x80+0x40+0x0b);

 write_date(table[get_temp()%1000/100]);

 //十位

 }

 if(get_temp()/1000==0)

 //温度未上百

  {

 write_com(0x80+0x40+0x0a);

 if(temperature==1)

 write_date('-');

  //若温度为负则前面显示“-”

  else

  write_date(' '); //若温度的百位为0且正则不显示

  write_com(0x80+0x40+0x0b);

 write_date(table[get_temp()/100]);

 //十位

  }

  write_com(0x80+0x40+0x0c);

 write_date(table[get_temp()%100/10]); //个位

 write_com(0x80+0x40+0x0d);

 write_date(table[10]);

 write_com(0x80+0x40+0x0e);

 write_date(table[get_temp()%10]);

 //十分之一位

  write_com(0x80+0x40+0x0f);

 write_date(table[11]);

 } void

 s_delay(uchar z) //延时函数

 {

 uchar x,y;

 for(x=0;x<z;x++)

  for(y=0;y<30;y++);

 }

 void deal()

  //温度处理函数

 {

  if(get_temp()>limit)

  //当温度超过设定的上限值时

  { for(k=0;k<100;k++)

  {led=0;

  s_delay(1);

  led=1;

  s_delay(1);

  }

  } }

 /***************END***********END******************************/

 第五部分:Keyscan.h

 /****************键盘扫描函数***********************/

 sbit key1=P2^4;

 //键盘位定义

 sbit key2=P2^3; sbit key3=P2^2; sbit key4=P2^1;

 uchar flag,select,alarm=1;

 void KeyScan() { /////////进入/退出模式键被按下///////////

 if(key1==0)

 {

  write_com(0x01);

 //清屏

 if(alarm==2)

 //闹钟到时间

 {

 alarm=0;

 //退出闹钟模式,并且禁止进入

 }

  else

  {

  flag++;

 //模式间的转换

  if(flag>=2) { flag=0; select=0;}

 }

  while(!key1); //检测键盘是否释放,下同

  } /////////功能选择键被按下///////////

 if(key2==0&&flag==1)

 {

  write_com(0x01);

  //清屏

 select++;

  if(select>=3)

 { select=0; write_com(0x01); }

  while(!key2);

 } /////////时加/温度加一键被按下///////////

 if(key3==0)

 {

  if(select==0&flag==1)

 //调试模式下

 { uchar j,shi1,shi2;

  for(j=0;j<6;j++)

  //重新读当前时间

  {

 SetTime[j]=l_tmpdate[j];

 }

 shi1=SetTime[2]>>4; shi2=SetTime[2]&0x0f;

 shi2++;

 if(shi2>9)

 {

 shi2=0;

 shi1++;

 }

 if(shi1==2&&shi2==4)

 { shi1=0;

 shi2=0; }

 SetTime[2]=16*shi1+shi2;

 //写入数组

 Set_RTC(SetTime);

  }

 if(select==1&&flag==1)

 // 闹钟设置模式下

  {

  uchar shi1,shi2;

 alarm=1;

  //允许进入闹钟模式

  shi1=ring_time[2]>>4; shi2=ring_time[2]&0x0f;

  shi2++;

  if(shi2>9)

  {

  shi2=0;

  shi1++;

  }

  if(shi1==2&&shi2==4)

 { shi1=0;

 shi2=0; }

  ring_time[2]=shi1*16+shi2;

 //写入数组

  }

 if(select==2&&flag==1)

 //上限温度值加一

  {

  limit+=10;

 if(limit>1270)

  limit=0;

 write_com(0x01);

 }

  while(!key3);

  } /////////分加/温度减一键被按下///////////

 if(key4==0)

 //分加一键

  {

 if(select==0&flag==1)

 //调时模式下

  {

  uchar j,fen1,fen2;

  for(j=0;j<6;j++)

  //重新读当前时间

 {

  SetTime[j]=l_tmpdate[j];

  }

  fen1=SetTime[1]>>4;

 fen2=SetTime[1]&0x0f;

  fen2++;

  if(fen2>=10)

  {

  fen2=0;

  fen1++;

  }

  if(fen1>=6)

 {fen1=0;}

 SetTime[1]=fen1*16+fen2;

 //写入数组

  Set_RTC(SetTime);

 }

  if(select==1&&flag==1)

 // 闹钟设置模式下

  {

  uchar fen1,fen2;

 alarm=1;

  //允许进入闹钟模式

  fen1=ring_time[1]>>4; fen2=ring_time[1]&0x0f;

 fen2++;

  if(fen2>9)

  {

  fen2=0;

  fen1++;

  }

  if(fen1>=6)

 { fen1=0; }

  ring_time[1]=fen1*16+fen2;

 //写入数组

  }

  if(select==2&&flag==1)

 //温度上限值减一

 {

  limit-=10;

 if(limit<=0)

  limit=1270;

 write_com(0x01);

 }

 while(!key4);

 } } /***************END***********END******************************/ 第六部分:Mode.h

 /*********************功能模式函数*****************************/

 uchar code menu[3][9]={{"Time Set"},{"Ring Set"},{"Temp Set"}}; uchar code ringtable[14]="Time To Get Up"; //闹钟显示

  void SetTime_Mode()

  //调时模式

 {

 uchar i;

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

 {

  SetTime[i]=l_tmpdate[i];

 }

 write_com(0xc0+5);

  write_date(table2[SetTime[2]>>4]);

  //读时的第一位

 write_date(table2[SetTime[2]&0x0f]); //读时的第二位

 write_date(':');

  write_date(table2[SetTime[1]>>4]);

  //读分的第一位

 write_date(table2[SetTime[1]&0x0f]); //读分的第二位

 } void SetRing_Mode()

  //闹钟设置

 {

 write_com(0xc0+5);

 write_date(table2[ring_time[2]>>4]);

  //读时的第一位

 write_date(table2[ring_time[2]&0x0f]); //读时的第二位

 write_date(':');

  write_date(table2[ring_time[1]>>4]);

  //读分的第一位

 write_date(table2[ring_time[1]&0x0f]); //读分的第二位

  } void SetTemp_Mode()

 //温度上限设置模式

  {

  if(limit/1000)

  //若温度百位为0则不显示

 {

 write_com(0xc0+5);

 write_date(table[limit/1000]);

  }

 write_com(0xc0+6);

 write_date(table[limit%1000/100]);

 write_com(0xc0+7);

 write_date(table[limit%100/10]);

 write_com(0xc0+8);

 write_date('.');

 write_com(0xc0+9);

 write_date('0');

 write_com(0xc0+0x0a);

 write_date('C');

 } /***************END***********END******************************/

 第七部分:moter.h sbit CLK

 = P1^0; sbit CW

  = P1^1; sbit EN

  = P1^2;

 int a;

  int n;

  char m_flag=1;

  //窗帘状态 0 关 1开

  char mm;

 sbit LED1=P3^0;

 sbit LED2=P3^1;

 sbit LED3=P3^2;

 sbit LED4=P3^3;

 sbit LED5=P3^4;

  sbit MAN_ATUO=P3^6;

 sbit open_shart=P3^5;

 sbit signal=P1^3; //信号端口定义

 0

 光线暗 1 光线强

 uint m;

  int

  MANATUO()

  //为0时 自动 为

 1 时手动

 {

  if(MAN_ATUO==0)

  {

 { a=!a; }

 while(!MAN_ATUO);

  }

  return a;

 }

 int openshart()

 //为 0时 关闭 为1时 打开

 {

  if(open_shart==0&&MANATUO()==1)

  {

  {

 n=!n; }

 while(!open_shart);

  }

  return n;

 }

  void LM297_Init() //LM297初始化 { CLK=1; CW=1; EN=0;

 } void m_Delay(long time) {

  while(time!=0)

  time--;

 } void CLK_Out()

  //脉冲产生 {

 CLK=0;

 m_Delay(200);

  CLK=1;

 m_Delay(200); }

 

推荐访问:单片机 控制系统 毕业论文

《基于单片机的自动窗帘控制系统毕业论文.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:

文档为doc格式

一键复制全文 下载 投诉