基于STC89C51单片机的智能足浴器设计

摘  要

本设计采用STC89C51单片机为核心来设计智能足浴器。本设计也对单片机控制足浴器实现智能化的可能性进行了分析,利用温度传感器、和继电器等来完成本设计。在硬件设计方面,主要对单片机最小系统及其扩展、电源电路、键盘显示及接口电路、水温检测电路、报警电路进行了详细介绍。还详细介绍了设计中应用到的主要芯片的性能和特点,包括STC89C51、DS18B20等。在软件设计方面,采用C语言编程。

该智能足浴器设计完善,实现方案简单易行。采用软件设计来控制,可以实现智能检测水温,智能加热,并且提高了整机的可靠性及准确性。

关键词:STC89C51,DS18B20,智能

第1章  绪论

1.1 选题的背景、目的及意义

足浴器市场现状和未来前景展望,消费需求的火爆反映了足浴器市场正在爆发式的扩张,尤其是自2012年到2013年之间,足浴器市场需求的发展和壮大是非常迅速的,拒不完全统计随着中国社会老龄化现象的出现,足浴器市场需求也随之爆炸式发展,每年会有几千万台的增长量,这个速度还是相当惊人的。 

正是在这样的背景下,本设计选择基于STC89C51单片机的智能足浴器系统设计研究。

本选题目的是基于人们对现代家庭舒适、便利、安全以及多元化信息服务的需要,基于STC89C51单片机设计具有智能特征的足浴器。

选用STC89C51单片机作为控制芯片,就是为了实现足浴器的智能化,自动断电的安全功能,使人们洗脚时能放心享受,利于人们的身体健康,其务实性能快速满足人们对现代生活快节奏的需求。

1.2 研究设想和实验设计

STC89C51单片机低功耗,高性能CMOS8位单片机,片内4kb的可系统编程Flash只读程序存储器,器件采用高密度、非易失性存储技术生产,兼容标准8051指令系统及引脚。它集合了Flash程序存储器,既可在线编程(ISP)也可用传统方法进行编程及通用8位微处理器于单片机芯片中,功能很强大,可灵活应用于各种控制领域。基于此,我采用STC89C51作为智能电足浴器的控制芯片,通过选用电源模块、单片机模块、ISP在线编程接口、键盘模块、数码管及指示灯显示模块、水温、水位检测模块、报警输出模块,来实现智能控制的要求。

具体实验设计:

STC89C51采用+5V电源供电,设计要求制作一直流稳压电源,采用220V市电供电,经桥式整流后送入滤波电路,再经稳压芯片CW7805输出+5V电压。单片机容易受外界环境干扰,因此要求供电电源单独设计制作。单片机硬件部分由单片机最小系统配以按键、显示器件构成。限于单片机型号采用12MHz晶振和两个30μF陶瓷平衡电容组成振荡电路。为使硬件具有通用性,复位电路采用上电与按键复位结合设计,独立式按键通过P1口扫描查询,分别执行设置、加、减、确定功能。系统还有红外遥控的功能,可以通过红外遥控器远距离控制热水器的工作,提高了系统的安全性。系统工作时,首先检测功能按键,进行温度范围设置。其次检测加减按键,进行温度范围调节,也可以按下红外遥控器上的按键操作,与主板上的按键功能一样,然后运行程序,由传感器DS18B20检测水温,当检测温度低于预设温度下限时,开始加热;检测温度高于预设温度上限时,停止加热。并可以设置加热时间,设定时间0-999分钟,定时时间到达自动断电。

第2章 硬件系统设计

2.1 方案验证

        本课题是基于STC89C51单片机的智能足浴器的控制器的设计,要达到的控制要求有:(1)用LCD1602液晶显示水温、设置上下限和定时时间,(2)水温检测显示范围为00~99℃,精度为±1℃。(3)温度预设范围为0~99℃,当检测温度低于预设温度时,开始加热;检测温度高于预设温度时,停止加热。(4)设置4个程序按键。分别问设置按键、加键、减键、确定。(5)可以红外遥控,通过红外一体接收探头接收遥控器信号,执行与主板按键同等功能。

方案一:以STC89C51单片机为控制中心的智能足浴器

        STC89C51单片机具有结构简单、控制能力强、可靠性高、体积小、价格低等优点,在许多行业都得到了广泛的应用。以STC89C51单片机为核心,配以外围电路如时钟电路、复位电路、按键、显示器件即可构成足浴器系统,结构框图如图2.1.1:

方案二:PIC16C72单片机为控制器件的智能足浴器

PIC16C72是美国微芯(Microchip)公司推出的8/11位单片机,采用宽字节单周期指令,哈佛双总线和RISC结构,其数据吞吐量最高可达6MIPS,这几乎是其它大多数8位微控制器速度的4倍128脚封装的PIC16C72单片机内集成了以下主要功能:2KB片内ROM程序存储器,128KB数据存储器;22位I/O线;5路8位A/D转换器,2个8位,1个16位多功能计数器/定时器,1个捕捉/比较/脉宽调制(CCP)部件。

以PIC16C72为控制芯片的足浴器,虽然功能很强大,但是存在一些很需要改进的地方:中断的现场保护是中断应用中一个很重要的部分由PIC16C72的指令系统中没有专门的PUSH(入栈)和POP(出栈)指令,所以要用一段程序来实现该功能。对可能用到的W寄存器和STATUS寄存器内容进行现场保护1然后在中断服务程序中对马达,继电器进行控制1漏电检测报警在中断里给出,而每50ms进入一次中断,所以发生漏电时最多50ms即可切断电源1入口→中断保护→控制马达→控制继电器如果用直流对电机进行控制,其转速太快,过调量太大,容易引起震荡。

通过以上两种设计方法的比较来看,实现足浴器的智能控制可以有很多种方法。可以采用可编程序控制器PLC,各种单片机来实现。但考虑到成本控制和软硬件实现难度,采用方案一的控制系统设计,可以进一步提高足浴器的智能作用,能够保证持续的热水供应,并可以满足人们日常生活的需要,提高了人们生活的质量。

时钟电路用来产生时钟信号供单片机工作,晶振采用12MHz,平衡电容采用30pF。复位电路在系统上电或运行过程中对单片机进行初始化操作。按键采用独立式热键,用来扩展系统功能。显示通过LCD1602液晶显示实时温度、上下限温度值和预约功能的定时时间。报警指示灯(黄):当热水器出现异常情况时,该指示灯被点亮。

依据设计要求,系统上电复位后按默认值开始运行,然后开始检测温度按键,若无按键,则按设定温度进行工作;若温度键已按下,则开始设定温度范围,并按新的设定值开始加热。接着继续检测温度按键,若无按键,则接着上一步的执行(以新的设定值开始工作)。若有按键,则重新设定温度范围,如此循环。

2.2 硬件系统设计

单片机应用系统的硬件电路设计包含两部分内容:一是系统扩展,即单片机内部的功能单元,如ROM、RAM、I/O、定时器/计数器、中断系统等不能满足应用系统的要求时,必须在片外进行扩展,选择适当的芯片,设计相应的电路。二是系统的配置,即按照系统功能要求配置外围设备,如键盘、显示器、打印机、A/D、D/A转换器等,要设计合适的接口电路。本设计中只用最小系统加上键盘、显示、ISP接口电路,单片机本身资源可以满足设计要求,所以不必对单片机进行扩展。

系统的硬件系统以STC89C51单片机为核心,主要分两部分:直流稳压电源和智能足浴器控制电路,其原理图见附录二。直流稳压电源由变压器、整流桥、滤波电路、稳压电路组成。智能足浴器系统由时钟电路、复位电路、报警电路、键盘、温度检测电路和显示接口电路组成。

2.2.1 电源电路

        电源电路按元件类型可分为电子管稳压电路、三极管稳压电路、可控硅稳压电路、集成稳压电路等。根据调整元件与连接方法,可分为并联型和串联型;根据调整元件工作状态不同,可分为线性和开关稳压电路。本设计中采用了线性工作状态的线性集成稳压电源。

        直流稳压电源一般由电源变压器、整流滤波电路及稳压电路所组成,设计框图:

各部分简介:

(1)电源变压器

电源变压器作用是将电网220V的交流电压V1变换成整流滤波电路所需的交流电压V2。变压器副边与原边的功率比P2/P1=η,式中η为变压器的效率。

(2)整流滤波电路

整流电路将交流电压变成单向脉动的直流电压。滤波电路用来滤除整流后单向脉动电压中的交流成份,合之成为平滑的直流电压。

常用的整流电路有全波整流电路、半波整流电路、桥式整流电路及倍压整流电路。小功率直流电源因功率比较小,通常采用单相交流供电。由于桥式整流电路克服了半波整流的缺点,在桥式整流电路中,由于每两只二极管只导通半个周期,故流过每个二极管的平均电流仅为负载电流的一半,与半波整流电路相比较,其输出电压提高,脉动成分减少。

整流电路将交流电变为脉动直流电,但其中含有大量的交流成分(称为纹波电压)。为了获得平滑的直流电压,应在整流电路的后面加接滤波电路,以滤去交流成分。滤波电路常见的有电容滤波电路、电感滤波电路及π型滤波电路。本设计采用电容滤波电路。电容滤波电路主要利用电容两端电压不能突变的特性,使负载电压波形平滑,故电容应与负载并联。桥式整流电路带电阻负载时的输出直流电压U0=0.9V,接上电容滤波后,空载时的输出直流电压U0=UC=U2。所以,接上负载时的桥式整流电容滤波电路的输出电压介于上述两者之间,其大小与放电时间常数RLC有关,RLC越大,U0越大。

(3)稳压电路

稳压电路的作用是当输入交流电源电压波动、负载和温度变化时,维持输出直流电压的稳定。由于三端式稳压器只有三个引出端子,具有应用时外接元件少、使用方便、性能稳定、价格低廉等优点,因而广泛应用。三端式稳压器有两种,一种称为固定输出三端稳压器,另一种称为可调输出三端稳压器。它们的基本组成及工作原理都相同,均采用串联型稳压电路。

(4)三端固定输出集成稳压器通用产品有CW7800T系列和CW7900系列。

1正压系列:CW7800系列,该系列稳压块有过流、过热和调整管工作保护,以防过载而损坏。一般不需要接元件即可工作,有时为改善性能也会加少量元件。

2负压系列:CW7900系列与CW7800系列相比,除了输出电压极性、引脚定义不同外,其它特点都相同。

(5)稳压电源的技术指标分为两种:

一是特性指标,包括允许的输入电压、输出电压、输出电流及输出电压调节范围等;另一种是质量指标,用来衡量输出直流电压的稳定程度,包括稳压系数(或电压调整流器率)、输出电阻、温度系数及纹波电压等。

(6)电路目的:给单片机及其他控制电路提供电源。

电源设计是电路设计很重要关节。它的稳定与否涉及到电路是否能稳定工作。按要求需要一个+5V电压,一个+12V左右可调电压。于是采用可调压芯片LM317,它是稳压芯片。LM317是三端稳压集成电路,最大输出电流为2.2A,输出电压范围为1.25V~37V。它具有输出电压可变、内藏保护功能、体积小、性价比高、工作稳定可靠等特点。用它制作输出电压可变稳压电源,调节可变电阻R2,便可从LM317输出端获得UO(可变输出电压)。

从电路中可以看出,LM317的输出电压(也就是稳压电源的输出电压)U0为两个电压之和,也就是R1两端电压与R2两端电压之和。而IR2实际上是两路电流之和,一路是经R1流向R2的电流IRI,其大小为URI/Rl。因URI为恒定电压1.25V,Rl是一个固定电阻,小于240欧姆。所以IRl是一个恒定的电流。另一路是LM317调整端流出的电流ID,ID的平均值是50μA左右,最大值一般不超过100μA。而且在LM317稳定工作时,ID的值基本上是一个恒定的值。调节R2阻值即可调节LM317输出电压UO。

既然ID和IRl对调节输出电压UO都起到了一定作用,并且IR1是由R1提供,IRI大小也没有任何限制,LM317输出电压服从1.25+IDR2=UO关系。

可调稳压电路原理图如图2.4所示。

图2.2.1.2 可调稳压电路原理图

+5V电压也是利用三端稳压集成电路得到的,采用7805芯片。其用法和LM317差别不大,如下图所示。LM7805的1端是电源的输入端,3端是输出端,2端是接地端。

图2.2.1.3 7805三端稳压电源电路

本设计电源电路原理图见附录3。

2.2.2 键盘接口电路

按键输入均采用低电平有效,此外,上拉电阻保证了按键断开时,I/O口线有确定的高电平。当I/O口线内部有上拉电阻时,外电路不可接上拉电阻。独立式按键的软件常采用查询式结构。先逐位查询每根I/O口线的输入状态,如某一根I/O口线输入为低电平,则可确认该I/O口线所对应的按键已按下,然后,再转向该键的功能处理程序,具体编程见程序清单。

2.2.3 报警电路

当温度超过上限是电路会报警,提示水温过高,注意安全。图下面位报警电路:

2.2.5温度检测电路

本文采用温度传感器DS18B20采集足浴器的实时温度, 提供给STC89C51的P2.2口作为数据输入。在本次设计中我们所控的对象为水温。其电路原理框图如下:

 图2.2.5.1 温度检测电路

DS18B20是DALLAS公司生产的一线式数字温度传感器,具有3引脚TO-92小体积封装形式;温度测量范围为-55℃~+125℃,可编程为9位~12位A/D转换精度,测温分辨率可达0.0625℃,被测温度用符号扩展的16位数字量方式串行输出,支持3V~5.5V的电压范围,使系统设计更灵活、方便;其工作电源既可在远端引入,也可采用寄生电源方式产生;多个DS18B20可以并联到3根或2根线上,CPU只需一根端口线就能与诸多DS18B20通信,占用微处理器的端口较少,可节省大量的引线和逻辑电路。以上特点使DS18B20非常适用于远距离多点温度检测系统。分辨率设定,及用户设定的报警温度存储在EEPROM中,掉电后依然保存。DS18B20使电压、特性有更多的选择,让我们可以构建适合自己的经济的测温系统。如图2所示DS18B20的2脚DQ为数字信号输入/输出端;1脚GND为电源地;3脚VDD为外接供电电源输入端。

当传感器工作时,如果水温超过60℃,将温度传给单片机,蜂鸣器报警,并断电;如果水温低于30℃,热水器开始工作,加热指示灯亮。

2.2.7 红外一体接收模块

红外传感器接收到人体红外信号经BISS0001处理后输出输给单片机P1.0口,TEL0表示接STC89C52是的P1.0口,通过对P1.0电平的判断,实现对单片机外围电路的控制,如电磁阀控制水阀电路,液晶显示淋浴时间等。红外采集电路[7]如图3-5:

3.3显示电路设计

在本系统中,用LCD液晶屏来构成显示部分,主要在人来时对淋浴计时时间和定时时间的显示。LCD液晶显示器具有功耗低、寿命长、无辐射、不易引起视疲劳等优点,正在被广泛应用于仪表、家用电器、计算机、医疗仪器及交通和通信领域[8]。本系统中,选择JHD162A作为液晶屏的显示驱动控制器。

3.3.1 1602液晶模块JHD162A 简介

字符型液晶显示模块是一种专门用于显示字母、数字、符号等点阵式LCD 目前常用16*1 16*2 20*2和40*2行等的模块。是一种很常用的小型液晶显示模块 在单片机系统、嵌入式系统等的人机界面中得到了广泛的应用。

  1. 1602LCD主要技术参数如下:

(1)显示容量:16×2个字符

(2)芯片工作电压:4.5-5.5V

(3)工作电流:2.0mA(5.0V)

(4)模块最佳工作电压:5.0V

(5)字符尺寸:2.95×4.35(W×H)mm

    1. 引脚功能说明:

1602LCD采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如表3.3所示:

3.3 引脚接口说明表

编号

符号

引脚说明

编号

符号

引脚说明

1

VSS

电源地

9

D2

数据

2

VDD

电源正极

10

D3

数据

3

VL

液晶显示偏压

11

D4

数据

4

RS

数据/命令选择

12

D5

数据

5

R/W

读/写选择

13

D6

数据

6

E

使能信号

14

D7

数据

7

D0

数据

15

BLA

背光源正极

8

D1

数据

16

BLK

背光源负极

  1. 1602LCD的指令说明及时序

1602液晶模块内部的控制器共有11条控制指令,如表3.4所示:

3.4 指令说明

序号

指令

RS

R/W

D7

D6

D5

D4

D3

D2

D1

D0

1

清显示

0

0

0

0

0

0

0

0

0

1

2

光标返回

0

0

0

0

0

0

0

0

1

*

3

置输入模式

0

0

0

0

0

0

0

1

I/D

S

4

显示开/关控制

0

0

0

0

0

0

1

D

C

B

5

光标或字符移位

0

0

0

0

0

1

S/C

R/L

*

*

6

置功能

0

0

0

0

1

DL

N

F

*

*

7

置字符发生存贮器地址

0

0

0

1

字符发生存贮器地址

8

置数据存贮器地址

0

0

1

显示数据存贮器地址

9

读忙标志或地址

0

1

BF

计数器地址

10

写数到CGRAM或DDRAM)

1

0

要写的数据内容

11

从CGRAM或DDRAM读数

1

1

读出的数据内容

1602液晶模块的读写操作、屏幕和光标的操作都是通过指令编程来实现的。(说明:1为高电平、0为低电平)。

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

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

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

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

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

指令6:功能设置命令DL:高电平时为4位总线 低电平时为8位总线 N:低电平时为单行显示 高电平时双行显示 F: 低电平时显示5×7的点阵字符 高电平时显示5×10的点阵字符。

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

指令8:DDRAM地址设置。

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

指令10:写数据。

指令11:读数据。

读操作时序如图3-6所示:

写操作时序如图3-7所示:

图3-7 写操作时序图

3.3.2单片机与1062LCD接口电路设计

根据1062LCD的工作原理,我们可以设计单片机与1062LCD的接口电路图如3-8所示:

2.2.7 STC89C51功能特点介绍

 (1)主要性能参数:

1与 MCS-51 产品指令系统完全兼容

24k字节在线系统编程(ISP)Flash 闪速存储器

31000次擦写周期                          

43.3-5.5V 的工作电压范围

5全静态工作模式:0Hz-33MHz

6三级程序加密锁

7128×8字节内部RAM

832个可编程I/O口线                           

92个16位定时/计数器

106个中断源

11全双工串行UART通道

12低功耗空闲和掉电模式

13看门狗(WDT)及双数据指针

14掉电标识和快速编程特性

15灵活的在线系统编程(ISP字节或页写模式)

(2)串行编程指令设置:

串行编程指令设置为一个4字节协议。

(3)并行编程接口:

采用控制信号的正确组合可对Flash闪速存储阵列中的每一代码字节进行写入和存储器的整片擦除,写操作周期是自身定时的,初始化后,它将自动定时到操作完成。

(4)功能特性概述:

STC89C51 提供以下标准功能:4k字节Flash闪速存储器,128字节内部RAM,32个I/O口线,看门狗(WDT),两个数据指针,两个16位定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。同时,STC89C51可降至0Hz的静态逻辑操作,并支持两种软件可选的节电工作模式。空闲方式停止CPU的工作,但允许RAM,定时/计数器,串行通信口及中断系统继续工作。掉电方式保存RAM中的内容,但振荡器停止工作并禁止其它所有部件工作直到下一个硬件复位。

(5)芯片擦除:

在并行编程模式,利用控制信号的正确组合并保持ALE/PROG引脚200ns-500ns的低电平脉冲宽度即可完成擦除操作。在串行编程模式,芯片擦除操作是利用擦除指令进行。在这种方式,擦除周期是自身定时的,大约为500ms。擦除期间,用串行方式读任何地址数据,返回值均为00H。

(6)Flash闪速存储器的串行编程:

将RST接至Vcc,程序代码存储阵列可通过串行ISP接口进行编程,串行接口包含SCK线、MOSI(输入)和MISO(输出)线。将RST拉高后,在其它操作前必须发出编程使能指令,编程前需将芯片擦除。芯片擦除则将存储代码阵列全写为FFH。外部系统时钟信号需接至XTAL1端或在XTALl和XTAL2接上晶体振荡器。最高的串行时钟(SCK)不超过l/16晶体时钟,当晶体为33MHz时,最大SCK频率为2MHz。Flash闪速存储器的串行编程方法:

1上电次序:将电源加在Vcc和GND引脚,RST置为“H”,如果XTAL和XTAL2接上晶体或者在XTAL1接上3-33MHz的时钟频率,等候10ms。

2将编程使能指令发送到MOSI(Pinl.5),编程时钟接至SCK(Pinl.7),此频率需小于晶体时钟频率的l/16。

3代码阵列的编程可选字节模式或页模式。写周期是自身定时的,一般不大于 0.5ms(5V 电压时)。

4任意代码单元均可由MISO(Pinl.6)和读指令选择相应的地址回读数据进行校验。

5编程结束应将RST置为“L”以结束操作。

6断电次序:如果需要的话按这个方法断电,假如没有使用晶体,将XATL置为低,RST置低,关断Vcc。

(7)数据校验:

数据校验也可在串行模式下进行,在这个模式下,在一个写周期中,通过输出引脚MISO串行回读一个字节数据的最高位将作为最后写入字节的反码。

(8)STC89C51单片机最小系统

STC89C51单片机最小系统由STC89C51单片机及其外围电路组成,外围电路包括时钟电路和复位电路两部分。

1时钟电路:时钟电路为单片机产生时序脉冲,单片机所有运算与控制过程都是在统一的时序脉冲的驱动下的进行的,时钟电路就好比人的心脏。同样,如果单片机的时钟电路停止工作(晶振停振),那么单片机也就停止运行了。当采用内部时钟时,连接方法如下图所示,在晶振引脚XTAL1(19脚)和XTAL2(18脚)引脚之间接入一个晶振,两个引脚对地分别再接入一个电容即可产生所需的时钟信号,电容的容量一般在几十皮法,如30PF。

单片机内部有一个高增益反向放大器,输入端为芯片引脚XTAL1,输出端为引脚XTAL2。而在芯片外部XTAL1和 XTAL2之间跨接晶体震荡器和微调电容,从而构成一个稳定的自激振荡器。外接晶体(石英或陶瓷,陶瓷的精度不高,但价格便宜)振荡器以及电容C1和C2构成并联谐振电路,接在放大器的反馈回路中, C1和C2的大小会对振荡器频率的高低、振荡器的稳定性、起振的快速性和温度特性有一定的影响。因此建议在采用石英晶体振荡器时取C=30+/-10pF,陶瓷振荡器时取C=40+/-10pF,典型值为40pF。在设计电路板时,振荡器和电容应尽量安装得与单片机靠近,以减小寄生电容的存在,更好的保障振荡器稳定、可靠的工作。在任何情况下,振荡器始终驱动内部时钟发生器向主机提供时钟信号,因为时钟发生器的输入是一个二分频电路,所以对外部振荡信号的脉宽无特殊要求,但必须保证高、低电平的最小宽度。

2复位电路:单片机的复位电路分上电复位和按键手动复位。它是利用外部复位电路来实现的。当Vcc上升时间不超过1ms(RC=τ),振荡器启动时间不超过10ms。在加电情况下,这个电路可以使单片机复位。在加电开机时,RST上的电压从Vcc逐渐下降,RST引脚的电位是Vcc与电容电压的差,RST上的电压必须保证在斯密特触发器的阀值电压以上足够长时间,以满足复位操作的要求。按键电平复位是将复位端通过电阻与Vcc相连。在按键电平复位和按键脉冲复位两种简单的复位电路中,干扰易串入复位端,在大多数情况下,不会造成单片机的错误复位,但会引起内部寄存器错误复位,这里可在复位端引脚上接一个去藕电容。需说明的是,如复位电路中R、C的值选择不当,使复位时间过长,单片机将处于循环复位状态。

为了使用方便和设计电路简化及设计要求,我们采用上电复位和按键电平复位相结合的方法。复位后,单片机从0000H单元开始执行程序,并初始化一些专用寄存器为复位状态值,受影响的专用寄存器如下表所示:

            表2.2.7.1 专用寄存器状态表

寄存器

状态

寄存器

状态

PC

0000H

TCON

00H

ACC

00H

TL0

00H

PSW

00H

TH0

00H

SP

07H

TL1

00H

DPTR

0000H

TH1

00H

P0 -- P3

FFH

SCON

00H

IP

xxx00000H

SBUF

不确定

IE

0xx00000H

PCON

0xxx0000H

TMOD

00H

 

 

   图2.2.7.1 单片机最小系统     

第3章 软件系统设计

软件设计由主程序,键扫描子程序及若干功能模块子程序组成。其中主控制器子程序测温程序,键盘处理及显示子程序,等组成。主程序要先初始化系统的工作参数,统主程序循环调用各个功能模块子程序,对相关事件的处理依靠标志位和判断标志位实现。

3.1 主程序流程框图

致  谢

首先,衷心感谢我的指导老师*********老师和**********老师。本课题是在老师的指导下完成的。在我整个的毕业设计制作过程中,受到两位老师很多的帮助。从设计的选题、研制计划的安排到设计的具体过程,两位老师都给予了悉心的指导。王老师严谨的治学态度、开明的学术思想,老师事必躬亲的工作精神、和宽人律己的高尚品德深深打动着我,使我倍受教育。值此毕业设计完成之际,谨向***老师、***老师致以诚挚的谢意!再一次向他们表示衷心的感谢,感谢他们为学生营造的浓郁学习氛围,以及学习、生活上的无私帮助!

同时感谢//通信与控制工程系的所有教师对我的学业和成长付出宝贵的时间和辛勤的汗水;感谢*************班的同学们在学习、生活上给我大力的支持和帮助。在此论文完成之际,我衷心的祝愿你们身体健康,工作顺利!!

学生签名:

日    期:

参考文献

[1] 吴国经.单片机应用技术[M].北京:中国电力出版社.2004:10.

[2] 张振荣.MCS-51单片机原理及实用技术[M].北京:人民邮电出版社.2000:10-13.

[3] 沈红卫.基于单片机的智能系统设计与实现[M].北京:电子工业出版社.2005:30-35.

[4] 肖洪兵.跟我学用单片机[M].北京:北京航空航天大学出版社.2002:100-103.

[5] 楼然苗.51系列单片机设计实例[M].北京:北京航空航天大学出版社.2003:50-60.

[6] 李光飞.单片机课程设计实例指导[M].北京:北京航空航天大学出版社.2004:14-17.

[7] 张丰.电子开发论坛[EB/OL].

http://bbs.dzkf.net/pub/txt/9888.html,1996-8-14.

[8] 徐惠民、安德宁.单片微型计算机原理接口与应用[M].北京:北京邮电大学出版社.1996:80-88.

[9] 夏继强.单片机实验与实践教程[M].北京:北京航空航天大学出版社.2001:71-76.

[10] 何立民.单片机高级教程[M].北京:北京航空航天大学出版社.2001:51-59.

[11] 张友德,涂时亮,陈章龙.MC68HC08系列单片机原理与应用[M].上海:复旦大学出版社.2001:16-18.

[13] 刘筱明.电脑足浴器继电器非正常状态下的保护措施[D].广东顺德万和电器有限公司. 1999.

[14] 李建事.陈刚. 家用电器单片机控制系统的制作与检修[M]. 上海:上海交通大学出版社.1998:22-30.

[15] 杨宁. 单片机与控制技术[M]. 北京:北京航空航天大学出版社.2005:33-36.

[16] 付家才.单片机控制工程实践技术[M].北京:化学工业出版社.2004:42-45.

程序

#include <reg52.h>
//显示函数
#include <display.h>
//宏定义
#define uint unsigned int 
#define uchar unsigned char
 
//管脚声明
sbit jdq= P1^0;	//继电器
sbit Feng = P2^6; //蜂鸣器
//按键
sbit Key1=P1^4;	 //设置
sbit Key2=P1^5;	 //加
sbit Key3=P1^6;	 //减
sbit Key4=P1^7;	 //确定

sbit DQ=P2^2;     			//定义DS18B20总线I/O
signed char w,bj,bjx,bjd;     				//温度值全局变量
uint c;				//温度值全局变量
bit bdata flag=0;
//时间计算
#define Imax 14000    //此处为晶振为11.0592时的取值, 
#define Imin 8000    //如用其它频率的晶振时,
#define Inum1 1450    //要改变相应的取值。
#define Inum3 3000 
//解码变量
unsigned char Im[4]={0x00,0x00,0x00,0x00};

//全局变量
uchar f;
unsigned long m,Tc;
unsigned char IrOK;

//设置变量

uchar xx=29;
//下限
uchar sx=35;
//上限
int ds=0;
uchar Mode=0;

void delay(uint z)
{
	uint i,j;
	for(i=0;i<z;i++)
	for(j=0;j<121;j++);
}
/*****延时子程序*****/
void Delay_DS18B20(int num)
{
  while(num--) ;
}
/*****初始化DS18B20*****/
void Init_DS18B20(void)
{
  unsigned char x=0;
  DQ = 1;         //DQ复位
  Delay_DS18B20(8);    //稍做延时
  DQ = 0;         //单片机将DQ拉低
  Delay_DS18B20(80);   //精确延时,大于480us
  x = DQ;           //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
  Delay_DS18B20(20);
}
/*****读一个字节*****/
unsigned char ReadOneChar(void)
{
  unsigned char i=0;
  unsigned char dat = 0;
  for (i=8;i>0;i--)
  {
    DQ = 0;     // 给脉冲信号
    dat>>=1;
    DQ = 1;     // 给脉冲信号
    if(DQ)
    dat|=0x80;
    Delay_DS18B20(4);
  }
  return(dat);
}
/*****写一个字节*****/
void WriteOneChar(unsigned char dat)
{
  unsigned char i=0;
  for (i=8; i>0; i--)
  {
    DQ = 0;
    DQ = dat&0x01;
    Delay_DS18B20(5);
    DQ = 1;
    dat>>=1;
  }
}
/*****读取温度*****/
unsigned int ReadTemperature(void)
{
  unsigned char a=0;
  unsigned char b=0;
  unsigned int t=0;
  float tt=0;
  WriteOneChar(0xCC);  //跳过读序号列号的操作
  WriteOneChar(0x44);  //启动温度转换
  Init_DS18B20();
  WriteOneChar(0xCC);  //跳过读序号列号的操作
  WriteOneChar(0xBE);  //读取温度寄存器
  a=ReadOneChar();     //读低8位
  b=ReadOneChar();    //读高8位
  t=b;
  t<<=8;
  t=t|a;
  tt=t*0.0625;
  t= tt*10+0.5;     //放大10倍输出并四舍五入
  return(t);
}
//=====================================================================================
//=====================================================================================
//=====================================================================================


/*****读取温度*****/
void check_wendu(void)
{
	c=ReadTemperature()-5;  			//获取温度值并减去DS18B20的温漂误差
	w=c/10;      						//计算得到整数位
	if(w<0){w=0;}   				//设置温度显示上限
	if(w>99){w=99;}   				//设置温度显示上限    
}
void Key()
{
	//模式选择
	if(Key1==0)
	{
		while(Key1==0);
		Feng=0;
		if(Mode==4)
		{
			Mode=1;
			Feng=1;
		}
   		write_com(0x38);//屏幕初始化
   		write_com(0x0d);//打开显示 无光标 光标闪烁
   		write_com(0x06);//当读或写一个字符是指针后一一位
		switch(Mode)
		{
			case 1:
			{
				write_com(0x80+15);//位置
				Feng=1;
				break;
			}
			case 2:
			{
				write_com(0x80+0x40+5);//位置
				Feng=1;
				break;
			}
			case 3:
			{
				write_com(0x80+0x40+14);//位置
				Feng=1;
				break;
			}
		}
	}
	if(Key2==0&&Mode!=0)
	{
		while(Key2==0);
		Feng=0;
		switch(Mode)
		{
			case 1:
			{
				if(ds<999)
				{
					ds++;
					write_com(0x80+13);
					write_data('0'+ds/100);
					write_com(0x80+15);//位置
				}
				Feng=1;
				break;
			}
			case 2:
			{
				if(sx<99-1)
				{
					sx++;
					write_com(0x80+0x40+4);
					write_data('0'+sx/10%10);
					write_data('0'+sx%10);
					write_com(0x80+0x40+5);//位置
				}
				Feng=1;
				break;				
			}
			case 3:
			{
				if(xx<sx-1)
				{
					xx++;
					write_com(0x80+0x40+13);
					write_data('0'+xx/10%10);
					write_data('0'+xx%10);
					write_com(0x80+0x40+14);//位置
				}
				Feng=1;
				break;				
			}		
		}
	}
	if(Key3==0&&Mode!=0)
	{
		while(Key3==0);
		Feng=0;
		switch(Mode)
		{
			case 1:
			{
				if(ds>0)
				{
					ds--;
					write_com(0x80+13);
					write_data('0'+ds%10);
					write_com(0x80+15);//位置
				}
				Feng=1;
				break;
			}
			case 2:
			{
				if(sx>xx+1)
				{
					sx--;
					write_com(0x80+0x40+4);
					write_data('0'+sx/10%10);
					write_data('0'+sx%10);
					write_com(0x80+0x40+5);//位置
				}
				Feng=1;
				break;				
			}
			case 3:
			{
				if(xx>0)
				{
					xx--;
					write_com(0x80+0x40+13);
					write_data('0'+xx/10%10);
					write_data('0'+xx%10);
					write_com(0x80+0x40+14);//位置
				}
				Feng=1;
				break;				
			}		
		}
	}
	if(Key4==0)
	{
		while(Key4==0);
		Feng=0;
		Mode=0;
	//	write_com(0x38);//屏幕初始化
	//	write_com(0x0c);//打开显示 无光标 无光标闪烁
		Init1602();
		if(ds>0)
		{
			flag=0;
			jdq=1;
			TR1=1;
		}
		Feng=1;
	}
		if(IrOK==1) 
		{
			if(Im[2]==0x0d)	//遥控设置键
			{
				Feng=0;
				Mode++;
				Display_wd();
				if(Mode==4)
				{
					Feng=1;
				}
		   		write_com(0x38);//屏幕初始化
		   		write_com(0x0d);//打开显示 无光标 光标闪烁
		   		write_com(0x06);//当读或写一个字符是指针后一一位
				switch(Mode)
				{
					case 1:
					{
						write_com(0x80+15);//位置
						Feng=1;
						break;
					}
					case 2:
					{
						write_com(0x80+0x40+5);//位置
						Feng=1;
						break;
					}
					case 3:
					{
						write_com(0x80+0x40+14);//位置
						Feng=1;
						break;
					}
				}				 
			}
			//+键
			else if(Im[2]==0x40)
			{
				if(Mode!=0)
				{
					Feng=0;
					switch(Mode)
					{
						case 1:
						{
							if(ds<999)
							{
								ds++;
								write_com(0x80+13);
								write_data('0'+ds/10%10);
								write_data('0'+ds%10);
								write_com(0x80+15);//位置
							}
							Feng=1;
							break;
						}
						case 2:
						{
							if(sx<99-1)
							{
								sx++;
								write_com(0x80+0x40+4);
								write_data('0'+sx/10%10);
								write_data('0'+sx%10);
								write_com(0x80+0x40+5);//位置
							}
							Feng=1;
							break;				
						}
						case 3:
						{
							if(xx<sx-1)
							{
								xx++;
								write_com(0x80+0x40+13);
								write_data('0'+xx/10%10);
								write_data('0'+xx%10);
								write_com(0x80+0x40+14);//位置
							}
							Feng=1;
							break;				
						}		
					}
				}
			}
			//-键
			else if(Im[2]==0x19)
			{
				if(Mode!=0)
				{
					Feng=0;
					switch(Mode)
					{
						case 1:
						{
							if(ds>0)
							{
								ds--;
								write_com(0x80+13);
								write_data('0'+ds/100);
								write_com(0x80+15);//位置
							}
							Feng=1;
							break;
						}
						case 2:
						{
							if(sx>xx+1)
							{
								sx--;
								write_com(0x80+0x40+4);
								write_data('0'+sx/10%10);
								write_data('0'+sx%10);
								write_com(0x80+0x40+5);//位置
							}
							Feng=1;
							break;				
						}
						case 3:
						{
							if(xx>0)
							{
								xx--;
								write_com(0x80+0x40+13);
								write_data('0'+xx/10%10);
								write_com(0x80+0x40+14);//位置
							}
							Feng=1;
							break;				
						}		
					}
				}
			}
			//确定键
			else if(Im[2]==0x15)
			{
				Feng=0;
				Mode=0;
				Init1602();
				if(ds>0)
				{
					flag=1;
					jdq=1;
					TR1=1;
				}
				Feng=1;
			} 
			IrOK=0;	  
		}
}
void main()
{
	Init1602();
	EA=1;//打开中断总开关
	IT1=1;//下降沿有效
	EX1=1;//外部中断1开
	ET1=1;//打开允许开关
	TMOD=0x11;//设置工作方式
	TH1=0x4b;
	TL1=0xff;//赋初值
	TH0=0;//T0赋初值
	TL0=0;
	TR0=0;//t0开始计时
	check_wendu();
	delay(1000);
	bjd=99;
	bjx=0;
	while(1)
	{	
		check_wendu();
		if(Mode==0)
		{	
			Display_1602(c,ds,sx,xx);
			if(flag==0)
			{
				if((w<bjd)&&(w>bjx))
				{
					if(w>=sx)
					{
						jdq=1;
				//		Feng=0;
					}
					else if(w<xx)
					{
				//		Feng=0;
					}
					else
					{
				//		Feng=1;
					}
					bjd=w+5;
					bjx=w-5;
				}
			}
		}
		Key();
	}
}

void time0() interrupt 3//定时器函数
{
	uint s;
	TH1=0x4b;
	TL1=0xff;//重新赋初值
	s++; 
	if(s==1200)	//s=20为1s钟  1200为1分钟
	{
		s=0;
		ds--;
		if(ds==0)
		{
			flag=1;
			jdq=1;
			bjd=w+10;
			bjx=w-10;
			TR1=0;
			delay(1000);
			Feng=1;
		}
	}
}
//外部中断解码程序_外部中断0
void intersvr1(void) interrupt 2 using 1
{
 TR0=1;
 Tc=TH0*256+TL0;//提取中断时间间隔时长
 TH0=0; 
 TL0=0;         //定时中断重新置零

 if((Tc>Imin)&&(Tc<Imax))
 { 
	m=0;
	return;
 }       //找到启始码
 if(f==1)
 {
	if(Tc>Inum1&&Tc<Inum3) 
    {
   	Im[m/8]=Im[m/8]>>1|0x80; m++; 
    }
    if(Tc>Inum2&&Tc<Inum1) 
    {
      Im[m/8]=Im[m/8]>>1; m++; //取码
  	 }
  	 if(m==32) 
    {
      m=0;  
      f=0;
      if(Im[2]==~Im[3]) 
      {
           IrOK=1;
      else IrOK=0;   //取码完成后判断读码是否正确
    }
               //准备读下一码
 }
}

智能足浴器原理图:

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值