单片机控制电热水壶温度的设计
中文摘要
随着微机测量和控制技术的迅速发展与广泛应用,以单片机为核心的温度采集与控制系统的研发与应用在很大程度上提高了生产生活中对温度的控制水平。本设计论述了一种以STC89C52单片机为主控制单元,以DS18B20为温度传感器的温度控制系统。该控制系统可以实时存储相关的温度数据并记录当前的时间。系统设计了相关的硬件电路和相关应用程序。硬件电路主要包括STC89C52单片机最小系统,测温电路、实时时钟电路、LCD液晶显示电路以及通讯模块电路等。系统程序主要包括主程序,读出温度子程序,计算温度子程序、按键处理程序、LCD显示程序以及数据存储程序等。
[关键词] STC89C52单片机;DS18B20;显示电路
目 录
一、引言 .............................................................................. 3
(一)课题研究的背景 ................................................................ 3
(二)课题研究的目的和意义 .......................................................... 3
二、硬件电路的设计 .................................................................... 3
(一)系统设计的框架 ................................................................ 3
(二)单片机最小系统电路 ............................................................ 4
(三)单片机的选型 .................................................................. 5
1.STC89C52单片机简介 .......................................................... 5
2.STC89C52单片机时序 .......................................................... 5
3.STC89C52单片机引脚介绍 ...................................................... 6
(四)温度传感器电路 ................................................................ 8
(五)系统电源电路的设计 ............................................................ 9
(六)LCD显示电路 .................................................................. 10
(七)串口通讯电路 ................................................................. 10
(八)按键接口电路 ................................................................. 11
(九)DS1302时钟电路 ............................................................... 12
(十)存储器接口电路 ............................................................... 12
三、系统软件设计 ..................................................................... 12
(一)计算温度子程序 ............................................................... 13
(二)按键处理子程序 ............................................................... 14
(三)计算温度子程序 ............................................................... 15
(四)显示数据刷新子程序 ........................................................... 16
四、结束语 ........................................................................... 17
参考文献 ............................................................................. 18
致谢 ................................................................................. 19
附件1:系统原理图 .................................................................... 20
附件2:系统相关程序 .................................................................. 21
一、DS18B20底层驱动程序 .............................................................. 21
二、DS1302时钟底层驱动程序 ........................................................... 26
三、数据存储底层驱动程序 ............................................................. 32
一、引言
(一)课题研究的背景
工业控制是计算机的一个重要应用领域,计算机控制系统正是为了适应这一领域的需要而发展起来的一门专业技术,它主要研究如何将计算机技术、通过信息技术和自动控制理论应用于工业生产过程,并设计出所需要的计算机控制系统。随着微机测量和控制技术的迅速发展与广泛应用,以单片机为核心的温度采集与控制系统的研发与应用在很大程度上提高了生产生活中对温度的控制水平。本设计就是基于单片机STC89C52温度控制系统的设计,通过本次课程实践,我们更加的明确了单片机的广泛用途和使用方法,以及其工作的原理。
(二)课题研究的目的和意义
随着社会的发展,温度的测量及控制变得越来越重要。本文采用单片机STC89C52设计了温度实时测量及控制系统。单片机STC89C52 能够根据温度传感器DS18B20 所采集的温度在液晶屏上实时显示,通过控制从而把温度控制在设定的范围之内。所有温度数据均通过液晶显示器LCD显示出来。系统可以根据时钟存储相关的数据。 通过该课程的学习使我们对计算机控制系统有一个全面的了解、掌握常规控制算法的使用方法、掌握简单微型计算机应用系统软硬的设计方法,进一步锻炼同学们在微型计算机应用方面的实际工作能力。
二、硬件电路的设计
(一)系统设计的框架
本课题设计的是一种以STC89C52单片机为主控制单元,以DS18B20为温度传感器的温度控制系统。该控制系统可以实时存储相关的温度数据并记录当前的时间。其主要包括:电源模块、温度采集模块、按键处理模块、实时时钟模块、数据存储模块、LCD显示模块、通讯模块以及单片机最小系统。
图1 系统设计框架
(二)单片机最小系统电路
在课题设计的温度控制系统设计中,控制核心是STC89C52单片机,该单片机为51系列增强型8位单片机,它有32个I/O口,片内含4K FLASH工艺的程序存储器,便于用电的方式瞬间擦除和改写,而且价格便宜,其外部晶振为12MHz,一个指令周期为1μS。使用该单片机完全可以完成设计任务,其最小系统主要包括:复位电路、震荡电路以及存储器选择模式(EA脚的高低电平选择),电路如下图2所示:
图2 单片机最小系统
(三)单片机的选型
本课题设计的温度控制系统主控制芯片选型为STC89C52单片机,其特点如下:
1.STC89C52单片机简介
目前,51系列单片机在工业检测领域中得到了广泛的应用,因此我们可以在许多单片机应用领域中,配接各种类型的语音接口,构成具有合成语音输出能力的综合应用系统,以增强人机对话的功能。STC89C52单片机是深圳宏晶科技有限公司生产的一种单片机,在一小块芯片上集成了一个微型计算机的各个组成部分。每一个单片机包括:一个8位的微型处理器CPU;一个512K的片内数据存储器RAM;4K片内程序存储器;四个8位并行的I/O接口P0-P3,每个接口既可以输入,也可以输出;两个定时器/记数器;五个中断源的中断控制系统;一个全双工UART的串行I/O口;片内振荡器和时钟产生电路,但石英晶体和微调电容需要外接。最高允许振荡频率是12MHZ。以上各个部分通过内部总线相连接。
2.STC89C52单片机时序
STC89C52单片机的一个执器周期由6个状态(s1—s6)组成,每个状态又持续2个震荡周期,分为P1和P2两个节拍。这样,一个机器周期由12个振荡周期组成。若采用12MHz的晶体振荡器,则每个机器周期为1us,每个状态周期为1/6us;在一数情况下,算术和逻辑操作发生在N期间,而内部寄存器到寄存器的传输发生在P2期间。对于单周期指令,当指令操作码读人指令寄存器时,使从S1P2开始执行指令。如果是双字节指令,则在同一机器周期的s4读人第二字节。若为单字节指令,则在51期间仍进行读,但所读入的字节操作码被忽略,且程序计数据也不加1。在加结束时完成指令操作。多数STC89C52指令周期为1—2个机器周期,只有乘法和除法指令需要两个以上机器周期的指令,它们需4个机器周期。 对于双字节单机器指令,通常是在一个机器周期内从程序存储器中读人两个字节,但Movx指令例外,Movx指令是访问外部数据存储器的单字节双机器周期指令,在执行Movx指令期间,外部数据存储器被访问且被选通时跳过两次取指操作。
3.STC89C52单片机引脚介绍
STC89C52单片机的40个引脚中有2个专用于主电源引脚,2个外接晶振的引脚,4个控制或与其它电源复用的引脚,以及32条输入输出I/O引脚。
下面按引脚功能分为4个部分叙述个引脚的功能。
(1)电源引脚Vcc和Vss
Vcc(40脚):接+5V电源正端;
Vss(20脚):接+5V电源正端。
(2)外接晶振引脚XTAL1和XTAL2
XTAL1(19脚):接外部石英晶体的一端。在单片机内部,它是一个反相放大器的输入端,这个放大器构成采用外部时钟时,对于HMOS单片机,该引脚接地;对于CHOMS单片机,该引脚作为外部振荡信号的输入端。
XTAL2(18脚):接外部晶体的另一端。在单片机内部,接至片内振荡器的反相放大器的输出端。当采用外部时钟时,对于HMOS单片机,该引脚作为外部振荡信号的输入端。对于CHMOS芯片,该引脚悬空不接。
(3)控制信号或与其它电源复用引脚
控制信号或与其它电源复用引脚有RST/VPD、ALE/P、PSEN和EA/VPP等4种形式。
(A).RST/VPD(9脚):RST即为RESET,VPD为备用电源,所以该引脚为单片机的上电复位或掉电保护端。当单片机振荡器工作时,该引脚上出现持续两个机器周期的高电平,就可实现复位操作,使单片机复位到初始状态。
当VCC发生故障,降低到低电平规定值或掉电时,该引脚可接上备用电源VPD(+5V)为内部RAM供电,以保证RAM中的数据不丢失。
(B).ALE/ P (30脚):当访问外部存储器时,ALE(允许地址锁存信号)以每机器周期两次的信号输出,用于锁存出现在P0口的低
(C).PSEN(29脚):片外程序存储器读选通输出端,低电平有效。当从外部程序存储器读取指令或常数期间,每个机器周期PESN两次有效,以通过数据总线口读回指令或常数。当访问外部数据存储器期间,PESN信号将不出现。
(D).EA/Vpp(31脚):EA为访问外部程序储器控制信号,低电平有效。当EA端保持高电平时,单片机访问片内程序存储器4KB(MS—52子系列为8KB)。若超出该范围时,自动转去执行外部程序存储器的程序。当EA端保持低电平时,无论片内有无程序存储器,均只访问外部程序存储器。对于片内含有EPROM的单片机,在EPROM编程期间,该引脚用
于接21V的编程电源Vpp。
(4)输入/输出(I/O)引脚P0口、P1口、P2口及P3口
(A).P0口(39脚~22脚):P0.0~P0.7统称为P0口。当不接外部存储器与不扩展I/O接口时,它可作为准双向8位输入/输出接口。当接有外部程序存储器或扩展I/O口时,P0口为地址/数据分时复用口。它分时提供8位双向数据总线。
对于片内含有EPROM的单片机,当EPROM编程时,从P0口输入指令字节,而当检验程序时,则输出指令字节。
(B).P1口(1脚~8脚):P1.0~P1.7统称为P1口,可作为准双向I/O接口使用。对于MCS—52子系列单片机,P1.0和P1.1还有第2功能:P1.0口用作定时器/计数器2的计数脉冲输入端T2;P1.1用作定时器/计数器2的外部控制端T2EX。对于EPROM编程和进行程序校验时,P0口接收输入的低8位地址。
(C).P2口(21脚~28脚):P2.0~P2.7统称为P2口,一般可作为准双向I/O接口。当接有外部程序存储器或扩展I/O接口且寻址范围超过256个字节时,P2口用于高8位地址总线送出高8位地址。对于EPROM编程和进行程序校验时,P2口接收输入的8位地址。
(D).P3口(10脚~17脚):P3.0~P3.7统称为P3口。它为双功能口,可以作为一般的准双向I/O接口,也可以将每1位用于第2功能,而且P3口的每一条引脚均可独立定义为第1功能的输入输出或第2功能。P3口的第2功能见下表
表1 单片机P3.0管脚含义
综上所述,MCS—51系列单片机的引脚作用可归纳为以
下两点:
1).单片机功能多,引脚数少,因而许多引脚具有第2功能;
2).单片机对外呈3总线形式,由P2、P0口组成16位地址总线;由P0口分时复用作
为数据总线。
(四)温度传感器电路
采用一线制数字温度传感器DS18B20来作为本课题的温度传感器。传感器输出信号进
4.7K的上拉电阻直接接到单片机的P1.0引脚上。
DS18B20温度传感器是美国达拉斯(DALLAS)半导体公司推出的应用单总线技术的数字温度传感器。该器件将半导体温敏器件、A/D转换器、存储器等做在一个很小的集成电路芯片上。本设计中温度传感器之所以选择单线数字器件DS18B20,是在经过多方面比较和考虑后决定的,主要有以下几方面的原因:
(1)系统的特性:测温范围为-55℃~+125℃ ,测温精度为士0.5℃;温度转换精度9~12位可变,能够直接将温度转换值以16位二进制数码的方式串行输出;12位精度转换的最大时间为750ms;可以通过数据线供电,具有超低功耗工作方式。
(2)系统成本:由于计算机技术和微电子技术的发展,新型大规模集成电路功能越来越强大,体积越来越小,而价格也越来越低。一支DS18B20的体积与普通三极管相差无几,价格只有十元人民币左右。
(3)系统复杂度:由于DS18B20是单总线器件,微处理器与其接口时仅需占用1个I/O端口且一条总线上可以挂接几十个DS18B20,测温时无需任何外部元件,因此,与模拟传感器相比,可以大大减少接线的数量,降低系统的复杂度,减少工程的施工量。
(4)系统的调试和维护:由于引线的减少,使得系统接口大为简化,给系统的调试带来方便。同时因为DS18B20是全数字元器件,故障率很低,抗干扰性强,因此,减少了系统的日常维护工作。
DS18B20温度传感器只有三根外引线:单线数据传输总线端口DQ ,外供电源线VDD,共用地线GND。DS18B20有两种供电方式:一种为数据线供电方式,此时VDD接地,它是通过内部电容在空闲时从数据线获取能量,来完成温度转换,相应的完成温度转换的时间较长。这种情况下,用单片机的一个I/O口来完成对DS18B20总线的上拉。另一种是外部供电方式(VDD接+5V),相应的完成温度测量的时间较短。
在本设计中采用外部供电方式实现DS18B20传感器与单片机的连接,其接口电路如图4所示。
图4 温度传感器接口
(五)系统电源电路的设计
本系统采用电源稳压芯片是LM2596,该开关电压调节器是降压型电源管理单片集成电路,能够输出3A的驱动电流,输入电压是+5v,输入电压是+24v,同时具有很好的线性和负载调节特性。
该器件内部集成频率补偿和固定频率发生器,开关频率为150KHz,与低频开关调节器相比较,可以使用更小规格的滤波元件。
该器件还有其他一些特点:在特定的输入电压和输出负载的条件下,输出电压的误差可以保证在±4%的范围内,振荡频率误差在±15%的范围内;可以用仅80μA的待机电流,实现外部断电;具有自我保护电路(一个两级降频限流保护和一个在异常情况下断电的过温完全保护电路)
在该温度控制系统中,其电源电路设计如下图10所示。
图5 系统电源模块
(六)LCD显示电路
本课题设计的温度控制系统是采用液晶屏128*64作为显示模块,其接口原理图如下图6所示:
图6 液晶显示接口电路
(七)串口通讯电路
本课题设计的通讯采用的是常见的串口通讯,协议转换芯片是采用MAX232A,其接口原理图如下图7所示:
图6 串口通讯接口电路
(八)按键接口电路
本课题设计采用的键盘模块,其接口原理图如下图8所示:
图8 键盘模块电路
(九)DS1302时钟电路
本课题设计的时钟是采用时钟芯片DS1302,其接口原理图如下图9所示:
图9 时钟接口电路
(十)存储器接口电路
本课题设计的存储器采用的是AT24C256,其接口原理图如下图十所示:
图10 存储器电路
三、系统软件设计
系统的软件主要是采用C语言,对单片机进行变成实现各项功能。主程序对模块进行初始化,而后调用读温度、处理温度、显示、键盘等模块。用的是循环查询方式,来显示和控制温度,主程序的主要功能是负责温度的实时显示、读出并处理DS18B20的测量的当前温度值并负责调用各子程序,其程序流程如图10系统程序流程图。
图10系统程序流程图
(一)计算温度子程序
读出温度子程序的主要功能包括初始化,判断DS18B20是否存在,若存在则进行一系列的读操,作若不存在则返回。其程序流程图如图11所示。
图11 读温度流程图
(二)按键处理子程序
按键处理子程序主要是负责参数的设置,主程序每循环一次都要对按键进行扫描,判断是否有输入键按下则进行一系列的按键输入操作。其程序流程框图如图12所示。
图12 温度转换流程图
(三)计算温度子程序
计算温度子程序将RAM中读取值进行BCD码的转换运算,并进行温度值正负的判定,其程序流程图如图13所示。
图13 计算温度子程序
(四)显示数据刷新子程序
显示数据刷新子程序主要是对显示缓冲器中的显示数据进行刷新操作,当最高显示位为0时将符号显示位移入下一位。程序流程图如图14。
N
图14 数据刷新子程序
四、结束语
通过此次毕业论文的课题设计,我们学会了怎样把所学的书本知识应用于实践中去,并学会了如何去思考整个控制系统的软硬件设计。实践过程中我们遇到了一些困难,但在解决问题的过程中,我们学会了团队合作精神和怎样发现问题、分析问题,进而解决问题。此次课程设计不仅增强了我们学习专业课的兴趣,而且给了我们勇气和信心,更重要的是它为我们以后的学习指明了方向。
参考文献
[1] 李广弟,朱月秀,王秀山.《单片机基础》北京航空航天大学出版社,2001(07). [2] 蔡美琴,张为民等.《MCS-51系列单片机系统及其应用》高等教育出版社,2004(06). [3] 张毅刚,等.MCS-51单片机应用设计[M].哈尔滨工业大学出版社,1997. [4] 刘瑞星,胡健等.《Protel DXP 实用教程》机械工业出版社,2003(04). [5] 于海生. 《计算机控制技术》 机械工业出版社 2007(05). [6] 谭浩强. 《C程序设计》 清华大学出版社.
[7] 康华光. 《电子技术基础 模拟部分》 高等教育出版社 1998(08). [8] 余锡存. 《单片机原理与接口技术》 西安电子科技大学出版社,2003.
致谢
本论文是在我的指导老师密切关心和悉心指导下完成的。老师在课题开题期间和论文写作的过程中给予了我许多指导,导师总是以认真负责、一丝不苟的工作态度阅读并修改文章中不足的地方,他优良的作风和严谨治学的态度深深影响着我,至此,向恩师致以最真挚的感谢和最崇高的敬意!
同时我要感谢我的同学,特别是我的室友们,正是他们在这几年里陪我一起成长,一起学习,才让我有了今天的成绩。他们在平时的学习和生活中他们给予了我无私的关怀和帮助,在此表示我最诚挚的谢意。
附件1:系统原理图
附件2:系统相关程序
一、DS18B20底层驱动程序
//延时 N ms
//DS1820引脚定义
sbit TMDAT =P1^0;
void DS1820_DelayCount (unsigned char Coun)
{
data unsigned char Count;
Count=Coun;
while(Count>0) Count--;
Count=Coun;
while(Count>0) Count--;
}
//复位DS18B20
void DS1820_Reset(void)
{
TMDAT=0;
DS1820_DelayCount(412);
TMDAT=1;
DS1820_DelayCount(16);
}
//等待DS18B20应答
unsigned char DS1820_Answer(void)
{
data unsigned int i; data unsigned char j;
while(TMDAT)
{
}
i=0xffff;
j=3;
while(~TMDAT)
{
i--; if (i==0) if(j==0) return(aban_return); else { j--; i=0xffff; } } i--; if (i==0) return(aban_return);
DS1820_DelayCount(16);
return(done_return);
}
//等待DS18B20应答
//读取位
bit DS1820_Readbit(void)
{
data int i=0;
TMDAT=0;i++;i++;i++;i++;
TMDAT=1;i++;i++;i++;i++;i++;i++;i++;i++;
dat = TMDAT;
// DS1820_DelayCount(8);
DS1820_DelayCount(32);
return dat;
}
//读取字节
unsigned char DS1820_Readbyte(void)
{
data unsigned char i,j,dat=0;
for(i=1;i
{
j=DS1820_Readbit();
dat=(j>1);
}
return dat;
}
//写一个字节
void DS1820_Writebyte(unsigned char dat)
{
data signed char i=0;
data unsigned char j;
bit testb;
for(j=1;j
{
testb=dat & 0x01;
dat = dat>>1;
if(testb)
{
TMDAT=0;
i++;i++;i++;i++;i++;i++;i++;i++;
TMDAT=1;
//DS1820_DelayCount(8);
DS1820_DelayCount(32);
}
else
{
TMDAT=0;
//DS1820_DelayCount(8);
DS1820_DelayCount(32);
TMDAT=1;
i++;i++;i++;i++;i++;i++;i++;i++;
}
}
}
//读操作开始
unsigned char DS1820_StartTem(void)
{
EA=0;
DS1820_Reset();
if(DS1820_Answer()==aban_return)
{
EA=Ea;
return(aban_return);
}
// DS1820_Delayms(1);
DS1820_Delayms(4);
DS1820_Writebyte(0xcc);
// DS1820_Writebyte(0x55);
// for(i=0;i
//DS1820_Writebyte(DS1820_temp[i]);
DS1820_Writebyte(0x44);
EA=Ea;
return(done_return);
}
//读所有传感器
int DS1820_ReadTem(void)
{
data unsigned char a,b;
data int y3;
data float y4;
data unsigned char i;
EA=0;
DS1820_Reset();
if(DS1820_Answer()==aban_return)
{
EA=Ea;
return(0xffff);
}
DS1820_Delayms(4);
DS1820_Writebyte(0xcc); //跳过匹配传感器
//DS1820_Writebyte(0x55); //匹配传感器
// for(i=0;i
//DS1820_Writebyte(run_inf.system_index.DS1820_temp[i]);
DS1820_Writebyte(0xbe); //读取温度
for(i=0;i
{
run_inf.system_index.DS1820_temp[i]=DS1820_Readbyte(); } if(CRC(9)!=0) {
EA=1;
return(0xffff);
} //计算CRC
a = run_inf.system_index.DS1820_temp[0];
b = run_inf.system_index.DS1820_temp[1];
DS1820_Reset();
y3 = (b
y4=y3;
y4=(y4*25)/4;
EA=1;
return((int)(y4));
}
二、DS1302时钟底层驱动程序
//DS1302引脚定义
sbit rtc_sc=P3^4;
sbit rtc_io=P3^5;
sbit rst_1302=P3^6;
bdata unsigned char temp;
sbit temp_0 = temp^0;
sbit temp_7 = temp^7;
/************************************************************** DS1302驱动程序开始
**************************************************************/ //功能: 往DS1302写入1Byte数据
void v_RTInputByte(unsigned char ucDa)
{
unsigned char i;
temp = ucDa;
for(i=8; i>0; i--)
{
rtc_io = temp_0; /*相当于汇编中的 RRC */
rtc_sc = 1;
rtc_sc = 0;
temp = temp >> 1;
}
}
//功能: 从DS1302读取1Byte数据
unsigned char uc_RTOutputByte(void)
{
unsigned char i;
rtc_io=1;
for(i=8; i>0; i--)
{
temp = temp >>1; /*相当于汇编中的 RRC */
temp_7 = rtc_io;
rtc_sc = 1;
rtc_sc = 0;
}
return(temp);
}
//功能: 往DS1302写入数据
void write1302(unsigned char ucAddr,unsigned char ucDa)
{
bit ea;
ea=EA;
EA=0;
rtc_rs_port&=(~rtc_rs_bit);
rtc_sc = 0;
rtc_rs_port|=rtc_rs_bit;
v_RTInputByte(ucAddr); /* 地址,命令 */
v_RTInputByte(ucDa); /* 写1Byte数据*/
rtc_sc = 1;
rtc_rs_port&=(~rtc_rs_bit);
EA = ea;
}
//功能: 读取DS1302某地址的数据
unsigned char read1302(unsigned char ucAddr)
{
unsigned char ucDa;
bit ea;
ea=EA;
rtc_rs_port&=(~rtc_rs_bit);
rtc_sc = 0;
rtc_rs_port|=rtc_rs_bit;
v_RTInputByte(ucAddr); /* 地址,命令 */
ucDa = uc_RTOutputByte(); /* 读1Byte数据 */
rtc_sc = 1;
rtc_rs_port&=(~rtc_rs_bit);
EA = ea;
return(ucDa);
}
//功能: 设置初始时间
void Set1302(pTime_S time_temp)
{
unsigned char i= 0x80;
write1302(0x8e,0x00); /* 控制命令,WP=0,写操作*/
write1302(i,time_temp->sec);
i +=2;
write1302(i,time_temp->min);
i +=2;
write1302(i,time_temp->hou);
i +=2;
write1302(i,time_temp->day);
i +=2;
write1302(i,time_temp->mon);
i +=2;
write1302(i,0x02);
i +=2;
write1302(i,time_temp->yea);
write1302(0x8e,0x80); /* 控制命令,WP=1,写保护*/
}
//功能: 读取DS1302当前时间
void get1302(void)
{
unsigned char i,time_bcd_temp[6];
unsigned char ucAddr = 0x81;
for (i=0;i
{
time_bcd_temp[i] = read1302(ucAddr);/*格式为: 秒 分 时 日 月 星期 年 */
ucAddr += 2;
}
sec=time_bcd_temp[0];
min=time_bcd_temp[1];
hou=time_bcd_temp[2];
day=time_bcd_temp[3];
mon=time_bcd_temp[4];
yea=time_bcd_temp[6];
}
//连续6字节读出程序
void ds1302_read(unsigned char *ptr,unsigned char addr)
{
unsigned char i;
}
addr=addr*2+0x0c1; for(i=0;i
//连续6字节写入程序
void ds1302_write(unsigned char *ptr,unsigned char addr)
{
}
void Start1302(void)
{
unsigned char temp;
bit ea;
ea=EA;
EA=0;
unsigned char i; addr=addr*2+0x0c0; write1302(0x8e,0x00); //写保护置低(关闭) for(i=0;i
temp=read1302(0x81);
temp&=0x7f;
write1302(0x8e,0x00); /* 控制命令,WP=0,写操作*/
write1302(0x80,temp);
write1302(0x90,0);
write1302(0x8e,0x80); /* 控制命令,WP=1,写保护*/
EA=ea;
}
//DS1302驱动程序结束
三、数据存储底层驱动程序
//ATC256引脚定义
sbit epr_sd=P3^3;
sbit epr_sc=P3^2;
bdata unsigned char temp1;
sbit temp1_0 = temp1^0;
sbit temp1_7 = temp1^7;
//存储器驱动程序开始
void noack(void)
{
epr_sd=1;
epr_sc=1;
epr_sc=1;
epr_sc=1;
epr_sc=0;
}
void ask()
{
unsigned char i=0xff;
epr_sd=1;
epr_sc=1;
epr_sc=1;
epr_sc=1;
do{
i--;
if(epr_sd==0)
{
epr_sc=0;
i=0;
}
}while(i!=0);
epr_sd=1;
epr_sd=1;
epr_sd=1;
}
void stop()
{
epr_sd=0;
epr_sd=0;
epr_sd=0;
epr_sc=1;
epr_sc=1;
epr_sc=1;
epr_sd=1;
epr_sd=1;
epr_sd=1;
epr_sd=1;
///24c256 start
void start()
{
epr_sc=1; epr_sd=1; epr_sd=1;
epr_sd=0;
epr_sd=0;
epr_sc=0;
}
void wrby(unsigned char x)
{ unsigned char i;
epr_sc=0;
}
//////////////24c256 rdby
unsigned char rdby() //从高位开始读出数据
temp1=x; for(i=0;i
unsigned char i;
epr_sd=1;
epr_sd=1;
epr_sd=1;
for(i=0;i
{
epr_sc=1;
epr_sc=1;
temp1=temp1
temp1_0=epr_sd;
epr_sc=0;
epr_sc=0;
epr_sc=0;
}
return(temp1);
}
///////////////24c256 waddr
void waddr()
{
start();
wrby(0xa0);
ask();}
///////////////24c256 raddr
unsigned char raddr()
{
start();
wrby(0xa1);
ask();
temp1=rdby();
noack();
stop();
return(temp1);
}
void w16addr(unsigned int x)
{
union { unsigned int int_type; unsigned char char_type[1]; }u_int_char; unsigned m,n; u_int_char.int_type=x; //将x的高位赋给m,低位赋给n m=u_int_char.char_type[0]; n=u_int_char.char_type[1];
wrby(m );
ask();
wrby(n );
ask();
}
/////////////////延时
void d5ms()
{
unsigned char a, b;
for (a=0;a
{
for (b=0;b
{;}
}
}
//24c256 读出一字节
unsigned char epr_read(unsigned int x)
{
bit ea; ea=EA;
EA=0; //关中断
EPR_WEN; d5ms();
waddr();
w16addr(x);
temp1=raddr();
EA=ea;//开中断
return(temp1);
}
//24c256 写入一字节
void epr_write(unsigned int f,unsigned char x)
{
bit ea; ea=EA;
EA=0 ; //关中断
d5ms();
waddr();
w16addr(f);
wrby(x);
ask();
stop();
d5ms();
}
//存储器驱动程序结束
汇编部分:
TEMPERATURE_L DATA 31H ;DS18B20低8位Buffer
TEMPERATURE_H DATA 30H ;DS18B20高8位Buffer
TEMPERATURE_HC DATA 32H ;计算后的百位和十位的BCD码存放
;BUFFER
TEMPERATURE_LC DATA 33H ;计算后的个位和小数位的BCD码存放
TEMPERATURE_ZH DATA 34H ; 计算后十位和个位HEX码的存放BUFFER
DIS_BUF_X DATA 35H ;数码管小数位Buffer
DIS_BUF_G DATA 36H ;数码管个位Buffer
DIS_BUF_S DATA 37H ;数码管十位Buffer
DIS_BUF_B DATA 38H ;数码管百位Buffer
KEY_BUF_G DATA 39H ;键盘输入后,的个位值
KEY_BUF_S DATA 49H ;键盘输入后,的十位值
KEY_BUF_B DATA 41H ;键盘输入后,的百位值
K_UP EQU P1.1 ;上调按钮
K_DOWN EQU P1.2 ;下调按钮
K_ENTER EQU P1.0 ;输入数据确认按钮
P_DS18B20 EQU P3.0 ;读取DS18B20的输入端口
P_SWITCH EQU P3.1 ;可控硅控制
FLAG EQU 20H.0 ;标志位,确定是否存在DS18B20
ENTER_FLAG EQU 20H.1 ;键盘输入的标志位,
ORG 0000H
LJMP MAIN
ORG 0100H
MAIN: MOV SP,#60H ;初始化
MOV KEY_BUF_G,#00H ;由于KEY_BUF是由用户输入的,所以先赋值初始化 MOV KEY_BUF_S,#00H
MOV KEY_BUF_B,#00H
NEXT:
LCALL READ_TEMP ;调用读温度子程序
JB FLAG,NORMAL ;判断是否有DS18B20的存在
CALL ERR ;不存在时显示错误信息
AJMP NEXT
NORMAL: LCALL DATA_DEA ;处理从DS18B20得到的数据
LCALL SET_DIS_BUF ;赋值给DIS_BUF_X,G,S,B
EA=ea; //开中断
LCALL DISPLAY ;调用数码管显示子程序
LCALL SCAN_KEY ;扫描键盘
LCALL SWITCH ;处理可控硅
AJMP NEXT
;程序名称:ERR
;功能:程序出错处理,显示四个8,即8888
;入口参数:无
;出口参数:DIS_BUF_X,DIS_BUF_G, DIS_BUF_S, DIS_BUF_B
ERR: MOV DIS_BUF_X,#08H ;如果没有找到DS18B20,那么就显示错误,错误
;显示为888
MOV DIS_BUF_G,#08H
MOV DIS_BUF_S,#08H
MOV DIS_BUF_B,#08H
LCALL DISPLAY
RET
;程序名称:DATA_DEAL
;功能:处理采集后的的数据
;入口参数:TEMPERATURE_L
;出口参数:DIS_BUF_G, DIS_BUF_S, DIS_BUF_
DATA_DEAL:
MOV A,TEMPERATURE_H ;判温度是否零下
ANL A,#80H
JZ TEMPC1 ;A为0,说明是正数,如果是负数,则
;对低8为进行补码处理
CLR C
MOV A,TEMPERATURE_L ;二进制数求补(双字节)
CPL A ;取反加1
ADD A,#01H
MOV TEMPERATURE_L,A
MOV A,TEMPERATURE_H
CPL A
ADDC A,#00H
MOV TEMPERATURE_H,A ;写回TEMPERATURE_H
MOV TEMPERATURE_HC,#0BH
SJMP TEMPC11
TEMPC1: MOV TEMPERATURE_HC,#0AH
TEMPC11: MOV A,TEMPERATURE_HC
SWAP A
MOV TEMPERATURE_HC,A
MOV A,TEMPERATURE_L
ANL A,#0FH
MOV DPTR,#TEMPDOTTAB
MOVC A,@A+DPTR ;查表
MOV TEMPERATURE_LC,A ;TEMPERATURE_LC LOW=小数部分 BCD MOV DIS_BUF_X,A ;小数位的BCD码送入显示buffer中
MOV A,TEMPERATURE_L ;整数部分
ANL A,#0F0H ;得到个位‘单个数值
SWAP A ;SWAP后就得到个位真正的个位
MOV TEMPERATURE_L,A
MOV A,TEMPERATURE_H
ANL A,#0FH
SWAP A
ORL A,TEMPERATURE_L
MOV TEMPERATURE_ZH,A ;组合后的值存入TEMPERATURE_ZH LCALL HtoB ;转换HEx值成为BCD码
MOV TEMPERATURE_L,A
ANL A,#0F0H
SWAP A
ORL A,TEMPERATURE_HC ;TEMPERATURE_HC LOW位 = 十位数
MOV TEMPERATURE_HC,A
MOV A,TEMPERATURE_L
ANL A,#0FH
SWAP A
MOV R7,A
MOV A,TEMPERATURE_HC ;TEMPERATURE_HC HI = 百位数 BCD
ANL A,#0FH
ORL A,R7
MOV TEMPERATURE_HC,A
TEMPC12: RET ;小数部分码表
TEMPDOTTAB:
DB
00H,01H,01H,02H,03H,03H,04H,04H,05H,06H,06H,07H,08H,08H,09H,09H
;0.0625->00H
;0.0625*2 = 0.125->01H
;0.0625*3 = 0.1875->01H
;0.0625*4 = 0.25->02H
;0.0625*5 = 0.3125->03H
;以此类推..........
;程序名称:HtoB
;功能:十六进制转 BCD
;入口参数:A
;出口参数:R7
HtoB: MOV B,#064H ;100
DIV AB ;a/100
MOV R7,A ;
MOV A,#0AH
XCH A,B
DIV AB
SWAP A
ORL A,B
RET
;程序名称:INIT_TEMP
;功能:初始化DS18B20,确定DS18B20是否是存在的
;入口参数:无
;出口参数:FLAG
INIT_TEMP:
SETB P_DS18B20
NOP
CLR P_DS18B20 ;主机发出延时537微秒的复位低脉冲
MOV R0,#6BH
MOV R1,#04H
TSR1: DJNZ R0,$
MOV 40,#6BH
DJNZ R1,TSR1
SETB P_DS18B20 ;然后拉高数据线,释放总线进入接受状态
NOP
NOP
NOP
MOV R0,#32H
TSR2: JNB P_DS18B20,TSR3 ;等待DS18B20回应
DJNZ R0,TSR2
LJMP TSR4 ;延时
TSR3: SETB FLAG ;置标志位,表示DS1820存在
LJMP TSR5
TSR4: CLR FLAG ;清标志位,表示DS1820不存在
LJMP TSR7
TSR5: MOV R0,#06BH
TSR6: DJNZ R0,TSR6 ;时序要求延时一段时间
TSR7: SETB P_DS18B20
RET
;程序名称:READ_TEMP
;功能:读取DS18B20的数据
;入口参数:TEMPERATURE_L,TEMPERATURE_H
;出口参数:无
READ_TEMP:
SETB P_DS18B20
LCALL INIT_TEMP ;先复位DS18B20
JB FLAG,TSS2
RET ;判断DS1820是否存在?若DS18B20不存在则返回
TSS2: MOV A,#0CCH ;跳过ROM匹配
LCALL WRITE_18B20
MOV A,#44H ;发出温度转换命令
LCALL WRITE_18B20
LCALL DISPLAY ;等待AD转换结束,12位的话750微秒
LCALL INIT_TEMP ;准备读温度前先复位
MOV A,#0CCH ;跳过ROM匹配
LCALL WRITE_18B20
MOV A,#0BEH ;发出读温度命令
LCALL WRITE_18B20
LCALL READ_18B20 ;将读出的温度数据保存到35H/36H
RET
程序名称:WRITE_18B20
;功能:将A保存的数值写入DS1820中,
;入口参数:A 寄存器
;出口参数:无
WRITE_18B20:
MOV R2,#8 ;一共8位数据,串行通信
CLR C
WR1: CLR P_DS18B20
MOV R3,#07
DJNZ R3,$
RRC A ;循环右移
MOV P_DS18B20,C
MOV R3,#3CH
DJNZ R3,$ ;23*2 = 46微妙
SETB P_DS18B20
NOP
DJNZ R2,WR1 ;A里面一共是8位,所以要送8次
SETB P_DS18B20 ;释放总线
RET
;程序名称:READ_18B20
;功能:读取18B20中的数据,由于是串行通信,每次读取一个,循环8次读取
;入口参数:TEMPRATURE_L
;出口参数:无
READ_18B20:
MOV R4,#4 ;将温度高位和低位从DS18B20中读出
MOV R1,#TEMPERATURE_L
RE00: MOV R2,#8 ;数据一共有8位
RE01: CLR C
SETB P_DS18B20
NOP
NOP
CLR P_DS18B20
NOP
NOP
NOP
SETB P_DS18B20
MOV R3,#09
RE10: DJNZ R3,RE10
MOV C,P_DS18B20
MOV R3,#3CH
RE20: DJNZ R3,RE20
RRC A
DJNZ R2,RE01
MOV @R1,A
DEC R1
DJNZ R4,RE00
RET
;程序名称:SCAN_KEY
;功能:扫描键盘
;入口参数:DIS_BUF_G,DIS_BUF_S,DIS_BUF_B
;出口参数:KEY_BUF_G,KEY_BUF_S,kEY_BUF_B
SCAN_KEY:
JB K_ENTER,QUIT ;如果又Enter键入,则开始键盘输入
LCALL K_DELAY
JB K_ENTER,QUIT
CLR ENTER_FLAG ;每次进来都赋值输入标志,设置为0
MOV KEY_BUF_G,DIS_BUF_G ;将当前的温度赋值给KEY_BUF
MOV KEY_BUF_S,DIS_BUF_S
MOV KEY_BUF_B,DIS_BUF_B
K_LOOP:
JB ENTER_FLAG,QUIT ;如果输入完成,ENTER_FLAG则为1,退出键盘程
;序
JB K_ENTER,KUP
CALL PRO_ENTER
KUP: JB K_UP,KDOWN
CALL PRO_UP
KDOWN: JB K_DOWN,LOOPA
CALL PRO_DOWN
LOOPA: LCALL DISPLAY
SJMP K_LOOP
QUIT: RET
;程序名称:PRO_ENTER
;功能:确认键盘输入和退出键盘输入
;入口参数:ENTER_FLAG
;出口参数:ENTER_FLAG
PRO_ENTER:
CALL K_DELAY
JB K_ENTER,K_LOOP ;按钮抖动处理
SETB E NTER_FLAG
CALL K_DELAY
RET
;程序名称:PRO_UP
;功能:数值上调处理
;入口参数:KEY_BUF_G,KEY_BUF_S,KEY_BUF_B
;出口参数:DIS_BUF_G,DIS_BUF_S,DIS_BUF_B
PRO_UP:
CALL K_DELAY
JB K_UP,K_LOOP ;按钮抖动处理
INC KEY_BUF_G ;个位增一
MOV A,KEY_BUF_G
CJNE A,#0AH,UPNEXT ;个位增加到10,回0
MOV KEY_BUF_G,#00H
INC KEY_BUF_S ;十位加一
MOV A,KEY_BUF_S
CJNE A,#0AH,UPNEXT ;十位超过99,溢出了
MOV R0,#200
ERROR1: LCALL ERR ;出错,显示8888
DJNZ R0,ERROR1
DEC KEY_BUF_S ;退回99
MOV KEY_BUF_G,#09H
UPNEXT:
MOV DIS_BUF_G,KEY_BUF_G
MOV DIS_BUF_S,KEY_BUF_S
MOV DIS_BUF_B,KEY_BUF_B
CALL K_DELAY
RET
;程序名称:PRO_DOWN
;功能:数值下调处理
;入口参数:KEY_BUF_G,KEY_BUF_S,KEY_BUF_B
;出口参数:DIS_BUF_G,DIS_BUF_S,DIS_BUF_B
PRO_DOWN:
CALL K_DELAY
JB K_DOWN,K_LOOP ;按钮抖动处理
DEC KEY_BUF_G ;个位减一
MOV A,KEY_BUF_G
CJNE A,#0FFH,DOWNNEXT ;个位减到0,回到9
MOV KEY_BUF_G,#09H
DEC KEY_BUF_S ;十位减一
MOV A,KEY_BUF_S
CJNE A,#0FFH,DOWNNEXT;十位低于0,溢出了
MOV R0,#200
ERROR2: LCALL ERR ;出错,显示8888
DJNZ R0,ERROR2
INC KEY_BUF_S ;退回00
MOV KEY_BUF_G,#00H
DOWNNEXT:
MOV DIS_BUF_G,KEY_BUF_G ;增加完成后,赋值退出,然后DISPLAY
;显示出来
MOV DIS_BUF_S,KEY_BUF_S
MOV DIS_BUF_B,KEY_BUF_B
CALL K_DELAY
RET
K_DELAY: ;键盘抖动延时子程序
MOV R6,#250
DL20MS_1:
MOV R7,#200
DJNZ R7,$
DJNZ R6, DL20MS_1
RET
;可控硅控制
SWITCH:
MOV A,KEY_BUF_G ;三个Buffer都是0的话,说明还没有输入数值,直
;接退出
JNZ SNEXT
MOV A,KEY_BUF_S
JNZ SNEXT
MOV A,KEY_BUF_B
JZ SQUIT
SNEXT: CALL SET_DIS_BUF
MOV A,KEY_BUF_S
SUBB A,DIS_BUF_S
JC COOL
JNZ HOT ;十位如果相等,那么继续比较个位
MOV A,KEY_BUF_G
SUBB A,DIS_BUF_G
JC COOL
HOT: CLR P_SWITCH ;P_SWITCH为0说明当前温度小于设定温度,要升温,
;所以接电阻丝
SETB P1.3 ;报警
SJMP SQUIT
COOL: SETB P_SWITCH ;P_SWITCH 为1说明当前温度大于设定温度 SETB P1.3 ;报警
SQUIT: RET
;程序名称:SET_DIS_BUF
;功能:赋值给DIS_BUF_G, DIS_BUF_S, DIS_BUF_B
;入口参数:TEMPERATURE_LC,TEMPERATURE_HC
;出口参数:DIS_BUF_G, DIS_BUF_S, DIS_BUF_B
SET_DIS_BUF:
MOV A,TEMPERATURE_LC
ANL A,#0FH
MOV DIS_BUF_X,A ;小数位
MOV A,TEMPERATURE_LC
SWAP A
ANL A,#0FH
MOV DIS_BUF_G,A ;个位 MOV A,TEMPERATURE_HC ANL A,#0FH
MOV DIS_BUF_S,A ;十位 MOV A,TEMPERATURE_HC SWAP A
ANL A,#0FH
MOV DIS_BUF_B,A ;百位 MOV A,TEMPERATURE_HC ANL A,#0F0H
CJNE A,#010H,NEXT0 SJMP NEXT1
NEXT0: MOV A,TEMPERATURE_HC ANL A,#0FH
JNZ NEXT1 ;十位数是0
MOV A,TEMPERATURE_HC
SWAP A
ANL A,#0FH
MOV 73H,#0AH ;符号位不显示
MOV 72H,A ;十位数显示符号
NEXT1: RET
;程序名称:DISPLAY
;功能:显示数据到数码管中。
;入口参数:DIS_BUF_G, DIS_BUF_S, DIS_BUF_B ;出口参数:无
DISPLAY:
MOV DPTR,#DISTAB
MOV R3,#0FEH
MOV R1,#DIS_BUF_B
DPLOP: MOV A,@R1
MOVC A,@A+DPTR
MOV P2,R3
MOV P0,A
CJNE R3,#0FBH,DPNEXT
CLR P0.7
DPNEXT: MOV A,R3
RL A
MOV R3,A
DEC R1
CALL DS1M
CJNE R3,#0EFH,DPLOP
MOV P0,#0FFH ;一次显示结束,P0口复位 MOV P2,#0FFH ;P2口复位
RET
DS1M: MOV R7,#0FFH
DJNZ R7,$
RET
;数码管TAB
DISTAB:
DB 0C0H ;0
DB 0F9H ;1
DB 0A4H ;2
DB 0B0H ;3
DB 099H ;4
DB 092H ;5
DB 082H ;6
DB 0F8H ;7
DB 080H ;8
DB 090H ;9
DB 0FFH ;NONE END