您好,欢迎来到爱够旅游网。
搜索
您的当前位置:首页基于单片机的智能型家居窗帘控制电路的设计

基于单片机的智能型家居窗帘控制电路的设计

来源:爱够旅游网
此毕业设计仅供参考,请勿偷懒直接使用

可实现功能:手动控制,定时控制,光控;

还有遥控控制没实现,希望对学弟学妹有用!

摘 要

本文首先介绍了智能家居的基本知识及其应用前景,接着着重介绍了开发单片机控制的红外线遥控窗帘系统所用到的集成芯片STCC52、L7805稳压芯片、LCD1602液晶显示屏、DS1302时钟芯片、AT24C02存储芯片、28BYJ_48步进电机、HS0038红外线接收电路等硬件的结构原理。本文采用分块的模式,对整个系统的硬件电路设计进行分析,分别给出了系统方案原理框图、电源电路、显示电路、时钟DS1302电路、外扩存储电路、电机控制电路、红外线接收电路,并对相应电路设计进行了相关的阐述。软件的编写思路也是采用分块的模式,分别写出了LCD1602液晶显示程序、DS1302时钟芯片控制程序、时间调整与定时程序、步进电机控制程序、HS0038红外线解码程序、AT24C02控制程序、光控程序的编写思路,每一模块都画出了其方框图,一目了然。

最后通过仿真调试,时钟,手动开关窗帘等控制方面的设计上基本达到了预期目的。当然,该系统在一些细节的设计上还需要不断的完善和改进。

关键词:STCC52RC单片机;DS1302时钟芯片;红外遥控;LCD1602;窗帘

Abstract

At first, this paper introduces the basic knowledge of the smart home and its application prospect, and then introduces the development of single-chip microcomputer control of infrared remote control curtain system used by the integrated chip STCC52, L7805 voltage chip, LCD1602 LCD display, DS1302 clock chip, 28 byj_48 stepper motor,AT24C02 storage chip, HS0038 infrared receiving circuit, etc. hardware structure principle,based on the block model, this paper give an analysis to the hardware circuit design of the whole system.It respectively presents the system principle block diagram, power supply circuit, display circuit, clock DS1302 circuit , outside enlarge storage circuit , motor control circuit, infrared receiving circuit and gives a corresponding explanation of the related circuit design. Writing ideas of software adopt the block pattern too . They write down the compile thoughts of the LCD1602 LCD display program, DS1302 clock chip control procedures, time adjustment and timing, stepper motor control procedures, HS0038 infrared decoding procedures, AT24C02 control procedures . Every module draws the very block diagram ,which is clear at a glance .

Finally,via simulation and debugging ,the design of the control aspects such as the clock , the manual switch curtain has basically reached the expected purpose . Of course , the system requires constant perfection and improvement on some detail designs .

Key words:stcc52rc singlechip;ds1302 clock chip;infrared remote

control;lcd1602;curtain

目录

摘 要I AbstractIII 1 绪言1

1.1 课题背景1

1.2 课题的研究方向1 2 系统总体方案设计2

2.1 系统方案确定2 2.2 模块器件选择2

2.2.1 STCC52RC单片机2 2.2.2 LCD1602液晶显示屏5 2.2.3 DS1302时钟芯片5

3 系统硬件电路设计5

3.1 单片机时钟电路5 3.2 单片机复位电路6 3.3 电源电路7 3.4 显示电路7

3.4.1 LCD1602管脚介绍8 3.4.2 LCD1602操作时序8 3.4.3 LCD1602指令集8 3.5 DS1302时钟电路9

3.5.1 DS1302简介9 3.5.2 DS1302芯片引脚9 3.5.3 DS1302内部寄存器10 3.5.4 DS1302数据传输方式10 3.6 AT24C02数据存储电路11

3.6.1 AT24C02简介11 3.6.2 AT24C02芯片引脚11 3.6.3 I2C总线介绍12 3.7 步进电机28BYJ-48电路13

3.7.1 28BYJ_48电路图13 3.7.2 28BYJ_48相关概念14 3.7.3 28BYJ_48驱动时序14 3.7.4 28BYJ_48特点14

3.7.5 28BYJ_48驱动芯片ULN200314 3.8 红外接收电路15

3.8.1 红外接收电路图15

3.8.2 红外接收探头HS003816 3.9 光控电路16

3.10 窗帘框架设计17 4 系统软件设计17

4.1 LCD1602显示程序18

4.1.1 LCD1602的初始化过程18 4.1.2 LCD1602的程序流程图18 4.2 DS1302时钟芯片控制程序18 4.3 时间调整和定时时间程序20 4.4 步进电机控制程序20

4.4.1 步进电机转动方式(一)20 4.4.2 步进电机转动方式(二)21 4.4.3 步进电机控制程序流程图4.421 4.5 HS0038红外解码程序22

4.5.1 红外编码波形说明22 4.5.2 红外解码说明23 4.5.3 红外解码流程图23 4.6 数据存储程序24 4.7 光控程序25 5 总结26 参考文献27

附录(一)原理图28 附录(二)源程序29

1 延时函数30

2 LCD1602有关子函数30 3 DS1302有关子函数31

4 读DS1302时间显示于LCD1602函数34 5 按键调整时间函数35 6 按键定时时间函数41 7 步进电机控制程序函数44 8 I2C模块函数47 9 定时扫描子函数49 10 光控子函数50 11 主函数51

12 红外中断函数51

致谢53

1 绪言

1.1 课题背景

随着时尚元素与家居生活的逐步融合,人们对于家居装饰也提出了更高的要求。谈到家居装饰,窗帘所发挥的作用绝对是功不可没。现如今,通透的玻璃窗正在变成现代建筑设计中的流行元素。大阳台、外飘窗、阳光住宅开始成为一种时尚和高品质生活的体现。而对家居装饰起到点睛之笔的窗帘,也尤如一股势不可挡的旋风,吹遍家居卖场,吹进了百姓的家。

现在市场上的智能窗帘有如下特点:

1.无线遥控。2.半自动手动控制。3.环境亮度控制。4.时间自动控制。5.电机工作鸣响提示和整点报时功能。

这种简约风格的新型窗饰不仅仅是我们看风景的眼睛,也成为家居中一道美丽风景。在秋冬季节里,透过智能窗饰传来的浓浓暖意,让你更接近自然,从舒适到陶醉,十分妥帖的个性化“定制”对阳光的需求——生活像是在旅行,惬意中带着情调。

虽然遥控自动窗帘系统在我国还刚刚兴起,但其发展前景广阔,推广和应用自动窗帘系统具有重要的现实意义。 1.2 课题的研究方向

自动窗帘机的控制方式大体上有三种:声控、光控、时控,声控和遥控属于半自动类;而光控虽属全自动式,但因光敏器件的灵敏度,冬夏等不同季节的光照度的不同,以及人们对起闭窗帘在时间上的要求不同,而难以实施和普及。因此,时控式的全自动窗帘机便成了专业以及业余电子设计人员的热门课题。

本电路设计利用价格相对便宜的单片机作为主要控制器件,通过步进电机的正反转模拟窗帘开启关闭,实现以下功能:

[1]无线遥控功能; [2]半手动控制功能;

[3]根据环境亮度自动控制功能;

[4]定时控制功能。考虑到单片机IO口有限,比市场上的少了正点报时功能。

2 系统总体方案设计

2.1 系统方案确定

根据任务书要求:

[1]能根据时间定时开关窗帘; [2]能根据光的亮度自动开关窗帘; [3]能用红外遥控器控制窗帘开启关闭;

为满足上述要求,确定的方案原理图图2.1如下:

电源模块 显示模块 按键模块 时钟模块 STCC52RC 单片机 步进电机 红外接收模块 光控模块

遥控器 图2.1 系统方案原理框图

按键模块除了定时外,还可在遥控器失灵后手动控制,防止意外情况。 2.2 模块器件选择

为使基于单片机控制的红外线遥控系统在实际使用过程中具有较高的性能/价格比,所以对该系统的原器件作了精心挑选。

按在实际工作中的作用,可分为以下几个部分:STCC52RC单片机是整个电路的核心,它控制其它模块来完成各种复杂的操作;红外线一体化接受HS0038负责接受命令;芯片DS1302负责时钟的运行及设置参数;AT24C02用来存储数据;LCD1602用来显示各种数据,包括实时时间、定时时间、电机运行状态等。

下面重点说明下STCC52RC单片机以及简单介绍下部分其他器件(其他器件会在相应电路中详细介绍)。 2.2.1 STCC52RC单片机

STCC52RC有很宽的工作电源电压,可为2.7~6V,当工作在3V时,电流相当于6V工作时的1/4。STCC52RC工作于12Hz时,动态电流为5.5mA,空闲态为

1mA,掉电状态仅为20nA。引脚图如图2.2:

图2.2 STCC52RC引脚图

STCC52RC的特点

·STCC52RC与MCS-51系列的单片机在指令系统和引脚上完全兼容; ·片内有4k字节在线可重复编程快擦写程序存储器; ·全静态工作,工作范围:0Hz~24MHz; ·三级程序存储器加密; ·128×8位内部RAM; ·32位双向输入输出线; ·两个十六位定时器/计数器 ·五个中断源,两级中断优先级; ·一个全双工的异步串行口; ·间歇和掉电两种工作方式

·超强抗干扰: 高抗静电(ESD保护) ,轻松过 2KV/4KV快速脉冲干扰;

·宽电压,不怕电源抖动 ;·宽温度范围,-40℃~85℃ ;·禁止ALE输出

·

:

[1]掉电模式:典型功耗<0.1 μ A ; [2]空闲模式:典型功耗2mA ; [3]正常工作模式:典型功耗4mA-7mA ; [4]掉电模式可由外部中断唤醒,适用于电池供电系统,如水表、气表、便携设备等. STCC52RC的引脚

[1]电源:①VCC - 芯片电源,接+5V; ②VSS - 接地端; [2]时钟:XTAL1、XTAL2 - 晶体振荡电路反相输入端和输出端。 [3]控制线:控制线共有4根:

ALE/PROG:地址锁存允许/片内EPROM编程脉冲 ① ALE功能:用来锁存P0口送出的低8位地址

② PROG功能:片内有EPROM的芯片,在EPROM编程期间,此引脚输入编程脉

冲。

PSEN:外ROM读选通信号。 RST/VPD:复位/备用电源。

① RST(Reset)功能:复位信号输入端。 ② VPD功能:在Vcc掉电情况下,接备用电源。 EA/Vpp:内外ROM选择/片内EPROM编程电源。 ① EA功能:内外ROM选择端。

② Vpp功能:片内有EPROM的芯片,在EPROM编程期间,施加编程电源Vpp。 [4]I/O口线:P0、P1、P2、P3共四个八位口。

 P0口是三态双向口,通称数据总线口,因为只有该口能直接用于对外部存储器的读/写操作。P0口也用以输出外部存储器的低8位地图1址。由于是分时输出,故应在外部加锁存器将此地址数据锁存,地址锁存,信号用ALE。

 P1口是专门供用户使用的I/O口,是准双向口。

 P2口是从系统扩展时作高8位地址线用。不扩展外部存储器时,P2口也可以作为用户I/O口线使用,P2口也是准双向口。

 P3口是双功能口,该口的每一位均可地定义为第一I/O功能或第二I/O功能。作为第一功能使用时操作同P1口。P3口的第二功能如表2.1所示。

表2.1 P3口第二功能

端口引脚 P3.0 RXD(串行口输入端) 各个功能 P3.1 P3.2 P3.3 P3.4 P3.5 P3.6 P3.7

TXD(串行口输出端) (外部中断0请求输入端,低电平有效) (外部中断1请求输入端,低电平有效) T0(定时器/计数器0计数脉冲输入端) T1(定时器/计数器1计数脉冲输入端) (外部数据存储器写选通信号输入端,低电平有效) (外部数据存储器读选通信号输入端,低电平有效) 2.2.2 LCD1602液晶显示屏

LCD1602液晶也叫1602字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵型液晶模块。它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此所以它不能很好地显示图形(用自定义CGRAM,显示效果也不好)。

1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。 2.2.3 DS1302时钟芯片

DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后备电源双电源引脚,同时提供了对后备电源进行涓细电流充电的能力。

3 系统硬件电路设计

3.1 单片机时钟电路

片内电路与片外器件就构成一个时钟产生电路,CPU的所有操作均在时钟脉冲

同步下进行。片内振荡器的振荡频率非常接近晶振频率,一般多在1.2MHz~24MHz之间选取。C2、C3是反馈电容,其值在20pF~100pF之间选取,典型值为30pF。本电路选用的电容为30pF,晶振频率为12MHz。

振荡周期=1/12 μS; 机器周期=1 μS; 指令周期=1~4 μS;

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

图3.1 单片机时钟电路

3.2 单片机复位电路

单片机在开机时都需要复位,以便处理CPU以及其他功能部件都处于一个

确定的初始状态,并从这个状态开始工作。单片机的复位后是靠外部电路实现的,在时钟电路工作后,只要在单片机的RST引脚上出现24个时钟振荡脉冲(2个机器周期)以上的高电平,单片机便可实现初始化状态复位,如图3.2所示。

图3.2 单片机复位电路

3.3 电源电路

通过220V转12V变压器输入,再经桥式整流电路后,输入直流12V电压。C1、C2是12伏的电源滤波电容,大电容C1旁边并联一个小电容的目的是降低高频内阻,因为大的电解电容一般采用卷绕工艺制造,所以等效电感较大,小电容可以提供一个小内阻的高频通道,降低电源全频带内阻。之后经过3端集成稳压芯片LM7805稳压后输出+5V电压VCC,为步进电机电路、红外接收电路、显示电路、时钟芯片提供电源,5V电源经过二极管D5、限流电阻R1=5K后,为DS1302提供VDD电压,BATTERY是直流供电电源,电压为3V左右,在本电路中为了节省成本,使用两节5号可充电电池。市电正常的情况下,VDD电源为DS1302供电的同时,也为电池充电,从而延长电池的使用寿命,当市电停电的时候,电池为DS1302供电,DS1302在掉电状态下维持时钟的正常,如图3.3所示。

图3.3 电源电路

3.4 显示电路

显示电路设计采用的是液晶LCD1602(仿真时用LM016L代替)来显示实时时间、步进电机运行状态等内容。由于P0口带负载能力差,故需接上拉电阻(这里用1K的排阻),P0口作为数据口连接LCD1602的7~14口,来传输数据及指令。P2.5接LCD1602的4脚RS(数据/命令选择端),P2.6接LCD1602的5脚R/W(读写选择端),P2.7接LCD1602的6脚E(使能信号)。电位器RV1用来调节LCD1602的亮

度,如图3.4所示。

图3.4 LCD1602显示电路

3.4.1 LCD1602管脚介绍

1602共16个管脚,但是编程用到的主要管脚不过三个,分别为:RS(数据命令选择端4脚),R/W(读写选择端5脚),E(使能信号6脚)。以后编程便主要围绕这三个管脚展开进行初始化,写命令,写数据。

以下具体阐述这三个管脚:RS为寄存器选择,高电平选择数据寄存器,低电平选择指令寄存器。R/W为读写选择,高电平进行读操作,低电平进行写操作。E端为使能端,后面和时序联系在一起。

除此外,D0~D7(7~14脚)分别为8位双向数据线,第1脚:VSS为地电源; 第2脚:VDD接5V正电源;第3脚:液晶显示偏压。 3.4.2 LCD1602操作时序

RS 0 0 1 1 表3.1 操作时序 R/W 操作说明 0 写入指令码到D0~D7 1 读从D0~D7输出的状态字 0 写数据到D0~D7 1 从D0~D7读数据 3.4.3 LCD1602指令集

0x38 设置16*2显示,5*7点阵,8位数据接口; 0x01 清屏;

0x0f 开显示,显示光标,光标闪烁; 0x08 只开显示;

0x0e 开显示,显示光标,光标不闪烁; 0x0c 开显示,不显示光标;

0x06 地址+1,当写入数据的时候光标右移;

0x02 地址计数器AC=0(此时地址为0x80),光标归原点,但是DDRAM中内容不变;

0x18 光标和显示一起向左移动; 3.5 DS1302时钟电路

本电路采用DS1302时钟芯片(DS1302主要特点是采用串行数据传输),采用32768Hz晶振,两个电源Vcc1及Vcc2接电源VDD,这样如果没有交流电的供电也可以由可充电电池供电,起了掉电保护,防止实时时间数据丢失。2脚X1(晶振引脚)及3脚X2(晶振引脚)接32786Hz的晶振,晶振旁接两个6pf的起振电容,5脚RST(复位引脚)与单片机的P1.7相连,6脚I/O(数据输入输出引脚)与单片机的P1.6相连,7脚CLK(串行时钟输入引脚)与单片机的P1.5相连,如图3.5所示。

图3.5 DS1302时钟电路

3.5.1 DS1302简介

DSl302是美国Dallas公司生产的一种串行实时时钟/日历芯片,以串行方式与单片机进行数据传送,它能够向单片机提供:秒、分、时、日、月、年、及星期等实时时间信息,并能够对闰年天数自动调整,日历有效至2100年。DSl302由双电源中较大者供电,使系统在没有主电源的情况下也能保持时钟的连续运行。片内具有31个字节静态RAM,可用来保存重要数据。DSl302具有引脚少、体积小、价格低等优点,得到了广泛应用。本文对其进行详细分析和阐述并在分析其时序的基础上给出了DSl302与单片机连接的接口电路和通讯子程序。 3.5.2 DS1302芯片引脚

DS1302的引脚功能描述如表3.2所示:

表3.2 DS1302引脚描述

引脚号 1 2 3 4 名称 Vcc2 X1 X2 GND 说明 备用电源引脚 晶振引脚 晶振引脚 电源地引脚 引脚号 5 6 7 8 名称 CE I/O SCLK Vcc1 说明 复位引脚 串行输入输出引脚 串行时钟输入引脚 主电源引脚 3.5.3 DS1302内部寄存器

DS1302串行实时时钟芯片主要由移位寄存器、控制逻辑、振荡器、实时时钟及31个字节RAM组成,其内部结构如表3.3所示。数据传送前,必须把置为高电平且把提供地址和命令信息的8位字节装入到移位寄存器。在进行单字节传送或多字节传送时,开始的8位命令字节用于指定40个字节(31个字节RAM和9个字节时钟寄存器)中哪个将被访问。

表3.3 DS1302内部寄存器 寄存器名 秒寄存器 分钟寄存器 小时寄存器 日期寄存器 月份寄存器 周日寄存器 年份寄存器 命令字 写 读 81H 83H 85H 87H H 8BH 8DH 取值范围 00--59 00--59 各位内容 7 CH 0 0 0 0 0 6 5 10SEC 10MIN A/M HR 4 3 2 1 0 80H 82H 84H 86H 88H 8AH 8CH SEC MIN HR DATE MONTH 0 DAY YEAR 01--12或00--23 12/24 01--28,29,30,31 01--12 01--12 00--99 0 0 0 10DATE 0 0 10M 0 10 YEAR 从上面可以看出,DS1302的寄存器存的是BCD码,用的时候要转换回十进制码。

3.5.4 DS1302数据传输方式

对DS1302 进行任何数据传送时, 第一个数据字节必须是命令字节, 格式如表3.4所示, 其最高有效位MSB (位7) 必须为逻辑1。如果它是零, 禁止写DS1302。位6为逻辑0 时指定传送时钟/日历数据。 逻辑1指定传送RAM数据。位1至5 指定进行输入或输出的特定寄存器的地址。最低有效位LSB (位0)为逻辑0 时指定时进行写操作(输入) 。 逻辑1指定进行读操作(输出)。命令字节总是从最低有效LSB (位0) 开始输入[07]。

表3.4 命令字

1 RAM __ CK A4 A3 A2 A1 A0 RD __ WR 3.6 AT24C02数据存储电路

本电路采用AT24C02芯片,AT24C02支持I2C协议(一种总线数据传送协议),总线协议规定任何将数据传送到总线的器件作为发送器。任何从总线接收数据的器件为接收器。数据传送是由产生串行时钟和所有起始停止信号的主器件控制的。A0、A1、A2接地表示该器件的地址为00H,SCK接单片机的P1.0脚,SDA接单片机的P1.1脚,如图3.6所示。

图3.6 AT24C02数据存储电路

3.6.1 AT24C02简介

CAT24WC02是一个2K位串行CMOS E2PROM,内部含有256个8位字节,CATALYST 公司的先进 CMOS 技术实质上减少了器件的功耗。CAT24WC01有一个8 字节页写缓冲器,CAT24WC02/04/08/16有一个16字节页写缓冲器,该器件通过I2C总线接口进行操作有一个专门的写保护功能。 3.6.2 AT24C02芯片引脚 AT24C02引脚描述如表3.5所示:

表3.5 AT24C02引脚描述 引脚名称 功能描述 A0,A1,A2 器件地址选择 SDA 串行数据/地址 SCL 串行时钟 WP 写保护 Vcc +1.8V~6.0V工作电压 Vss 电源地

SCL 串行时钟:

AT24C02串行时钟输入管脚用于产生器件所有数据发送或接收的时钟,这是一个输入管脚。

SDA 串行数据/地址:

AT24C02 双向串行数据/地址管脚用于器件所有数据的发送或接收,SDA 是一个开漏输出管脚,可与其它开漏输出或集电极开路输出进行线或(wire-OR)。 A0、A1、A2 器件地址输入端:

这些输入脚用于多个器件级联时设置器件地址,当这些脚悬空时默认值为0。当使用AT24C02 时最大可级联8个器件。如果只有一个AT24C02被总线寻址,这三个地址输入脚(A0、A1、A2 )可悬空或连接到Vss,如果只有一个AT24C02被总线寻址这三个地址输入脚(A0、A1、A2 )必须连接到Vss。 WP 写保护:

如果WP管脚连接到Vcc,所有的内容都被写保护只能读。当WP管脚连接到Vss 或悬空允许器件进行正常的读/写操作。 3.6.3 I2C总线介绍

I2C(Inter-Integrated Circuit)总线是由PHILIPS公司推出的一种串行总线,是具备多主机系统所需的包括总线裁决和高低速器件同步功能的高性能串行总线。

I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。

SDA SCL SCL SDA SCL SDA SCL SDA SCL SDA 单片机 单片 SCL SDA SCL SDA B 机A SRAM或A/D或日历时钟 E2PROM D/A 图3.7 I2C总线图

其他I2C外围设备 每个接到I2C总线上的器件都有唯一的地址。主机与其它器件间的数据传送可以是由主机发送数据到其它器件,这时主机即为发送器。由总线上接收数据的器件则为接收器。

在多主机系统中,可能同时有几个主机企图启动总线传送数据。为了避免混乱, I2C总线要通过总线仲裁,以决定由哪一台主机控制总线。

I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。

SCL

SDA 要求数 允许数据 要求数

据稳定 变化 据稳定

图3.8 I2C数据传送时序图

SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号

SCL SDA 起始信号 S 终止信号 P

图3.9 I2C总线起始停止时序图

起始和终止信号都是由主机发出的,在起始信号产生后,总线就处于被占用的状态;在终止信号产生后,总线就处于空闲状态。

连接到I2C总线上的器件,若具有I2C总线的硬件接口,则很容易检测到起始和终止信号。

3.7 步进电机28BYJ-48电路 3.7.1 28BYJ_48电路图

由于步进电机的驱动电流较大,单片机不能直接驱动,一般都是使ULN2003达林顿阵列驱动,当然,使用下拉电阻或三极管也是可以驱动的,只不过效果不是那么好,产生的扭力比较小,故本系统用了ULN2003驱动,如图3.10所示。

图3.10 28BYJ-48步进电机电路

3.7.2 28BYJ_48相关概念

相数:产生不同对极N、S磁场的激磁线圈对数。常用m表示。

拍数:完成一个磁场周期性变化所需脉冲数或导电状态用n表示,或指电机转过一个齿距角所需脉冲数,以四相电机为例,有四相四拍运行方式即AB-BC-CD-DA-AB,四相八拍运行方式即 A-AB-B-BC-C-CD-D-DA-A.

步距角:对应一个脉冲信号,电机转子转过的角位移用θ表示。θ=360度(转子齿数J*运行拍数)。四拍运行时步距角为θ=360度/(50*4)=1.8度(俗称整步),八拍运行时步距角为θ=360度/(50*8)=0.9度(俗称半步)。 3.7.3 28BYJ_48驱动时序

对应一个脉冲信号,步进电机28BYJ_48是四相五线制的,用四相四拍驱动,其驱动时序如表3.6所示:

表3.6 步进电机驱动时序表 控制位 D 0 0 0 1 1 1 0 C 0 0 1 1 1 0 0 0 B 1 1 1 0 0 0 0 0 A 1 0 0 0 0 0 1 1 步序 1 2 3 4 5 6 7 8 工作状态 AB B BC C CD D DA A 3.7.4 28BYJ_48特点

[1]给步进脉冲就转,不给步进脉冲电机就不转;

[2]步进脉冲频率高,步进电机转得快;步进脉冲频率低,步进电机转得慢; [3]改变各相的通电方式(叫脉冲分配)可以改变步进电机的运行方式; [4]改变通电顺序,可以控制步进电机的正、反转。 3.7.5 28BYJ_48驱动芯片ULN2003

ULN2003是一个单片高电压、高电流的达林顿晶体管阵列集成电路。它是由7 对NPN达林顿管组成的,它的高电压输出特性和阴极箝位二极管可以转换感应负

载。ULN2003是一个7路反向器电路,即当输入端为高电平时ULN2003输出端为低电平,当输入端为低电平时ULN2003输出端为高电平,继电器得电吸合。单个达林顿对的集电极电流是500mA。达林顿管并联可以承受更大的电流。此电路主要应用于继电器驱动器,字锤驱动器,灯驱动器,显示驱动器(LED气体放电),线路驱动器和逻辑缓冲器。ULN2003的每对达林管都有一个2.7k欧姆的串联电阻,可以直接和TTL或5V CMOS装置。

功能特点:高电压输出50V 输出钳位二极管 ,输入兼容各种类型的逻辑电路 ,应用继电器驱动器,500mA 额定集电极电流(单个输出)。 引脚说明:

[1]IN1~IN7 (引脚1~7):脉冲输入端;

[2]OUT1~OUT7(引脚10~16):脉冲输出端; [3]GND(引脚8):电源地; [4]COM(引脚9):电源正极。

图3.11 ULN2003引脚图

本系统中,P1.0接IN1,P1.1接IN2,P1.3接IN3,P1.4接IN4。OUT1接步进电机28BYJ_48A(蓝色的线),OUT2接接步进电机28BYJ_48B(粉色的线),OUT3接接步进电机28BYJ_48C(黄色的线),OUT1接接步进电机28BYJ_48D(橙色的线)。

3.8 红外接收电路 3.8.1 红外接收电路图

红外线接收电路使用一个集成红外接收器,型号是HS0038,静态时输出端输出高电平,当接收到红外信号后,按红外信号的数据波形输出负脉冲数据信号。红外信号输出到单片机的P3.3 ,该口对应的第二功能是外部中断1(INT1),利用该口的第二功

能,一旦红外线信号到来,P3.3被拉低,单片机中止当前的工作转移到接收、处理红外信号,如图3.12所示。

图3.12 红外接收电路

3.8.2 红外接收探头HS0038

红外接收探头,接收红外信号频率为38kHz,周期约26μs。

红外接收头电路一体化的红外接收装置将遥控信号的接受、放大、检波、整形集一体,并且输出可以让单片机识别的TTL信号,这样大大简化了接收电路的复杂程度和电路的设计工作,方便使用。在本系统中我们采用红外一体化接收头HS0038,示意图如图3.13所示。HS0038 黑色环氧树脂封装,不受日光、荧光灯等光源干扰,内附磁屏蔽,功耗低,灵敏度高。在用小功率发射管发射信号情况下,其接收距离可达35m。它能与TTL、COMS 电路兼容。HS0038 为直立侧面收光型。它接收红外信号频率为38 kHz,周期约26 μs,同时能对信号进行放大、检波、整形,得到TTL 电平的编码信号。三个管脚分别是地、+5 V 电源、解调信号输出端。

HS0038

1 GND 2VCC 3脉冲输出端

图3.13 HS0038引脚示意图

3.9 光控电路

光控电路由光敏电阻LDR、滑动变阻器VR组成,利用单片机的P2.4完成对环境亮度的测试工作。

VR Vcc

P2.4

LDR光敏电阻

图3.14 光控电路图

3.10 窗帘框架设计

窗帘框架构造设计包括窗帘微动开关连接电路设计和窗帘架的制作与设计。本设计中的微动开关通过电容、电阻组成的复位电路与单片机的复位引脚相连,微动开关安装在窗帘滑杆上,当窗帘移动到预定位置时,触动微动开关,使单片机复位,此时电机停转,窗帘停到指定位置,如图3.15所示。

步进

电机

微动开关 主动

左半窗帘

图3.15 窗帘框架图

右半窗帘 从 动 轮

4 系统软件设计

单片机电路只有软件和硬件都正确才能使电路达到预计的目标,因此,软件的编写也是相当重要的。本系统的软件编程部分的编写主要分为LCD1602显示程序、时钟芯片DS1302控制程序、时间调整和定时时间程序、步进电机控制程序、红外解码程序、数据存储程序、光控程序这七大类。

4.1 LCD1602显示程序 4.1.1 LCD1602的初始化过程 LCD1602的初始化(复位)过程

[1]延时15mS,写指令38H(不检测忙信号);[2]延时5mS,写指令38H(不检测忙信号);[3]延时5mS,写指令38H(不检测忙信号,以后每次写指令、读/写数据操作均需要检[4]测忙信号);[5]写指令38H:显示模式设置(即16*2行显示,5*7点阵,8位数据);[6]写指令08H:显示关闭;[7]写指令01H:显示清屏;[8]写指令06H:整屏不移动,光标自动右移;[9]写指令0CH:开显示不显示光标; 4.1.2 LCD1602的程序流程图

开始 初始化 清屏并光标复位 单片机发写命令 否 液晶是否应答 是 准备写入数据 执行显示命令 图4.1 LCD1602显示程序流程图

4.2 DS1302时钟芯片控制程序

DS1302 与微处理器进行数据交换时,首先由微处理器向电路发送命令字节,命令字节最高位MSB(D7)必须为逻辑0,如果D7=1,则禁止写DS1302,即写保护(0X00禁止写保护、0X80打开写保护);

数据输入时,时钟的上升沿数据必须有效,数据的输出在时钟的下降沿。如果为低电平,那么所有的数据传送将被中止且I/0引脚变为高阻状态。上电时,在Vcc>2.5伏之前,必须为逻辑0。当把驱动至逻辑1状态时,SCLK必须为逻辑0。

单字节数据输入跟随在写命令字节的8个SCLK周期之后,在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。

开始 变量初始化 使DS1302不具备写保复位后产生一个高电平 写DS1302地址 向该地址写数据 地址增加 N 数据是否写完 Y 复位后产生一个高电平 写DS1302地址 将该地址数据读出 地址增加 N 数据是否读完 Y 显示数据 图4.2 DS1302读写流程图

4.3 时间调整和定时时间程序

这里采用的是按键中断实现的,因为在编写程序时发现实时刷新时间函数和按键调整时间和定时有冲突。

首先,按中断键key4,调中断(置标志位flag=1),返回主函数后将执行时间定时和时间调整扫面程序。如果按key5键,则进入定时开关窗帘程序;如果按key6,则进入调整时间函数。 程序流程图如图4.3所示:

key4按下否 调整时间函数执行完否

是 key6按下否 是

否 否 Key5按下否

是 执行定时时间函数

是 定时时间函数执行完否

是 清标志位,返回主函数 是 4.4 步进电机控制程序 4.4.1 步进电机转动方式(一)

要实现步进电机的转动,可以用以下两种方式: (1)8拍的方式八个状态:

[1]在A与A-正电压,B与B-不给电悬空;

执行调整时间函数图4.3 时间调整和定时时间程序

[2]在A与A-正电压,B与B-也给正电压; [3]A与A-不给电压悬空,B与B-正电压; [4]A与A-给负电压,B与B-给正电压; [5]A与A-给负电压,B与B-不给悬空; [6]A与A-给负电压,B与B-给负电压; [7]A与A-不给电悬空,B与B-给负电压; [8]A与给正电压,B与B-给负电压;

按以上八个状态轮流供电,控制一下脉宽应该就可以了。 四个引脚各一根控制线:A~H表示各线时序 A B C D E F G H A 1 1 0 0 0 0 0 1 A- 0 0 0 1 1 1 0 0 B 0 1 1 1 0 0 0 0 B- 0 0 0 0 0 1 1 1 4.4.2 步进电机转动方式(二)

4拍的方式: 电流驱动。

下面的a~ 和b~ 表示反向电流。两相双二拍:ab - a~b - a~b~ - ab~ 为一个转向。ab - ab~ - a~b~ - a~b 为反向。

A B C D A 1 0 0 1 A- 0 1 1 0 B 1 1 0 0 B- 0 0 1 1

4.4.3 步进电机控制程序流程图4.4

主函数

否 步进电机按键扫描函数

反转键按 是 key5下否

是 否

是 正转键按 key6下否

否 否

电机反转函数停止键按下否 电机正转函数电机停止函数图4.4 步进电机程序流程图

4.5 HS0038红外解码程序 4.5.1 红外编码波形说明

这里采用的是6122型遥控器,载波波形使用455KHz晶体,经内部分频电路,信号被调制在37.91KHz,占空比为三分之一。数据格式包括了引导码、用户码、数据码、数据反码,编码总共占32位。数据反码是数据码相反的编码,编码时可用对于数据的纠错,其红外波形图如图4.5所示。

图4.5 红外波形图

引导码由一个9ms的载波波形和4.5ms的关断时间构成,它作为随后发射的码的引导,这样当接收系统是由微处理器构成的时候,能更有效地处理码的接收与检测及其它各项控制之间的时序关系。编码采用脉冲位置调制方式(PPM)。每次8位的码被传送之后,它们的反码也被传送,减少了系统的误码率。

用户码或者数据码中的每一位可以是“1”,也可以是“0”。区分“0”和“1”是利用脉冲的时间间隔来区分,这种编码方式称为脉冲位置调制方式,简称PPM。 4.5.2 红外解码说明

图4.6 0、1波形图

解码的关键是如何识别“0”和“1”, 代码格式(以接收代码为准,接收代码与发射代码反向)。从位的定义我们可以发现“0”、“1”均以0.56ms的低电平开始,不同的是高电平的宽度不同,“0”为0.56ms,“1”为1.68ms,所以必须根据高电平的宽度区别“0”和“1”。如果从0.56ms低电平过后,开始延时,0.56ms以后,若读到的电平为低,说明该位为“0”,反之则为“1”,为了可靠起见,延时必须比0.56ms长些,但又不能超过1.12ms,否则如果该位为“0”,读到的已是下一位的高电平,因此取(1.12ms+0.56ms)/2=0.84ms最为可靠,一般取0.84ms左右均可;根据码的格式,应该等待9ms的起始码和4.5ms的结果码完成后才能读码。 4.5.3 红外解码流程图

红外解码流程图4.7如下:

有红外信号,产生中断 接收并解码 判断数据格式是否正确 否 跳出中断 是 比较,转出执行相应动作 中断返回 图4.7 红外解码流程图

4.6 数据存储程序

AT24C02的1、2、3脚是三条地址线,用于确定芯片的硬件地址(实验板中直接接地只有一块器件);第8脚和第4脚分别为正、负电源。第5脚SDA为串行数据输入/输出,数据通过这条双向I2C总线串行传送,SDA和SCL都需要和正电源间各接一个5.1K的电阻上拉。第7脚为WP写保护端,接地时允许芯片执行一般的读写操作。接电源端时不允许对器件写。 24C02中带有片内地址寄存器。每写入或读出一个数据字节后,该地址寄存器自动加1,以实现对下一个存储单元的读写。所有字节均以单一操作方式读取。为降低总的写入时间,一次操作可写入多达8个字节的数据。

AT24C02读写操作流程图4.8 如下:

产生启动条件 产生启动条件 给出从地址 给出从地址 等待接收确认 等待接收确认 给出数据地址 接收1字节数N 等待接收确认 是否最后字节 Y 写入接收数据 不做应答 等待接收确认 产生应答 产生停止条件 产生停止条件 写操作流程 读操作流程

图4.8 AT24C02读写操作流程图

4.7 光控程序

该子程序中,当有光照时,光敏电阻阻值小,单片机P2.4低电平;天黑后,光照太弱,光敏电阻增大至几十K欧姆,单片机P2.4端口高电平,通过判断P2.4口高低电平来实现自动控制。当由天黑变天亮时,执行开窗帘函数(即电机正转);当由白天进入夜晚时,执行关窗帘(即电机反转)函数。

5 总结

这次毕业设计让我更加熟悉了从理论到实践的跨越,从当初的查阅图书,到现在的实物的成功实现,这中间有很多值得回味的地方。这次的设计,我用到的软件主要有word、proteus,keil,protel99se。

虽然在系统开发过程中,好多知识都是随学随用,增加了很多不必要的麻烦,但是在不断的努力以及同学的帮助下,解决了大部分问题。

下面就把程序调时时出现的问题简述下:

[1]刚开始时按键设置时间函数与实时刷新时间函数有点冲突,按键按下后,时间刷新程序仍在运行,导致设置不了时间,后来通过中断置调时按键标志位为1进入调整时间函数死循环置退出;

[2]后面又发现定时程序与调时程序有冲突(调时程序会写DS1302,而定时不需要写),于是又加了个按键,结果发现进入中断后扫描程序太长,按键不太灵敏,而且两个键有影响,于是又把中断去掉,在主程序扫描置标志位,发现按键太灵敏,就加了点延时;

[3]实物上电后,液晶老是闪烁,而且85和正确的时间数据交替显示,因在仿真时把SCLK和I/O接反出现85。于是检查接线,发现无误,又检查BCD码转十进制数子函数,也没问题,最后发现在读DS1302一个字节时最后没有置IO=0,加上后显示正常;

虽然很多错误被克服了,但是系统中难免还有很多不足之处,希望各位评委老师和同学给予指正与建议。

我相信,只要肯钻研,只要挤时间,一切自己想要的知识都可以掌握。

参考文献

[01]华成英,童诗白.模拟电子技术基础[M].(第四版).北京:高等教育出版社,2006. [02]张毅刚,彭喜元,彭宇.单片机原理及应用[M].(第二版).北京:高等教育出版社,2010. [03]张家生.电机原理与拖动基础[M]. 北京:北京邮电大学出版社,2006.

[04]张靖武,周灵彬. 单片机系统的PROTEUS设计与仿真[M]. 北京:电子工业出版社,2007. [05]STCC52RC单片机中文资料. [06]ULN2003中文资料.

[07]徐发荣.DS1302、HT1380时钟芯片与8031单片机的接口技术.国外电子原器件,1999. [08]王明顺,吴省.可涓流充电的串行实时时钟芯片DS1302及其应用.电子技术应用,1996. [09]STCC51RC/RD+系列单片机器件手册.

[10]彭伟 单片机C语言程序设计实训100例[M],北京:电子工业出版社,2009. [11]覃韦玲. 利用单片机进行红外线编、解码遥控[J/OL]. 电子世界,2002.

[12]侯勇,王泊林,顾燕.一体化红外线接收模块及其在红外秒表通讯中的应用.仪器仪表与装置,2001.5

[13]阎石.数字电子技术[M].(第五版)北京:高等教育出版社,2005.

[14]姚福安.电子电路设计与实践[M].济南:山东科学技术出版社,2001.

[15]沙占友,王彦碰,孟志永等.单片机外围电路设计.北京:电子工业出版社,2003. [16]腾飞.智能家居就在眼前[J/OL].中国计算机用户,2001. [17]稳压芯片7805中文资料.

[18]集成红外接收器HS0038中文资料.

[19]邓奕,马双宝,谢龙汉.Protel 99 SE 原理图与PCB设计[M],北京:人民邮电出本社,2011. [20]张敏敏,陈亮亮. 实用智能家居窗帘的设计[J/OL].科技视界,2012.

附录(一)原理图

附录(二)源程序

#include

#define uint unsigned int #define uchar unsigned char

uchar a,miao,shi,fen,ri,yue,nian,week=1,key1n,temp,runstate=0,flag,flag1,motorflag。s[4]。 uchar dingmiao,dingshi,dingfen,dingri,dingyue,dingnian,dingweek,key2n,dingrunstate=0。 uchar code tabD[8]={1,1,0,0,0,0,0,1}。 uchar code tabC[8]={0,1,1,1,0,0,0,0}。 uchar code tabB[8]={0,0,0,1,1,1,0,0}。 uchar code tabA[8]={0,0,0,0,0,1,1,1}。 uchar code tabDB[8]={1,0,0,0,0,0,1,1}。 uchar code tabCB[8]={0,0,0,0,1,1,1,0}。 uchar code tabBB[8]={0,0,1,1,1,0,0,0}。 uchar code tabAB[8]={1,1,1,0,0,0,0,0}。 bit lighttemp。 sbit MA=P2^0。 sbit MB=P2^1。 sbit MC=P2^2。 sbit MD=P2^3。

sbit light=P2^4。//光控电路接口

#define yh 0x80 //LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1(100000000=80)

#define er 0x80+0x40 //LCD第二行初始位置(因为第二行第一个字符位置地址是0x40) //液晶屏的与C51之间的引脚连接定义(显示数据线接C51的P0口) sbit rs=P2^5。 sbit en=P2^7。

sbit rw=P2^6。 //如果硬件上rw接地,就不用写这句和后面的rw=0了 //DS1302时钟芯片与C51之间的引脚连接定义 sbit IO=P1^6。 sbit SCLK=P1^5。 sbit RST=P1^7。 sbit ACC0=ACC^0。 sbit ACC7=ACC^7。

//定义AT24C02引脚连接定义 sbit scl=P1^0。 //AT24C02SCL sbit sda=P1^1。 //AT24C02SDA

sbit red=P3^3。 //HS0038 负脉冲接口 sbit key6=P3^6。 //正转按键 sbit key7=P3^7。 //停止按键

//校时按键与C51的引脚连接定义 sbit key1=P1^2。 // 调整时间设置键 sbit key2=P3^0。 //加键

sbit key3=P3^1。 //减键 sbit key4=P1^3。 //按键中断 sbit key5=P3^5。 // 时间定时键 、步进电机反转按键

/**************************************************************/ uchar code tab1[]={\"20 - - \。 //年显示的固定字符 uchar code tab2[]={\" : : \。//时间显示的固定字符 uchar code tabrun[]={\"SRB\。 //运行状态显示

/******************************************************

1 延时函数

*****************************************************/

void delay(uint xms)//延时函数,ms级 { uint x,y。 for(x=xms。x>0。x--) for(y=110。y>0。y--)。 }

void delay0(uchar x) //x*0.14MS 延时函数0.14ms { uchar i。 while(x--) { for (i = 0。 i<13。 i++)。 } }

void delay1() //功能:延时函数1,us级 { 。 。 }

/******************************************************

2 LCD1602有关子函数

*****************************************************/

/*在这个程序中,液晶写入有关函数会在DS1302的函数中调用,所以液晶程序要放在前面*/ void write_1602com(uchar com)//****液晶写入指令函数**** { rs=0。//数据/指令选择置为指令 rw=0。 //读写选择置为写 P0=com。//送入数据 delay(1)。

en=1。//拉高使能端,为制造有效的下降沿做准备 delay(1)。 en=0。//en由高变低,产生下降沿,液晶执行命令 }

void write_1602dat(uchar dat)//***液晶写入数据函数**** { rs=1。//数据/指令选择置为数据 rw=0。 //读写选择置为写 P0=dat。//送入数据 delay(1)。 en=1。 //en置高电平,为制造下降沿做准备 delay(1)。 en=0。 //en由高变低,产生下降沿,液晶执行命令 }

void lcd_init()//***液晶初始化函数**** { write_1602com(0x38)。//设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据 write_1602com(0x0c)。//开显示不显示光标 write_1602com(0x06)。//整屏不移动,光标自动右移 write_1602com(0x01)。//清显示 write_1602com(yh+1)。//日历显示固定符号从第一行第1个位置之后开始显示 for(a=0。a<14。a++) { write_1602dat(tab1[a])。//向液晶屏写日历显示的固定符号部分 //delay(3)。 } write_1602com(er+2)。//时间显示固定符号写入位置,从第2个位置后开始显示 for(a=0。a<8。a++) { write_1602dat(tab2[a])。//写显示时间固定符号,两个冒号 //delay(3)。 } }

/******************************************************

3 DS1302有关子函数

*****************************************************/ void write_byte(uchar dat)//写一个字节 { ACC=dat。 RST=1。 for(a=8。a>0。a--) {

IO=ACC0。 SCLK=0。 SCLK=1。 ACC=ACC>>1。 } }

uchar read_byte()//读一个字节 { RST=1。 for(a=8。a>0。a--) { ACC7=IO。 SCLK=1。 SCLK=0。 ACC=ACC>>1。 } IO=0。 return (ACC)。 }

void write_1302(uchar add,uchar dat)//向1302芯片写函数(指定写入地址,数据) { RST=0。 SCLK=0。 RST=1。 write_byte(add)。 write_byte(dat)。 SCLK=1。 RST=0。 }

uchar read_1302(uchar add)//从1302读数据函数,指定读取数据来源地址 { uchar temp。 RST=0。 SCLK=0。 RST=1。 write_byte(add)。 temp=read_byte()。 SCLK=1。 RST=0。 return(temp)。 }

uchar BCD_Decimal(uchar bcd)//BCD码转十进制函数,输入BCD,返回十进制 {

uchar Decimal。

Decimal=bcd>>4。

return(Decimal=Decimal*10+(bcd&=0x0F))。 }

void ds1302_init() //1302芯片初始化子函数(2013-05-18,12:00:00,week4) {

RST=0。 SCLK=0。

write_1302(0x8e,0x00)。 //允许写,禁止写保护

write_1302(0x80,0x00)。 //向DS1302内写秒寄存器80H写入初始秒数据00 //write_1302(0x82,0x00)。//向DS1302内写分寄存器82H写入初始分数据00

//write_1302(0x84,0x12)。//向DS1302内写小时寄存器84H写入初始小时数据12 //write_1302(0x8a,0x06)。//向DS1302内写周寄存器8aH写入初始周数据6

//write_1302(0x86,0x18)。//向DS1302内写日期寄存器86H写入初始日期数据07 //write_1302(0x88,0x05)。//向DS1302内写月份寄存器88H写入初始月份数据01 //write_1302(0x8c,0x13)。//向DS1302内写年份寄存器8cH写入初始年份数据10 write_1302(0x8e,0x80)。 //打开写保护 }

//时分秒显示子函数

void write_sfm(uchar add,uchar dat)//向LCD写时分秒,有显示位置加、现示数据,两个参数 { uchar gw,sw。 gw=dat%10。//取得个位数字 sw=dat/10。//取得十位数字 write_1602com(er+add)。//er是头文件规定的值0x80+0x40 write_1602dat(0x30+sw)。//数字+30得到该数字的LCD1602显示码 write_1602dat(0x30+gw)。//数字+30得到该数字的LCD1602显示码 delay(20)。 }

//年月日显示子函数

void write_nyr(uchar add,uchar dat)//向LCD写年月日,有显示位置加数、显示数据,两个参数 { uchar gw,sw。 gw=dat%10。//取得个位数字 sw=dat/10。//取得十位数字 write_1602com(yh+add)。//设定显示位置为第一个位置+add write_1602dat(0x30+sw)。//数字+30得到该数字的LCD1602显示码 write_1602dat(0x30+gw)。//数字+30得到该数字的LCD1602显示码 delay(50)。 }

//写星期子函数

void write_week(uchar week) { write_1602com(yh+0x0c)。//星期字符的显示位置 switch(week)

{ case 1:write_1602dat('M')。//星期数为1时,显示 write_1602dat('O')。 write_1602dat('N')。 break。 case 2:write_1602dat('T')。//星期数据为2时显示 write_1602dat('U')。 write_1602dat('E')。 break。 case 3:write_1602dat('W')。//星期数据为3时显示 write_1602dat('E')。 write_1602dat('D')。 break。 case 4:write_1602dat('T')。//星期数据为4是显示 write_1602dat('H')。 write_1602dat('U')。 break。 case 5:write_1602dat('F')。//星期数据为5时显示 write_1602dat('R')。 write_1602dat('I')。 break。 case 6:write_1602dat('S')。//星期数据为6时显示 write_1602dat('T')。 write_1602dat('A')。 break。 case 7:write_1602dat('S')。//星期数据为7时显示 write_1602dat('U')。 write_1602dat('N')。 break。 } }

/******************************************************

4 读DS1302时间显示于LCD1602函数

*****************************************************/

void timegetdisp() //取得并显示日历和时间 {

//读取秒时分周日月年七个数据(DS1302的读寄存器与写寄存器不一样): miao = BCD_Decimal(read_1302(0x81))。

write_sfm(0x08,miao)。//秒,从第二行第8个字后开始显示(调用时分秒显示子函数) fen = BCD_Decimal(read_1302(0x83))。 write_sfm(0x05,fen)。//分,从第二行第5个字符后开始显示

shi = BCD_Decimal(read_1302(0x85))。 write_sfm(0x02,shi)。//小时,从第二行第2个字符后开始显示 ri = BCD_Decimal(read_1302(0x87))。

write_nyr(0x09,ri)。//日期,从第一行第9个字符后开始显示 yue = BCD_Decimal(read_1302(0x))。 write_nyr(0x06,yue)。//月份,从第一行第6个字符后开始显示 nian=BCD_Decimal(read_1302(0x8d))。 write_nyr(0x03,nian)。//年,从第一行第3个字符后开始显示 week=BCD_Decimal(read_1302(0x8b))。 write_week(week)。 }

/******************************************************

5 按键调整时间函数

*****************************************************/

void keyscan() //按键调整时间函数 { if(key1==0)//---------------key1为功能键(设置键)-------------------- { delay(9)。//延时,用于消抖动 if(key1==0)//延时后再次确认按键按下 { while(!key1)。 key1n++。 if(key1n==9) key1n=1。//设置按键共有秒、分、时、星期、日、月、年、 返回,8个功能循环 switch(key1n) { case 1: write_1602com(er+0x09)。//设置按键按动一次,秒位置显示光标 write_1602com(0x0f)。//设置光标为闪烁 temp=(miao)/10*16+(miao)%10。//秒数据写入DS1302 write_1302(0x8e,0x00)。 write_1302(0x80,0x80|temp)。//miao write_1302(0x8e,0x80)。 break。 case 2: write_1602com(er+6)。//按2次fen位置显示光标 //write_1602com(0x0f)。 break。 case 3: write_1602com(er+3)。//按动3次,shi //write_1602com(0x0f)。 break。 case 4: write_1602com(yh+0x0e)。//按动4次,week

//write_1602com(0x0f)。 break。 case 5: write_1602com(yh+0x0a)。//按动5次,ri //write_1602com(0x0f)。 break。 case 6: write_1602com(yh+0x07)。//按动6次,yue //write_1602com(0x0f)。 break。 case 7: write_1602com(yh+0x04)。//按动7次,nian //write_1602com(0x0f)。 break。 case 8: write_1602com(0x0c)。//按动到第9次,设置光标不闪烁 TR0=1。//打开定时器 temp=(miao)/10*16+(miao)%10。 write_1302(0x8e,0x00)。 write_1302(0x80,0x00|temp)。//miao数据写入DS1302 write_1302(0x8e,0x80)。 flag=0。 break。 } } }

//------------------------------加键key2---------------------------- if(key1n!=0)//当key1按下以后,再按以下键才有效(按键次数不等于零) { if(key2==0) //上调键 { delay(10)。 if(key2==0) { while(!key2)。 switch(key1n) { case 1:miao++。//设置键按动1次,调秒 if(miao>59) miao=0。//秒超过59,再加1,就归零 write_sfm(0x08,miao)。//令LCD在正确位置显示\"加\"设定好的秒数 temp=(miao)/10*16+(miao)%10。//十进制转换成DS1302要求的BCD码 write_1302(0x8e,0x00)。 //允许写,禁止写保护 write_1302(0x80,temp)。 //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码 write_1302(0x8e,0x80)。 //打开写保护 write_1602com(er+0x09)。//因为设置液晶的模式是写入数据后,光标自动

右移,所以要指定返回 //write_1602com(0x0b)。 break。 case 2:fen++。 if(fen>59) fen=0。 write_sfm(0x05,fen)。//令LCD在正确位置显示\"加\"设定好的分数据 temp=(fen)/10*16+(fen)%10。//十进制转换成DS1302要求的BCD码 write_1302(0x8e,0x00)。//允许写,禁止写保护 write_1302(0x82,temp)。//向DS1302内写分寄存器82H写入调整后的分数据BCD码 write_1302(0x8e,0x80)。//打开写保护 write_1602com(er+6)。//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置 break。 case 3:shi++。 if(shi>23) shi=0。 write_sfm(2,shi)。//令LCD在正确的位置显示\"加\"设定好的小时数据 temp=(shi)/10*16+(shi)%10。//十进制转换成DS1302要求的BCD码 write_1302(0x8e,0x00)。//允许写,禁止写保护 write_1302(0x84,temp)。//向DS1302内写小时寄存器84H写入调整后的小时数据BCD码 write_1302(0x8e,0x80)。//打开写保护 write_1602com(er+3)。//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break。 case 4:week++。 if(week>7) week=1。

write_1602com(yh+0x0C)。//指定'加'后的周数据显示位置 write_week(week)。//指定周数据显示内容

temp=(week)/10*16+(week)%10。//十进制转换成DS1302要求的BCD码 write_1302(0x8e,0x00)。//允许写,禁止写保护 write_1302(0x8a,temp)。//向DS1302内写周寄存器8aH写入调整后的周数据BCD码 write_1302(0x8e,0x80)。//打开写保护 write_1602com(yh+0x0e)。//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break。 case 5:ri++。 if(ri>31) ri=1。 write_nyr(9,ri)。//令LCD在正确的位置显示\"加\"设定好的日期数据

temp=(ri)/10*16+(ri)%10。//十进制转换成DS1302要求的BCD码 write_1302(0x8e,0x00)。//允许写,禁止写保护 write_1302(0x86,temp)。//向DS1302内写日期寄存器86H写入调整后的日期数据BCD码 write_1302(0x8e,0x80)。//打开写保护 write_1602com(yh+10)。//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break。 case 6:yue++。 if(yue>12) yue=1。 write_nyr(6,yue)。//令LCD在正确的位置显示\"加\"设定好的月份数据 temp=(yue)/10*16+(yue)%10。//十进制转换成DS1302要求的BCD码 write_1302(0x8e,0x00)。//允许写,禁止写保护 write_1302(0x88,temp)。//向DS1302内写月份寄存器88H写入调整后的月份数据BCD码 write_1302(0x8e,0x80)。//打开写保护 write_1602com(yh+7)。//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break。 case 7:nian++。 if(nian>99) nian=0。 write_nyr(3,nian)。//令LCD在正确的位置显示\"加\"设定好的年份数据 temp=(nian)/10*16+(nian)%10。//十进制转换成DS1302要求的BCD码 write_1302(0x8e,0x00)。//允许写,禁止写保护 write_1302(0x8c,temp)。//向DS1302内写年份寄存器8cH写入调整后的年份数据BCD码 write_1302(0x8e,0x80)。//打开写保护 write_1602com(yh+4)。//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break。 } } }

//------------------减键key3,各句功能参照'加键'注释--------------- if(key3==0) { delay(10)。//调延时,消抖动 if(key3==0) { while(!key3)。 switch(key1n) {

case 1:miao--。 if(miao==-1) miao=59。//秒数据减到-1时自动变成59 write_sfm(0x08,miao)。//在LCD的正确位置显示改变后新的秒数 temp=(miao)/10*16+(miao)%10。//十进制转换成DS1302要求的BCD码 write_1302(0x8e,0x00)。 //允许写,禁止写保护 write_1302(0x80,temp)。 //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码 write_1302(0x8e,0x80)。 //打开写保护 write_1602com(er+0x09)。//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置 //write_1602com(0x0b)。 break。 case 2:fen--。 if(fen==-1) fen=59。 write_sfm(5,fen)。 temp=(fen)/10*16+(fen)%10。//十进制转换成DS1302要求的BCD码 write_1302(0x8e,0x00)。//允许写,禁止写保护 write_1302(0x82,temp)。//向DS1302内写分寄存器82H写入调整后的分数据BCD码 write_1302(0x8e,0x80)。//打开写保护 write_1602com(er+6)。//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置 break。 case 3:shi--。 if(shi==-1) shi=23。 write_sfm(2,shi)。 temp=(shi)/10*16+(shi)%10。//十进制转换成DS1302要求的BCD码 write_1302(0x8e,0x00)。//允许写,禁止写保护 write_1302(0x84,temp)。//向DS1302内写小时寄存器84H写入调整后的小时数据BCD码 write_1302(0x8e,0x80)。//打开写保护 write_1602com(er+3)。//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break。 case 4:week--。 if(week==0) week=7。

write_1602com(yh+0x0C)。//指定'加'后的周数据显示位置 write_week(week)。//指定周数据显示内容

temp=(week)/10*16+(week)%10。//十进制转换成DS1302要求的BCD码 write_1302(0x8e,0x00)。//允许写,禁止写保护 write_1302(0x8a,temp)。//向DS1302内写周寄存器8aH写入调整后的周数据BCD码 write_1302(0x8e,0x80)。//打开写保护 write_1602com(yh+0x0e)。//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break。 case 5:ri--。 if(ri==0) ri=31。 write_nyr(9,ri)。 temp=(ri)/10*16+(ri)%10。//十进制转换成DS1302要求的BCD码 write_1302(0x8e,0x00)。//允许写,禁止写保护 write_1302(0x86,temp)。//向DS1302内写日期寄存器86H写入调整后的日期数据BCD码 write_1302(0x8e,0x80)。//打开写保护 write_1602com(yh+10)。//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break。 case 6:yue--。 if(yue==0) yue=12。 write_nyr(6,yue)。 temp=(yue)/10*16+(yue)%10。//十进制转换成DS1302要求的BCD码 write_1302(0x8e,0x00)。//允许写,禁止写保护 write_1302(0x88,temp)。//向DS1302内写月份寄存器88H写入调整后的月份数据BCD码 write_1302(0x8e,0x80)。//打开写保护 write_1602com(yh+7)。//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break。 case 7:nian--。 if(nian==-1) nian=99。 write_nyr(3,nian)。

temp=(nian)/10*16+(nian)%10。//十进制转换成DS1302要求的BCD码 write_1302(0x8e,0x00)。//允许写,禁止写保护 write_1302(0x8c,temp)。//向DS1302内写年份寄存器8cH写入调整后的年份数据BCD码 write_1302(0x8e,0x80)。//打开写保护 write_1602com(yh+4)。//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位 break。

} } } } }

/****************************************************/ /****************************************************/ /****************************************************/ void dingshi_dis() //定时时间显示函数 {

write_1602com(er+0x0d)。 //显示冒号 write_1602dat(tab2[2])。 write_1602com(er+0x0f)。 //显示秒 write_sfm(0x0e,dingmiao)。 write_1602com(er+0x0f)。 write_1602com(er+0x0c)。 // 显示分 write_sfm(0x0b,dingfen)。 write_1602com(er+0x0c)。 write_1602com(er+0x0a)。 //显示定时状态执行开还是关 if(dingrunstate==0) write_1602dat(tabrun[0])。 if(dingrunstate==1) write_1602dat(tabrun[1])。 if(dingrunstate==2) write_1602dat(tabrun[2])。 }

/******************************************************

6 按键定时时间函数

*****************************************************/

void keyscan1() //按键定时时间函数 { if(key4==0)//---------------key4为功能键(定时设置键)-------------------- { delay(10)。//延时,用于消抖动 if(key4==0)//延时后再次确认按键按下 { while(!key4)。 dingshi_dis()。 key2n++。 if(key2n==5) key2n=1。//设置按键共有秒、分、时、星期、日、月、年、 运行状态、返回,9

个功能循环 switch(key2n) { case 1: write_1602com(er+0x0f)。//设置按键按动一次,秒位置显示光标 write_1602com(0x0f)。//设置光标为闪烁 break。 case 2: write_1602com(er+0x0c)。//按2次分位置显示光标 break。

case 3:write_1602com(er+0x0a)。 //按动3次,运行状态位子显示光标 break。 case 4: write_1602com(0x0c)。//按动到第4次,设置光标不闪烁 flag1=0。 break。 } } }

//------------------------------加键key2---------------------------- if(key2n!=0)//当key4按下以下。再按以下键才有效(按键次数不等于零) { if(key2==0) //上调键 { delay(5)。 if(key2==0) { while(!key2)。 switch(key2n) { case 1:dingmiao++。//设置键按动1次,调秒 if(dingmiao>59) dingmiao=0。//秒超过59,再加1,就归零 write_sfm(0x0e,dingmiao)。//令LCD在正确位置显示\"加\"设定好的秒数 write_1602com(er+0x0f)。//因为设置液晶的模式是写入数据后,光标自动右移,所以要指定返回 break。 case 2:dingfen++。 if(dingfen>59) dingfen=0。 write_sfm(0x0b,dingfen)。//令LCD在正确位置显示\"加\"设定好的分数据 write_1602com(er+0x0c)。//因为设置液晶的模式是写入数据后,指针自动

加一,在这里是写回原来的位置 break。

case 3:dingrunstate++。 if(dingrunstate==3) dingrunstate=0。 write_1602com(er+0x0a)。 if(dingrunstate==0) { write_1602dat(tabrun[0])。 write_1602com(er+0x0a)。 } if(dingrunstate==1) { write_1602dat(tabrun[1])。 write_1602com(er+0x0a)。 } if(dingrunstate==2) { write_1602dat(tabrun[2])。 write_1602com(er+0x0a)。 } break。 } } } //------------------减键key3,各句功能参照'加键'注释--------------- if(key3==0) { delay(5)。//调延时,消抖动 if(key3==0) { while(!key3)。 switch(key2n) { case 1:dingmiao--。 if(dingmiao==-1) dingmiao=59。//秒数据减到-1时自动变成59 write_sfm(0x0e,dingmiao)。//在LCD的正确位置显示改变后新的秒数 write_1602com(er+0x0f)。//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置 break。 case 2:dingfen--。 if(dingfen==-1)

dingfen=59。 write_sfm(0x0b,dingfen)。 write_1602com(er+0x0c)。//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置 break。 case 3:dingrunstate--。 if(dingrunstate==-1) dingrunstate=3。 write_1602com(er+0x0a)。 if(dingrunstate==0) { write_1602dat(tabrun[0])。 write_1602com(er+0x0a)。 } if(dingrunstate==1) { write_1602dat(tabrun[1])。 write_1602com(er+0x0a)。 } if(dingrunstate==2) { write_1602dat(tabrun[2])。 write_1602com(er+0x0a)。 } break。 } } } } }

/******************************************************

7 步进电机控制程序函数

*****************************************************/ void motor_ccw(void) //电机反转函数 {

uchar i,j。

for(j=0。j<8。j++) //电机旋转一周,不是外面所看到的一周,是里面的传动轮转了一周 {

if(key7==0) {

break。 //如果K7按下,退出此循环

}

for(i=0。i<8。i++) //旋转45度 {

//P1=CCW[i]。 MA=tabD[i]。 MB=tabC[i]。 MC=tabB[i]。 MD=tabA[i]。

delay(5)。 //调节转速 } } }

void motor_cw(void) //电机正转函数 {

uchar i,j。

for(j=0。j<8。j++) {

if(key7==0) {

break。 //如果K7按下,退出此循环 }

for(i=0。i<8。i++) //旋转45度 {

//P1=CW[i]。 MA=tabDB[i]。 MB=tabCB[i]。 MC=tabBB[i]。 MD=tabAB[i]。

delay(5)。 //调节转速 } } }

void motor_back() //电机反转 {

write_1602com(er+0x01)。 write_1602dat(tabrun[2])。 //写运行状态反转B //for(r=0。rmotor_ccw()。

if(key7==0) //key7电机停止按键 { motorflag=0。 write_1602com(er+0x01)。

write_1602dat(tabrun[0])。 //break。 }

} }

void motor_run() //电机正转 {

write_1602com(er+0x01)。

write_1602dat(tabrun[1])。 //写运行状态正转A //for(r=0。rmotor_cw()。 if(key7==0) { motorflag=0。 write_1602com(er+0x01)。 write_1602dat(tabrun[0])。 //break。 }

} }

void motor_stop() //电机停止 { write_1602com(er+0x01)。 write_1602dat(tabrun[0])。 MD=0。 MC=0。 MB=0。 MA=0。 }

void keyscan2() // 电机控制按键扫描子涵数 {

if(key5==0) //key5电机反转按键 { delay(10)。 if (key5==0) { motorflag=1。 motor_back()。 } }

else if(key6==0) //key6电机正转按键 { delay(10)。 if(key6==0) { motorflag=1。 motor_run()。 } } else motor_stop()。 }

/******************************************************

8 I2C模块函数

*****************************************************/

void initbus() //总线初始化 { scl=1。 delay1()。 sda=1。 delay1()。 }

void start() //功能:起始信号(SCL线处于高电平,SDA由高电平跳到低电平) { sda=1。delay1()。 scl=1。delay1()。 sda=0。delay1()。 }

void stop() //功能:终止信号(当SCL线处于高电平时,SDA由低电平跳到高电平) { sda=0。delay1()。 scl=1。delay1()。 sda=1。delay1()。 }

void ask() //功能:应答信号 { uchar i=0。 scl=1。delay1()。// while((sda==1)&&(i<255))

{ i++。 } //如果数据线一直为高电平,则一段时间后则默认为应答(即时钟线由高到底的一个跳变--应答) scl=0。 delay1()。 }

void noask() //非应答函数 ,在数据线为高电平期间,时钟线一个完整的脉冲表示非应答 {

sda=1。 delay1()。 scl=0。 delay1()。 scl=1。 delay1()。 scl=0。 delay1()。 }

void write1byte(uchar dete) //功能:写一个字节 { uchar i,temp。 temp=dete。 scl=0。 //时钟线为低电平期间,允许数据变化 for(i=0。i<8。i++) { if(dete&0x80)//如果写进的数据与0x80进行与运算为“1”(即为真),则数据线为高电平 {

sda=1。 }

else //否则为低电平 {

sda=0。 } temp=temp<<1。//对8位数据进行移位操作 delay1()。 sda=CY。 delay1()。 scl=1。 //时钟线为高电平(即数据稳定),把数据取走 delay1()。 } scl=0。delay1()。 //吧时钟线拉回低电平 sda=1。delay1()。 //释放数据线 }

uchar read1byte() //功能:读一个字节 { uchar i,dete=0x00。 scl=0。delay1()。 sda=1。delay1()。//将总线释放 for(i=0。i<8。i++) { scl=1。delay1()。 dete=(dete<<1)|sda。 scl=0。delay1()。 } return dete。 }

uchar readfromadd(uchar address) //功能:读指定地址数据 { uchar temp。 start()。write1byte(0xa0)。 //指令码0xa0为写操作 ask()。write1byte(address)。ask()。 start()。write1byte(0xa1)。//指令码0xa1为读操作 ask()。temp=read1byte()。 stop()。return temp。 }

void writetoadd(uchar address,uchar dete) //输入指定地址及数据 (即写) { start()。write1byte(0xa0)。ask()。write1byte(address)。 ask()。write1byte(dete)。ask()。stop()。 }

/******************************************************

9 定时扫描子函数

*****************************************************/

void ding_shi()// 定时扫描子函数 { if((fen==dingfen)&&(miao==dingmiao)) switch(dingrunstate) { case 0:break。 case 1:motorflag=1。motor_run()。break。 case 2:motorflag=1。motor_back()。break。

} else delay(1)。 }

/******************************************************

10 光控子函数

*****************************************************/

void guangkong() {

if(light!=light) {

if(light==0) { lighttemp=light。 motorflag=1。 motor_run()。 } else { lighttemp=light。 motorflag=1。 motor_back()。 } } }

//-------------------------------

void init() //定时器、计数器设置函数 { EX0=1。//允许外部中断0中断 EX1=1。//允许外部中断1中断 IT0=1。 IT1=1。 EA=1。 //系统允许有开放的中断 }

/******************************************************

11 主函数

*****************************************************/

void main() {

delay(100)。 lcd_init()。 //调用液晶屏初始化子函数 ds1302_init()。 //调用DS1302时钟的初始化子函数 init()。 //中断初始化子函数 delay(10)。 initbus()。 // 总线初始化 write_week(week)。 lighttemp=light。 while(1) //无限循环下面的语句: { timegetdisp()。 //时间显示函数 ding_shi()。// 定时扫描子程序 guangkong()。 if(key1==0) { flag=1。 while(flag) keyscan()。 } if(key4==0) { flag1=1。 while(flag1) keyscan1()。 } keyscan2()。 //调用步进电机键盘扫描子函数 } }

/******************************************************

12 红外中断函数

*****************************************************/ void itn1() interrupt 1 using 2 //函数功能:外部中断1处理函数 { uchar i,j,num=0。 EX1=0。 delay(15)。

if(red==1) { EX1=1。 return。 } while(!red) // 去掉9ms的前导低电平信号 { delay0(1)。 } for(i=0。i<4。i++) { for(j=0。j<8。j++) { while(red) // 去4.5ms的前导高电平信号 { delay0(1)。 } while(!red)。//去除上一次低电平的干扰保证每次取0,1的准确 while(red) //计算高电平时长 { delay0(1)。 num++。 if(num>=30) { EX1=1。 return。 } } s[i]>>=1。 if(num>=8) s[i]|=0x80。 num=0。 } } if(s[2]!=~s[3]) //s[2]是否s[3]相反 { EX1=1。 return。 } switch(s[2]) { case 0x47: motor_stop()。break。 case 0x40: motorflag=1。motor_back()。break。

}

} EX1=1。

case 0x44:motorflag=1。 motor_run()。break。

default:break。

致谢

毕业设计即将完成,在这里我要衷心感谢所有在设计过程中给我提供帮助的老师和同学,没有他们的帮助,我的毕业设计不可能这么顺利的完成。

首先要感谢的是指导老师赵进辉老师,赵老师给我提供了很大的帮助。在完成毕业设计的过程中,赵老师给我指出了很多错误,提出了很多宝贵意见,还给我提供了毕业设计中所用到设备的支持。赵老师每次在查看我的进度的同时都是认真查看我的设计,对于设计中存在的问题也是耐心的回答和讨论。毕业设计的初稿赵老师也是仔细审阅,细节部分的问题也被他看出。在此对于赵老师一丝不苟,兢兢业业的精神表示衷心的敬佩。

同时,我要向在这次毕业设计中给我提供帮助和提出意见的同组同学表示感谢,在整个论文的选题、理论研究、需求分析和系统设计的过程中,他们给了我不少启发并对论文的设计方案提出了许多至关重要的建议,在实验过程中帮我解决了不少的难题。在论文写作期间曾经遇到过很多的阻力,但是在大家的帮助下总算是顺利地度过了。在他们的帮助和建议下,我的毕业设计才得以更加顺利的完成。

我还要感谢这一领域的学者们,是他们给我经验和研究方向,文中引用了一些他们研究成果,在此一并表示衷心的感谢。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- igbc.cn 版权所有 湘ICP备2023023988号-5

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务