找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 11526|回复: 5
打印 上一主题 下一主题
收起左侧

太阳能热水器控制器设计文档(Word格式 可编辑)

  [复制链接]
跳转到指定楼层
楼主
太阳能热水器控制器设计
The design of controller for solar water heater

主要内容:

本文论述了基于C51单片机的太阳能热水器控制器的实现C51单片机设计一种太阳能热水器控制器,实现水温、水位及时间的实时显示以及水温、水位的自动控制等功能,另外还需要实现时间和水温设定的功能

[摘要] 该太阳能热水器控制器是基于C51单片机设计和实施的,它以AT89C51单片机作为检测和控制中心,由主控芯片模块、DS18B20 温度检测及显示模块、水位检测及显示模块、时钟模块、报警模块和电磁阀控制模块、辅助加热模块等模块组成。它通过DS18B20温度检测及显示模块实时检测和显示水温,通过水位检测及显示模块实时检测和显示水位,通过时钟模块实时显示时钟并在设定的时间给主控芯片特定的信号,通过电磁阀控制模块实现热水器的自动及手动上水,通过辅助加热模块实现太阳能热水器自动及手动加热,当水位过低且水温过高时通过报警模块报警,而主控芯片则负责协调其他各模块的工作。


1  绪论
1.1  太阳能热水器应用的意义
1.2  我国太阳能发展现状
2  系统设计及仿真软件
2.1  系统的总体结构设计
2.2  设计功能要求
2.3  设计思路
2.4  仿真软件(proteus)简介
3  AT89C51简介
3.1  主要特性
3.2  中断向量
3.3  管脚说明
3.4  内部结构
4  控制器各模块电路设计
4.1  主控芯片模块
4.1.1  时钟电路
4.1.2  复位电路
4.1.3  单片机管脚分配
4.2  DS18B20 温度检测及显示模块
4.2.1  DS18B20芯片简介
4.2.2  74LS245简介
4.2.3  LED数码管显示
4.3  水位测量及显示模块
4.4  报警模块
4.5  辅助加热模块
4.5.1  继电器工作原理
4.5.2  辅助加热模块工作原理
4.6  电磁阀控制模块
4.6.1  电磁阀工作原理
4.6.2  电磁阀控制模块工作原理
4.7  时钟模块
4.7.1  电子表发声原理及控制器定时工作原理
5  控制器软件程序设计
5.1  软件设计分析
5.2  主程序模块
5.3  子程序模块
5.3.1  DS18B20温度检测子程序设计
5.3.2  DS18B20温度转化及显示子程序
5.3.3  加热子程序设计
5.3.4  上水子程序设计
5.4  中断子程序设计
5.4.1  外部中断0(设定温度+)子程序设计
5.4.2  外部中断1(设定温度-)子程序设计
6  调试与总结
6.1  调试方法
6.2  遇到的问题及解决办法
6.3  总结
致谢
参考文献
附录


1  绪论
1.1  太阳能热水器应用的意义

迈入21世纪以来,随着经济的急速发展,对自然资源的需求缺口越来越大,人口基数过大使得将在很长一段时间保持人口数量的增长,而经济的高发展速度也将持续对资源的供应提出考验。显而易见的,资源储量并不是无限的,若要保证经济的可持续发展,仅仅靠节约能源或是限制开采数量,并不是一个长久的解决办法,只有开发新的能源,才能从根本上解决发展与资源之间的矛盾。所以在今后,新能源必定将会有很大的发展空间,太阳能、风能、潮汐能,这些清洁能源是未来大规模利用的新趋势。
[1]
在各类能源中,太阳能以其清洁、无害、长久和普遍等特点,有极高的发展潜力,可以说是取之不尽用之不竭。虽然离太阳能的广泛利用还有很长的路要走,但是现在已经在不少地方开始使用,如常见的太阳能发电系统,太阳能热水系统,太阳能路灯、交通灯等等。我国目前太阳能产业规模已至世界第一,随着技术的日益成熟,太阳能相关的成熟产品造价也将随之降低,将更加广泛地在人们生产生活中普及,这同时也是解决越来越严重环境污染的一个极佳的解决方案。
在我们的生活中,最为我们所熟知的太阳能利用系统便是太阳能热水器,太阳能热水器同传统的热水器相比有着许多显著的特点。不仅节能环保,而且使用也非常方便。以其低廉的价格深受各层次消费者的青睐。
随着太阳能热水器的大面积使用,太阳能的优势特点已广泛为人们所熟知,这也对以后的相关产品的生产推广起到了很好的宣传效应。大力开发和利用丰富的太阳能资源,对于我国的经济、社会可持续发展具有重大深远意义。[2]
1.2  我国太阳能发展现状我国太阳能热水产业的发展特点可以用“起步晚,发展快”来形容,虽然国内与于上世纪80年代才开始研究推广,但是历经多年的飞速发展,我国的太阳能产业已经占据了世界首位,其中热水器的产量占世界百分之五十以上,同时,中国国产太阳能产品在世界同类产品中也占据着很大的市场份额,并且市场占有率还在不断增长。[3]
尽管有着如此迅猛的发展势头,但是需要指出的是,目前国内的能与太阳能热水器相配置的控制器的功能却并不完善,在市面上很多同类的太阳能热水器产品,控制系统简单,功能不全,大多数只具有设定水温,显示水温这两个功能,较为智能化的产品还尚未推广应用,有些功能还处于研发阶段。因此设计出一款具有温度控制功能和水位控制功能的产品,将很具有实际意义。这样的控制器,将能够解决天气原因导致的光线不足问题导致热水器水温过低的问题,并且因为有了水位控制功能,就可以解决当水位达到一定高度时不能自动开始或停止供水等等问题。

2  系统设计及仿真软件2.1  系统的总体结构设计系统总体结构设计如图2.1,该系统包括保温箱、排气管、集热管、溢流管、上下水管、调节阀等。

2.1  系统总体结构设计
2.2  设计功能要求该太阳能热水器的控制器不但需要具有水位、水温及时间的实时显示功能,而且需要具有水位、水温的自动控制功能,必要时,还需要能够实现对时间和水温进行设定等功能。当蓄水箱水位低于40%时能够实现自动上水,当设定时间到且水位低于蓄水箱水位90%时能够实现自动上水,当上水到达规定水位时能够实现自动停止上水,当水位界于高低水位之间时,用户可以通过按键操作手动上水、停水;当设定时间到且水温低于规定值时,能够实现自动加热。必要时还可以对太阳能热水器进行手动加热和上水,禁止高温空晒后进水以及淋浴时禁止上水等功能。
2.3  设计思路该太阳能热水器控制器是基于C51单片机设计和实施的,它以AT89C51单片机作为检测和控制中心,由主控芯片模块、DS18B20 温度检测及显示模块、水位检测及显示模块、时钟模块、报警模块和电磁阀控制模块、辅助加热模块等模块组成。它通过DS18B20温度检测及显示模块实时检测和显示水温,通过水位检测及显示模块实时检测和显示水位,通过时钟模块实时显示时钟并在设定的时间给主控芯片特定的信号,通过电磁阀控制模块实现热水器的自动及手动上水,通过辅助加热模块实现太阳能热水器自动及手动加热,当水位过低且水温过高时通过报警模块报警,而主控芯片则负责协调其他各模块的工作。
2.4  仿真软件(proteus)简介Proteus可以仿真单片机,兼具EDA软件的仿真功能,还能一部分外围器件,是当前使用最广,用户评价最好的仿真工具。可以从原理图设计,程序编写调试,再到与外围电路同步仿真,提供与PCB板设计的简单切换,可以由最初的模拟概型一直到产品的模拟仿真。该软件也是第一款融合电路原理图设计,PCB板设计,产品生产前的仿真三者结合的开发平台,其处理器模型支持8051、HC11、PIC10/12/16/18/24/30/DsPIC33、AVR、ARM、8086和MSP430,Cortex,DSP等系列处理器,截止到现在,依然在不断增加其它系列处理器模型。程序编译支持Keil和MPLAB软件编译器。[4]
Proteus软件具有其它EDA工具软件的功能:
1.原理布图
2PCB自动或人工布线
3SPICE电路仿真革命性的特点
Proteus的工作过程:在开始菜单中选择proteus文件夹,单击文件夹中的ISIS图标进入proteus仿真软件的主界面。在工作之前,先要设置捕捉对齐、颜色、图形界面大小等项目。工作时,先要单击工具栏中的P按钮进入元件选择对话框(pick devices),在对话框keyword中输入所需元件的关键字(比如当需要电阻时输入“res”),在results一栏中双击选出所需要的元器件(注意当选中元器件时在pick devices对话框中右侧两栏中会出现该元器件在仿真电路图和PCB板上的预览图,根据此预览图进行选择),选中的元件会自动出现在工作界面P按钮下面。然后需要进行仿真电路图的绘制(具体做法为:在P按钮下面单击所需要的元器件即选中此元器件,根据实验原理图把选中的元器件放在工作界面的适当位置,双击工作界面中的元器件,在出现的对话框中修改元器件的参数,重复以上步骤直到所有的元器件都摆放到工作界面上,然后单击各元器件的引脚进行连线。至此仿真电路图制作完成。然后进行程序的编写,在程序编写时需要使用专门的程序编写器(比如keil软件等)来编写并编译连接运行,生成hex文件。接下来需要把程序存入相应的芯片中,具体做法是:双击目标芯片,在出现的对话框中“program file”中选择相应的程序,然后点击ok 按钮即可。最后需要运行,在此步骤秩序点击proteus工作界面左下方的play按钮即可。

3  AT89C51简介3.1  主要特性•与MCS-51 兼容
•具有4K 字节的可重复编程的flash,可写入/抹掉数据1000次以上,写入的数据能保存10年以上
•操作频率:0Hz24MHz
128×8位内部RAM
32条可规划的I/O线
5个中断向量地址
•可编程串行通道
•需要振荡电路和时钟电路[5]
3.2  中断向量中断向量见图3.1[6]



3.1  中断向量表
3.3  管脚说明AT89C51引脚见图3.2[7]
VCC:供电电压。
GND:接地。
P0管脚、P1管脚、P2管脚、P3管脚都是8位双向I/O口,其中P3管脚还有第二功能。


3.2  AT89C51 芯片引脚图
              P3管脚第二功能见图3.3
RST:复位输入端。
ALE/ :地址锁存信号线。

3.3  P3口第二功能说明
:外部程序存储器读选通端。
/VPP:访问内部程序存储器控制端
XTAL1XTAL2:震荡电路输入端。
3.4  内部结构51单片机内部机构如图3.4[8]

图3.4  51单片机内部结构框图

4  控制器各模块电路设计4.1  主控芯片模块单片机只有40个管脚,其中I/O管脚只有32个,必须合理地分配单片机管脚,否则很容易造成单片机管脚的不够用。另外,单片机运行需要时钟电路、复位电路、电源、地线等,这些电路也需要在单片机主控芯片里面设计。主控芯片模块proteus仿真图如图4.1[9]

4.1  主控芯片模块proteus仿真图
4.1.1  时钟电路单片机的运行需要时钟电路的支持,单片机时钟电路是配合外部晶体实现振荡的电路,它由一个晶振和两个电容组成,其组成图如图4.2,它的两端分别接在单片机的XTAL1和XTAL2管脚。它可以为单片机提供运行时钟,如果运行时钟为0 的话,单片机就不工作,当然超出单片机的工作频率的时钟也会导致单片机不能正常工作,C51单片机的支持的时钟频率0~24MHz

4.2  单片机时钟电路
4.1.2  复位电路在单片机在使用过程中有时(比如上电瞬间以及运行中出现错误的时候)需要使单片机从开始状态重新运行,这时就需要单片机的复位电路了。它可以使单片机内部各寄存器的值变为初始状态,复位电路如图4.3。它可以在单片机上电瞬间和复位开关按下的瞬间给单片机RESET管脚加上一个程指数函数的电平信号,当此电平信号能够在单片机的RESET管脚保持两个机器周期以上的高电平时,单片机就能完成复位操作。[10]


图4.3  单片机复位电路

4.1.3  单片机管脚分配单片机管脚分配如图4.4


图4.4  单片机管脚分配
4.2  DS18B20 温度检测及显示模块蓄水箱水温检测电路使用单总线DS18B20芯片,它可以将温度信号转化成脉冲信号进而转化成水温高低的信号。DS18B20DQ端与单片机的P3.7口相连,它可以将水温大小直接以数值的方式存放在其内部的RAM中,单片机可以通过DS18B20DQ引脚直接读取其内部RAM中存放的温度值。在水温的显示上,本设计采用两位LED数码管来实现,LED数码管的段选信号由单片机的P0口来发出,其位选信号由单片机的P2.6P2.7管脚发出。水温检测及显示模块的proteus电路仿真如图4.5


图4.5  温度检测及显示模块proteus仿真图

4.2.1  DS18B20芯片简介DS18B20是美国DALLAS公司推出的一种温度传感器,它能比较准确的测量-55~125℃之间的温度。相对于以前的热敏电阻等温度传感器,DS18B20更加智能,它能够直接测出被测环境的温度并以数值方式存在其内部的RAM中,当有需要时,它可以通过单总线实现单片机等对DS18B20内部RAM中数据的读取。
DS18B20有如下性能特点:
单总线结构设计,仅需要一个引脚即可完成数据在DS18B20和单片机之间的通信。
每个DS18B20都有独一无二的序列号,可以在一条线上并联多个DS18B20芯片
测量温度范围-55~125
分辨率可调
DS18B20 内部结构[11]
DS18B20 内部结构如图4.6

4.6  DS18B20内部结构框图
  DS18B20引脚
DS18B20引脚功能描述见图4.7
序号
名称
引脚功能描述
1
GND
地信号
2
DQ  
数字信号输入输出引脚
3
VDD
供电电源输入端
4.7  DS18B20各引脚功能
DS18B20转换成的温度数据格式[12]
DS18B20接到温度转换命令时它就可以将测得的温度信号转换成温度值并以16位带符号扩展的二进制补码形式存储在其高速缓存RAM中,其温度值格式如图4.8
图4.8  DS18B20温度数据格式
单片机可以通过DS18B20DQ引脚直接取RAM中温度的值,读取时,先读取低位数据,然后读取高位数据。在DS18B20温度数据格式中,当S=0时表示此时的温度值为正值,当S=1时表示此时温度为负值。
DS18B20  ROM命令[13]
DS18B20的一系列操作基本都是通过ROM命令来实现的,DS18B20ROM命令见图4.9

图4.9  DS18B20的ROM命令
4.2.2  74LS245简介74LS2458位双向3态缓冲电路,主要用途为数据的双向缓冲,以增强芯片的驱动能力。[14]74LS245真值表如图4.10所示。

输入
输出

DIR
L
L
B端到A端进行数据传输
L
H
B端到A端进行数据传输
H
×
高阻态

4.10  74LS245真值表

4.2.3  LED数码管显示LED数码管是由八个发光二极管排列在一起并相互连接组成的,根据其连接方法的不同,LED数码管可以分为共阴极和共阳极两种连接方法。两种接法电路图如图4.11

图4.11  LED数码管及接线方法
当把数码管中各发光二极管的阴极连接在一块并与地相连,通过从各发光二极管阳极是否接电源来控制发光二极管的亮灭时成为共阴极接法。同理,当把数码管中各发光二极管阳极接在一块并与电源相连,通过在各发光二极管阴极是否接地来控制各发光二极管的亮灭时称为共阳极接法。不同的接法所需要点亮电平是不一样的,所以在使用数码管显示时,一定要注意区分这两种接法。当然为了显示数字或字符,需要对数字或字符进行编码,本设计采用共阴极LED数码管显示。
LED数码管显示方式有两种,即静态显示方式和动态显示方式。静态显示就是每个数码管都需要连接一个8位的数据线,通过该8位数据线发送数据来保持显示的字符,当向数码管送入一次8位数据时数码管就会一直显示该字符,如果需要改变需要显示的字符则需要重新给数码管输入另一个8位数据。动态显示就是通过一定的操作使各个数码管依次点亮,利用发光二极管的余晖效应和人眼的视觉暂留现象使人的感觉就像是同时点亮各个数码管一样。动态显示的亮度比静态显示稍微差一下,程序上稍微麻烦一些,占用的CPU时间长点,但当数码管位数比较多时需要的管脚位数明显减少,硬件电路会大大简化。由于单片机输出管脚有限,为了节省单片机管脚,本设计采用动态显示方式。
4.3  水位测量及显示模块蓄水箱水位是智能控制的一个重要参数,是实现智能控制的重要依据,只有准确检测出水箱水位才能更好地实现水位地显示以及蓄水箱的上水、停水等操作。要实现水位地精确检测最好采用连续液位传感器,但考虑到系统成本及使用范围,本系统在进行水位检测时仍然采用分段式液位传感器(即在蓄水箱不同的位置放入水位探针),在水位显示上采用由5个发光二极管组成的分段式液位显示器。水位检测及显示电路图如图4.12

图4.12  水位检测及显示电路图
检测原理:把五个金属水位探针分别固定在水箱的五个位置上,金属探针通过一个1M的电阻(即上拉电阻)和+5V电源相连,水箱里的水通过导线和地相连。当金属探针在水面以下时,+5V电源、上拉电阻、水箱里的水、地等组成一个回路,由于水的电阻远比1M小,所以此时探针处电平为低电平。这个低电平通过一个反相器(非门)后变为高电平,这个高电平通过发光二极管、500Ω的电阻放电,使得发光二极管点亮,显示此时该液位有水。当金属探针在水面以上时,金属探针处电平为高电平,该高电平经过反相器时变为低电平,低电平不能使发光二极管发光,从而显示该液位没有水。至此,水位的显示完成。水位测量及显示模块proteus仿真图如图4.13

4.13  水位测量及显示模块proteus仿真图

proteus仿真图使用按键开关代替水和+5V电源、1M电阻及地构成回路,当按键按下时代表此位置处有水,当按键没有按下时代表此水位处没有水。需要注意的是,上拉电阻不宜选的太小,因为水是有电阻的,上拉电阻选的太小会导致当探针在水面以下时探针输出低电平特性不明显,此时很容易导致液位显示上出现错误。位置最高到位置最低处的探针所测出的电平经反相器后会通过导线依次送到单片机的P2.0P2.4管脚,经单片机接收、处理,实现水位控制的操作。
4.4  报警模块太阳能热水器通常对蓄水箱内的水位有一定的要求,当水箱水位过低时,很容易给人们的正常生活带来不便,所以,当水位过低时能及时让人们知道就显得比较重要,报警模块正是基于此种原因设计的。报警模块的proteus仿真图如图4.14

图4.14  报警模块的proteus仿真图

检测及报警原理:当水位过低时,单片机相应管脚被清零,使得单片机通过P1.5口输出一系列脉冲波。脉冲波经由Q1R1组成的放大电路后作用于蜂鸣器BUZI的线圈上,线圈产生变化的磁场带动蜂鸣器纸盆震动从而发出声音。
4.5  辅助加热模块当光照不足时,太阳能热水器的水温很难达到指定的要求,为了不影响人们的正常使用,辅助加热设备就显得尤为重要了。辅助加热模块的proteus电路仿真图如图4.15

图4.15  辅助加热模块的proteus电路仿真图

4.5.1  继电器工作原理继电器工作原理图如图4.16所示。[15]

图4.16   继电器工作原理图
当继电器的控制回路没有电流流过时,继电器的衔铁在弹簧的拉力作用下右端上翘,触点3与触点5断开,与触点4结合。当有电流流过继电器的控制回路(即由导线和线圈组成的电磁铁)时,电流就会在在电磁铁上产生磁场,此时,衔铁会被电磁铁吸引而下降,使得触点3与触点4分离,与触点5连接。如果在端点3和端点5接上其他电路组成被控回路就会出现当有电流流过控制回路时被控回路导通,当没有电流流过控制回路时被控回路断开。
4.5.2  辅助加热模块工作原理当加热按钮没有按下时,此辅助加热模块为自动控制模式。在自动控制模式下,当设定的时间到时,单片机会自动对蓄水箱的水温进行判断。当水温高于设定值时,P1.1口输出为高电平,三极管Q1集电极和发射极断开,此时,输入回路中没有电流为零,继电器被控回路断开,加热电阻不工作。当P1.1口输出为低电平时,三极管Q1集电极和发射极导通,+5V电源经电阻R1,继电器控制回路、三极管Q1和地相连,输入回路导通,此时,继电器被控回路闭合,220V交流电源经继电器被控回路给加热电阻加热,从而使水温升高。当临时(不是设定时间)需要热水时可以通过加热按钮进行加热,此时,只需按下加热按钮即可对蓄水箱的水进行加热。
4.6  电磁阀控制模块电磁阀是把电信号转化成水龙头开关信号的装置,是实现水位智能控制不可缺少的一部分。电磁阀从原理上分为直动式分步直动式先导式三类电磁阀,本设计采用直动式电磁阀。电磁阀控制模块proteus仿真如图4.17

图4.17  电磁阀控制模块proteus仿真电路图
继电器工作原理已在辅助加热模块介绍,此处不再叙述
4.6.1  电磁阀工作原理电磁阀工作原理如图4.18

4.18  电磁阀工作原理图
当电磁阀不通电时,活动铁心在弹簧的弹力作用下上升,入口和出口被阀门隔开,水被阻断;当通电时,活动铁心在线圈产生的磁场作用下下落,此时入口和出口导通,水从入口经电磁阀流向出口,完成上水。
4.6.2  电磁阀控制模块工作原理在本设计中,此电磁阀控制模块分为自动控制和手动控制两种工作情况:当上水按键开关断开且淋浴开关闭合时电磁阀控制模块为自动控制模式,此时当单片机P1.4口输出为高电平时,继电器的输入端输入电流为零,继电器输出端开路,电磁阀所在电路开路,电磁阀关闭;当单片机P1.4口输出为低电平时,继电器输入端通过电阻、三极管和电源、地相连,此时,输入回路有输入电流,使得继电器输出回路闭合,电磁阀所在电路导通,电磁阀打开。当上水按键开关直接闭合且淋浴开关闭合时,电磁阀通过按键开关直接和220V电源相连,此时电磁阀所在电路导通,电磁阀打开。另外,为了避免淋浴时因水位偏低而导致热水器直接上水,本模块加了一个淋浴状态开关,当淋浴状态打开(淋浴开关断开)时,直接断开电磁阀开关,此时无论水位多么低都不会上水,当淋浴状态关闭(淋浴开关闭合)时,可以选择自动控制和手动控制两种模式。
4.7  时钟模块时间是实现热水器控制器定时上水、定时加热的重要参考,所以设置时钟模块是非常有必要的。时钟模块可以通过单片机设置一个数字时钟来实现,也可以时钟芯片(比如DS1302)实现,还可以通过外接具有定时功能的电子表来实现。考虑到单片机管脚的数量限制和设计的难易程度,本设计采用外接电子表的方式来实现定时上水、定时加热。
4.7.1  电子表发声原理及控制器定时工作原理电子表里面装有压电陶瓷片,压电陶瓷片是一种电子发音元件,在两个电极中间放入压电陶瓷介质材料,当设定时间到时,会在压电陶瓷片的两个电极上加上特定的交流信号,压电陶瓷片就会根据所加信号的大小和频率震动,从而发出声音。本设计中会把这个电极信号接在单片机的P1.0管脚,当该管脚的电平是低电平时可以给单片机一个触发信号,经单片机处理,使得加热设备开始工作;同理,当给单片机的P1.3管脚加上一个低电平时同样能给单片机一个触发信号,经单片机处理后,使得上水设备开始工作。

5  控制器软件程序设计5.1  软件设计分析软件是系统的指挥中心,由软件来配合硬件来完成电子设备特定的功能是目前电子设备的普遍规律。本系统同样要求软件和硬件两部分协调工作才能所完:由硬件电路完成数据的采集、显示以及对电磁阀和蜂鸣器的控制,由软件来实现数据的判断、处理等。由此可见,软件和硬件一样,都是该系统正常工作所必须的一部分。
软件相对于硬件电路来说具有更高的性价比,并且更容易实现,为了充分发挥C51单片机的优良的性能价格比,我们在进行系统设计时,更倾向于使硬件电路“软件化”,即通过编程的方法使硬件电路简化。考虑到C语言诸多优良特性,本设计采用C语言编写,为了增加系统的实时性,本设计对于偶然事件的处理采用中断的方式来进行处理。
在电路设计时我们采用模块化设计,同理,在软件设计时,我们也采用模块化设计。首先需要编写出大概的主程序,然后需要找出所设计的子程序并对子程序进行逐个分析和设计,编写出子程序后应给予每个子程序语法检验以确定子程序是不是有语法错误,接下来需要把子程序和主程序以及一些的声明函数等进行合理的检查和修改直到没有语法错误为止,再然后对偶然事件需要进行中断处理函数的编写。最后需要对整个程序进行编译检查以确定是否有语法错误,如果有语法错误需要对程序进行改正,如果没有可以把程序烤到单片机里来检验程序的正确与否。[16]
5.2  主程序模块主程序需要完成对单片机端口的初始化,开外部中断0,开外部中断1等,此外,还包括温度数据读取、温度数据显示、水位数据读取以及对热水器加热、上水等操作。其流程图如图5.1所示。

图5.1  主程序模块流程图
5.3  子程序模块子程序是指能够实现某一特定功能并能被其他程序调用的一段程序。采用子程序结构可以使程序得到简化,便于进行调试,并可实现程序的模块化,本设计将采用子程序模块的设计来实现部分功能。
5.3.1  DS18B20温度检测子程序设计DS18 B20温度检测模块的子程序流程图如图5.2,它包括对 DS18 B20的初始化、发 ROM命令、发温度转化命令、读存储器等操作。



图5.2  DS18B20温度检测流程图

5.3.2  DS18B20温度转化及显示子程序DS18 B20温度转化及显示子程序流程图如图5.3,它包括读取温度值、对温度值得判断、区分温度的十位和个位数据、显示十位数据、显示个位数据等操作。

图5.3  DS18B20温度转化及显示流程图
5.3.3  加热子程序设计当设定时间到时,外部时钟会在单片机的P1.0管脚给单片机一个触发信号,使得单片机执行加热子程序。加热子程序流程图如图5.4。


图5.4  加热子程序流程图
5.3.4  上水子程序设计同加热子程序一样,当设定时间到时,外部时钟会在单片机的P1.3管脚给单片机一个触发信号,使得单片机执行上水子程序。上水子程序流程图如图5.5。

图5.5  上水子程序流程图

5.4  中断子程序设计为了保证系统的实时性,本设计有一些功能是通过中断来实现的,这就要求在软件程序设计里面需要有专门的中断服务子程序的设计。本设计采用了两个中断服务,包括外部中断0和外部中断1。其中外部中断0用作增加设定的温度值,外部中断1用作减小设定的温度值。
5.4.1  外部中断0(设定温度+)子程序设计外部中断0负责使设定的温度值增加,每当执行一次外部中断0,所设定的温度值就会增加1。外部中断0(设定温度+)子程序流程图如图5.6。

图5.6  外部中断0(设定温度+)子程序流程图
5.4.2  外部中断1(设定温度-)子程序设计同外部中断0相对应,外部中断1用作使设定的温度值减小。每当执行一次外部中断1,所设定的温度值就会自动减1,当设定温度值减小到30℃一下时设定温度值自动变为99℃。外部中断1(设定温度-)子程序流程图如图5.7。

图5.7  外部中断1(设定温度-)子程序流程图
6  调试与总结
6.1  调试方法为了节省人力、物力,在正式调试之前往往会对电路进行仿真操作。所谓的仿真操作就是使用专门用于仿真的仿真软件对系统的硬件电路图及程序进行仿真。如果仿真结果满足我们的要求,那么我们就可以进行硬件电路的制作了,如果仿真结果不能满足我们的要求,那么我们就需要重新对程序及相关的硬件进行设计。
本设计使用proteus对系统的各部分和整个系统进行仿真。具体做法为:
  • 根据系统要求用proteus 画出整体系统的仿真电路图(可以先一个模块一个模块的画,然后在组装在一块)。
  • 2、根据系统要求及画出的仿真电路图编写程序(本设计使用C语言编写),并用keil软件进行编译,生成HEX文件。
  • 把生成的HEX文件下载到对应的单片机中(具体做法为:在proteus仿真电路图中双击相应的单片机会出现“Edit Component”对话框,在此对话框中program File一栏中选择所需的HEX文件,然后点击该对话框右上角的ok按钮即可),然后点击仿真电路图界面左下角的play按钮即可进行电路仿真。
在完成系统的仿真操作后就需要对系统进行调试了。调试可以分为硬件调试和系统调试两部分。硬件调试主要是对硬件部分进行调试,看看所设计的硬件能否完成我们期望的功能,而系统调试主要是看看系统能否按照预期进行工作。
在制作完成PCB板之后就可以进行硬件部分的调试了。              在制作完PCB板之后就可以进行硬件电路调试了。在进行硬件电路调试之前需要先对各元器件进行检查,对于有问题的元器件需要及时替换。在检查完元器件之后就可以往PCB板上查元器件了。为了降低硬件调试的难度,便于更好的发现问题,在硬件调试过程中采用分块调试的方法。
              在完成硬件电路调试之后就需要对系统进行调试了。所谓系统调试就是把提前编译好的程序下载单片机中,对系统的整体性能进行观察、调试。
6.2  遇到的问题及解决办法
  • 在进行proteus各模块仿真电路图设计时有部分元器件(比如电磁阀、加热装置等)在元件库中找不到。解决方法:用其他有相似特点的元件代替,并将此元件的参数修改一下。
  • 在进行proteus总体仿真电路设计时,有很多现象(比如:电磁阀的通断、水位的高低等)不容易观察或不容易操作。解决方法:用发光二极管、按键开关代替这些不容易观察或不容易操作的现象。
  • 在程序设计时对DS18B20的程序设计总是弄不对。解决方法:参考其他人对这部分程序的编写,然后按照自己的要求和DS18B20的原理进行修改。
  • 在程序设计过程中 ,对DS18B20测出的温度进行转化方面出现失误:没有注意DS18B20温度数据是包含小数部分的温度而导致在温度转化时出现错误。解决方法:在对DS18B20结构及原理仔细分析的基础上对设计的程序进行修改,首先去除温度的小数部分,然后吧温度的个位数部分和十位数部分分别放在一个数组的两个元素中。
  • 在系统调试中发现温度显示时总是个位数在前,十位数在后,给人的感觉很别扭。解决方法有两个:一、在温度数据的处理子程序中把个位数据和十位数据处理的语句调换一下。二、在硬件电路中把两个LED数码管位选信号输入端调换一下。本设计采用第一种方法,即在程序处理方面做改变。
6.3  总结太阳能热水器控制器是对太阳能热水器进行控制的一种装置,它需要能够实现对热水器水温、水位的控制。在本设计的过程中,我先是对太阳能热水器需要实现的功能进行分析,然后按照需要实现的功能按照模块设计的思想进行设计,接下来把各模块组合起来形成一个系统,用proteus对该系统进行仿真,最后进行实际电路连接。经过以上各个步骤的实际操作,我们可以看出,本设计是可行的。
本设计中我用的了单片机、C语言、模电、数电、电路分析等多门课程,可以说正是在这些知识的支撑下我才能顺利完成本设计。在进行本设计的过程中,我较深刻理解了能够综合运用知识的重要性,当然,本设计对我综合运用能力也有一定程度的提高。
另外,在进行本设计的过程中,我的交流能力也有一定程度的提高。在本设计中,我遇到过很多问题,正是与老师、学长、同学的交流给我解决这些问题很大的启发,使我能够顺利完成本设计。


附录
本设计程序如下:[17]

  1. /***************************************************/
  2. #include
  3. #include                           
  4. #define  Disdata  P0     
  5. #define  uchar unsigned char
  6. #define  uint  unsigned int
  7. sbit     b20=P3^7;
  8. sbit     p20=P2^0;
  9. sbit     p21=P2^1;                             
  10. sbit     p22=P2^2;
  11. sbit     p23=P2^3;
  12. sbit     p24=P2^4;
  13. sbit     p25=P2^5;                             
  14. sbit     p26=P2^6;
  15. sbit     p27=P2^7;
  16. sbit     beet=P1^5;
  17. sbit     heat=P1^0;
  18. sbit     p11=P1^1;
  19. sbit     qxjr=P1^2;
  20. sbit     add=P1^3;
  21. sbit     p14=P1^4;
  22. sbit     qxss=P1^6;
  23. uchar     a=35;
  24. uint    temp,b,wd,h;
  25. bit lock0=1; //加热标志位
  26. bit lock1=1;               
  27. uchar code dis[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf};     
  28. uchar data temp_data[3]={0x00,0x000,0x00};           
  29. uint key_[2]={5,0};
  30. /*****************11us延时函数*************************/
  31. void delay(uint t)
  32. {
  33.   for (;t>0;t--);
  34. }
  35. /******************1ms延时函数*****************************/
  36. void delay1ms(uint z)
  37. {
  38.               uint x,y;
  39.               for(x=z;x>0;x--)
  40.                             for(y=110;y>0;y--);            
  41. }
  42. /****************发音函数***************************/
  43. void play(uchar t)
  44. {
  45.               uchar i;
  46.               for(i=0;i<1000;i++)
  47.               {
  48.                             beet=~beet;
  49.                             delay1ms(t);
  50.               }
  51.               beet=0;
  52. }
  53. /****************显示扫描函数***************************/
  54. scan()
  55. {
  56.               uint k=0;
  57.               Disdata=~dis[temp_data[k]];
  58.               p26=0;
  59.               p27=1;
  60.               delay1ms(5);
  61.               k++;
  62.               Disdata=~dis[temp_data[k]];
  63.               p26=1;
  64.               p27=0;
  65.               delay1ms(5);
  66.               p26=1;
  67.               p27=1;
  68. }
  69. /*********************预置温度******************************/
  70. void yzwd(uint b)
  71. {
  72.               Disdata=~dis[b%10];
  73.               p26=0;
  74.               p27=1;
  75.               delay1ms(5);
  76.               Disdata=~dis[b/10];
  77.               p26=1;
  78.               p27=0;
  79.               delay1ms(5);
  80.               p26=1;
  81.               p27=1;
  82. }
  83. /****************DS18B20复位函数************************/
  84. ow_reset(void)
  85. {
  86.               char presence=1;
  87.               while(presence)
  88.               {
  89.                             while(presence)
  90.                             {
  91.                                           b20=1;_nop_();_nop_();
  92.                                           b20=0;                                      
  93.                                           delay(50);         
  94.                                           b20=1;                                       
  95.                                           delay(6);         
  96.                                           presence=b20;      
  97.                                }
  98.                  delay(45);         
  99.                  presence=~b20;        
  100.               }
  101.               b20=1;                 
  102. }
  103. /****************DS18B20写命令函数************************/
  104. void write_byte(uchar val)
  105. {
  106.   uchar i;
  107.   for(i=8;i>0;i--)
  108.   {
  109.                  b20=1;_nop_();_nop_();                 
  110.                  b20=0;_nop_();_nop_();_nop_();_nop_();
  111.                  b20=val&0x01;                          
  112.                  delay(6);                           
  113.                  val=val/2;                           
  114.    }
  115.    b20=1;
  116.    delay(1);
  117. }
  118. //
  119. /****************DS18B20读1字节函数************************/
  120. uchar read_byte(void)
  121. {
  122. uchar i;
  123. uchar value=0;
  124. for(i=8;i>0;i--)
  125. {
  126.               b20=1;_nop_();_nop_();
  127.   value>>=1;
  128.   b20=0;_nop_();_nop_();_nop_();_nop_();      
  129.   b20=1;_nop_();_nop_();_nop_();_nop_();        
  130.   if(b20)value|=0x80;
  131.   delay(6);                                   
  132. }
  133. b20=1;
  134. return(value);
  135. }
  136. /****************读出温度函数************************/
  137. uint read_temp()
  138. {
  139.                 ow_reset();                 
  140.                 delay(200);
  141.                 write_byte(0xcc);           
  142.                 write_byte(0x44);           
  143.                 ow_reset();
  144.                 delay(1);
  145.                 write_byte(0xcc);           
  146.                 write_byte(0xbe);
  147.                 temp_data[0]=read_byte();   
  148.                 temp_data[1]=read_byte();  
  149.                 temp=temp_data[1];
  150.                 temp<<=8;                                             
  151.                 temp=temp|temp_data[0];     
  152.                 return temp;               
  153. }
  154. /****************温度数据处理函数************************/
  155. work_temp(uint tem)            
  156. {
  157.               temp_data[2]=tem>>4;
  158.               temp_data[0]=temp_data[2]%10;
  159.               temp_data[1]=temp_data[2]/10;
  160. }
  161. /****************加热子函数************************/
  162. void heating(void)

  163. {
  164.   if(heat==0)
  165.   {lock0=0;}
  166.   if(lock0==0)
  167.   {p11=0;}
  168.   else
  169.   {p11=1;}
  170.   work_temp(read_temp());  
  171.   wd=temp_data[1]*10+temp_data[0];
  172.   if(wd>=a||qxjr==0)
  173.   {lock0=1;p11=1;}
  174. }
  175. /****************上水子函数************************/
  176. void adding(void)
  177. {
  178.   if(add==0)
  179.   {lock1=0;}
  180.   if(lock1==0)
  181.   {p14=0;}
  182.   else
  183.   {p14=1;}
  184.   if(p20==1||qxss==0)
  185.   {lock1=1;p14=1;}
  186. }
  187. /****************主函数************************/
  188. void main()
  189. {
  190.   P0=0xff;               
  191.   p26=1;
  192.   p27=1;
  193.   EX0=1;
  194.   IT0=1;
  195.   EX1=1;
  196.   IT1=1;
  197.   EA=1;
  198.   ow_reset();                           
  199.   write_byte(0xcc);           
  200.   write_byte(0x44);           
  201.   while(1)
  202.   {
  203.               heating();
  204.               adding();
  205.               work_temp(read_temp());   
  206.               scan();
  207.     wd=temp_data[1]*10+temp_data[0];
  208.               if(wd<80)
  209.               {            
  210.                             while(p22==0)
  211.                             {
  212.                                           p14=0;
  213.                                           delay1ms(1);
  214.                                           work_temp(read_temp());   
  215.                                           scan();
  216.                             }            
  217.               }                  
  218.               if(wd>=80)
  219.               {
  220.                             while(p24==1)
  221.                             {
  222.                                           p14=0;
  223.                                           work_temp(read_temp());   
  224.                                           scan();            
  225.                             }
  226.                             while(p24==0)
  227.                             {
  228.                                           play(2);
  229.                                           p14=1;
  230.                                           work_temp(read_temp());   
  231.                                           scan();                           
  232.                             }
  233.               }
  234.   }
  235. }
  236. /********************外部中断0(设定温度+)**************************/
  237. void wdxg(void) interrupt 0


  238. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

下载(word格式 可编辑):
基于单片机的太阳能热水器控制器.doc (1.77 MB, 下载次数: 200)

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏10 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1 发表于 2017-6-2 17:13 | 只看该作者
好资料,51黑有你更精彩!!!
回复

使用道具 举报

板凳
ID:454639 发表于 2020-2-22 09:31 | 只看该作者
很不错的贴,给我参考带来了很好的思路。
回复

使用道具 举报

地板
ID:497598 发表于 2020-3-15 09:45 | 只看该作者
不错的的文档,很受用
回复

使用道具 举报

5#
ID:461442 发表于 2020-5-24 23:00 | 只看该作者
妙阿,参考一下
回复

使用道具 举报

6#
ID:920158 发表于 2021-5-13 18:34 | 只看该作者
很不错的资料  解决了我很多疑惑
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表