智能家具设计与总结报告

目录

一.摘要?????????????????

二.引言?????????????????

要求??????????????

难点??????????????

重点??????????????

指导思想????????????

三.设计方案与论证??????????????

单片机芯片的选择方案与论证???????????? 显示的选择方案与论证??????????????? 时钟芯片的选择方案与论证????????????? 温度传感器的选择方案与论证????????????

四.硬件电路设计??????????????

五.系统原理????????????????

六.系统流程????????????????

七.软件测试?????????????????

测试元件??????????

测试内容???????????

八.心得体会??????????????????

九.参考文献??????????????????

十.附录???????????????????

智能家居设计与总结报告

一. 摘要

随着社会生产力的不断提高,单片机技术已广泛应用于各种领域,成为一种比较成熟的技术。

本设计基于AT89S52单片机设计了集万年历、温度传感器与烟雾传感器为一起的小型小型

室内环境检测系统。电路分为LM016 LCD显示、DS1302时钟芯片,DS18B20 温度传感器、

湿度传感器和MAX232。该设计主要通过数个按键、一个LCD1602、一个DS1302时钟芯

片、一个DS18B20温度模块等器件完成时间、日期的显示、声音提示、液晶显示、灯光警

告、复位等功能。

关键词:单片机、LCD1602、DS1302、DS18B20、MAX232

二.引言

要求:使用单片机设计一个简易的室内监测环境系统,实现下述功能:

(1)自动更新时间与日期及温度,且能够显示在LCD液晶屏上。

(2)烟雾报警,并且使用发光二极管、蜂鸣器等进行警告提示、正确提示的声光报警功能。

统的主要控制芯片

(3)光控开关,通过光敏二极管实现。

重点:对各主要模块进行讲解及对程序的论述,了解全局电路原理图及显示原 理。

难点:

具有万年历功能,能够调节时间及日期;

(2)在超过温度范围时,发出温度报警提示。

本论文的指导思想

本论文先对系统指定的主要芯片进行选择和论证,确定了选定AT89S52作为系统的主

要控制芯片,时钟芯片DS1302提供时钟,数字时温度传感器实现温度显示,显示部分采用

LCD显示屏。

三、方案设计与论证

(1)单片机芯片的选择方案与论证

方案1:采用89S52作为主要的核心芯片,采用flashROM,内部具有4KB的存储空间,能

在3V的超低压工作,而且与MCS-51单片机完全兼容。但是运用于电路设计中不具有ISP

在线编程功能,当对电路进行调试时,由于程序的错误修改或新增功能需要烧入程序时,对

芯片的多次拔插可能对芯片造成一定的损坏。

方案2:采用89S52,片内ROM全部采用FlashROM能在3V的超低压下工作,同时也与

MCS-51单片机兼容,该芯片内部为8KB ROM的存储空间,也具有89C51的功能,切具有

在线编程可擦除技术,当对电路进行调试时,由于程序的错误修改或新增功能需要烧入程序

时,不需对芯片的进行多次拔插,所以不会对芯片造成损坏。

(2)显示模块选择方案与论证

方案1:采用LED数码管进行动态扫描,虽然LED数码管价格适中,对于显示数字也较合

适,然而在需要多为狮子与字幕显示时编程较复杂,占用单片机口线多。

方案2:采用点阵式数码管显示,点正事数码管由四行四列发光二极管组成,对于显示文字

比较适合,但用在显示数字时比较浪费,而且价格也较高,所以不采用此方式作为显示。

方案3:采用LCD液晶屏显示,LCD液晶屏显示虽然价格较高,但其显示功能强大,可以显示字符,且需要的接口线少。

所以采用LCD液晶屏作为显示。

(3)时钟芯片的选择方案与论证

方案1:直接采用单片机定时计数器提供秒信号,使用程序实现年、月、日、星期、时、分、秒的计数,采用此种方案虽然可以减少芯片的使用,节约成本,但是实现时间误差较大。 方案2:采用DS1302作为时钟芯片,DS1302是一种高性能时钟芯片,可自动对时间日期进行计数,且精度高,位的RAM作为数据暂存区,工作电压在2.5V-5.5V

,2.5V时耗电小于300mA。

因而采用DS1302提供时钟。

(4)温度传感器的选择方案与论证

方案1:使用热敏电阻作为传感器,并与一相应电阻进行串联分压,利用热敏电阻的温度特性,采集量电阻变化的分压值,进行A/D转换。此设计方案需用A/D转换电路,增加硬件成本,而且热敏电阻的温度特性曲线并不是严格线性的,会产生较大误差。

方案2:采用数字时温度传感器DS18B20,此类传感器位数字传感器,而且仅需要一条数据线进行传输,易于与单片机进行连接,可以去除A/D转换模块,降低硬件成本,简化系统模型。且数字时温度传感器还具有测量精度高,范围广等优点。

所以采用数字式温度传感器DS18B20测量温度。

电路设计最终方案

综上各方案论证,对此次作品的方案决定:采用AT89S52作为主控制系统,DS1302提供时钟,DS18B20数字温度传感器测量温度,LCD液晶屏作为显示模块。

四、硬件电路设计

系统总体框图如下:

智能家具设计与总结报告

图1.1 系统硬件模块图

模块说明:DS1302时钟模块可以显示当前时间、日期及星期;

键盘输入电路可以调整日期及时间;

DS18B20温度模块可以测量当前室内温度;

蜂鸣器模块可以提供烟雾警示;

显示电路显示当前系统运行情况。

DS1302时钟电路的设计

单片机必须在时钟的驱动下才能工作.在单片机内部有一个时钟振荡电路,只需要外接一个振荡源就能产生一定的时钟信号送到单片机内部的各个单元,决定单片机的工作速度。

智能家具设计与总结报告

图1.2外部振荡源电路

一般选用石英晶体振荡器。此电路在加电大约延迟10ms后振荡器起振,在XTAL2引脚产生幅度为3V左右的正弦波时钟信号,其振荡频率主要由石英晶振的频率确定。电路中两个电容 C1,C2的作用有两个:一是帮助振荡器起振;二是对振荡器的频率进行微调。C1,C2的典型值为30PF。

单片机在工作时,由内部振荡器产生或由外直接输入的送至内部控制逻辑单元的时钟信号的周期称为时钟周期。其大小是时钟信号频率的倒数,常用fosc表示。如时钟频率为12MHz,即fosc=12MHz,则时钟周期为1/12?s。

2、复位电路的设计

单片机的第9脚RST为硬件复位端,只要将该端持续4个机器周期的高电平即可实现复位,复位后单片机的各状态都恢复到初始化状态,其电路图如图1.3所示:

智能家具设计与总结报告

图1.3复位电路

值得注意的是,在设计当中使用到了硬件复位和软件复位两种功能,由上面的硬件复位后的各状态可知寄存器及存储器的值都恢复到了初始值,而前面的功能介绍中提到了倒计时时间的记忆功能,该功能的实现的前提条件就是不能对单片机进行硬件复位,所以设定了软复位功能。软复位实际上就是当程序执行完毕之后,将程序指针通过一条跳转指令让它跳转到程序执行的起始地址。

3、显示电路的设计

显示功能与硬件关系极大,当硬件固定后,如何在不引起操作者误解的前提下提供尽可能丰富的信息,全靠软件来解决。

4、键盘扫描电路的设计

键盘是人与微机系统打交道的主要设备。关于键盘硬件电路的设计方法也可以在文献和书籍中找到,配合各种不同的硬件电路,这些书籍中一般也提供了相应的键盘扫描程序。站在系统监控软件设计的立场上来看,仅仅完成键盘扫描,读取当前时刻的键盘状态是不够的,还有不少问题需要妥善解决,否则,人们在操作键盘就容易引起误操作和操作失控现象。在单片机应用中键盘用得最多的形式是独立键盘及矩阵键盘。如图1.4开关电路。

智能家具设计与总结报告

图1.4开关电路

一般用在对硬件电路要求不高的简单电路中;矩阵键盘更适合于多按键电路。关于消除在按键过程中产生的“毛刺”现象。这里采用最常用的方法,即延时重复扫描法,延时法的原理为:因为“毛刺”脉冲一般持续时间短,约为几ms,而我们按键的时间一般远远大于这个时间,所以当单片机检测到有按键动静后再延时一段时间(这里我们取10ms)后再判断此电平是否保持原状态,如果是则为有效按键,否则无效。

液晶显示屏电路

智能家具设计与总结报告

五.系统原理

本系统是由AT89S52单片机为控制核心,时钟电路由DS1302提供,它可以对年、月、日、星期、时、分、秒进行计时,温度的采集由DS18B20构成,用LCD1602来显示数据,键盘输入电路可以调整时间及日期,通过C语言编程,从DS1302寄存器中读取数据信息,从DS18B20中读取温度信息数据,再编程将以上信息送入LCD1602显示出来,同时通过键盘扫描来调整日期。

智能家具设计与总结报告

图1.5 系统总原理框图

六.系统流程

智能家具设计与总结报告

智能家具设计与总结报告

时间调整流程图

智能家具设计与总结报告

图1.7时间调整程序流程图

七.软件测试

1.测试元件

智能家具设计与总结报告

2、测试内容:

蜂鸣器不报警,原因:蜂鸣器前置放大器放大倍数不够。

解决办法:更改蜂鸣器前置放大器,以达到放大倍数要求。

(2)LCD不显示字符,原因:LCD的电位器设置的阻值过高,导致字符显示亮度过低,字符显示而人眼无法察觉。

解决办法:调整电位器阻值,直至屏幕亮度适中,可以正常显示字符为止。

(3)LCD显示闪烁且亮度不均匀,原因:硬件电路电压不稳,导致芯片无法正常工作。 解决办法:对调用的延时进行逐渐修改,可解决闪烁问题;其次本作品是动态扫描方式显示的数字,动态扫描很快,人眼无法识别,但在调用显示程序时,如不在返回时屏蔽掉最后的附值,会出现很亮的现象,因而在现显示后面加了屏闭指令。

加入温度程序后进行修改时间日期未按要求值变化。

解决办法:由于DS18B20是串行通信数据,只用一个口线传输,在处理采集模拟信号时需要一定的时间,当把万年历的程序接入后,会对延时有很大的影响。因而在调用温度子程序时,先关闭定时器1中断允许,再介入温度子程序后再打开定时器1中断允许,从而解决此问题。 八.心得体会

在整个设计过程中,发挥团队精神,分工合作,充分发挥人的主观能动性,自主学习,学到了许多没学到的知识。较好的完成了作品。达到了预期的目的,在最初的设计中,发挥“三个臭皮匠,顶个诸葛亮”的作用。相互学习、相互讨论、研究。完了最初的设想。在电路焊接时虽然没什么大问题,但从中也知道了焊接在整个作品中的重要性,电路工程量大,不能心急,一个个慢慢来不能急于求成。反而达到事半功倍的效果。对电路的设计、布局要先有一个好的构思,才显得电路板美观、大方。程序编写中,由于思路不清晰,开始时遇到了很多的问题,经过静下心来思考,和同组员的讨论,理清了思路,反而得心应手。在此次设计中,知道了做凡事要有一颗平常的心,不要想着走捷径,一步一个脚印。也练就了我们的耐心,做什么事都在有耐心。此次比赛中学到了很多很多东西,这是最重要的。总之,参加电子竞赛我们的能力得到了全方位的提高。

九.参考文献

(1)谭浩强.C程序设计【M】.清华大学出版社,2005:1-300

(2)阎石.数字电子技术基础【M】.北京:等教育出版社,1995.4

(3)化成英.模拟电子技术基础【M】.北京:等教育出版社社.2001.12

(4)万福君、潘松等.单片微机原理系统设计与应用【M】.北京:

中国科学技术出版社,2005:1-357

(5)李权利,迟荣强等.单片机原理及接口技术【M】.北京:高等教育出版社,2004.1

十.附录

#include <REG51.H>

#include <intrins.h>

//#include "LCD1602.h"

//#include "DS1302.h"

#define uint unsigned int

#define uchar unsigned char

sbit DS1302_CLK = P1^7; //实时时钟时钟线引脚

sbit DS1302_IO = P1^6; //实时时钟数据线引脚

sbit DS1302_RST = P1^5; //实时时钟复位线引脚

sbit wireless_1 = P3^4;

sbit wireless_2 = P3^5;

sbit wireless_3 = P3^6;

sbit wireless_4 = P3^7;

sbit ACC0 = ACC^0;

sbit ACC7 = ACC^7;

sbit lightk=P1^2;

sbit lightled=P3^7;

sbit lightld=P3^2;

sbit yanwu=P1^1;

sbit ldk=P3^3;

sbit beep=P2^4;

sbit tempk1=P1^3;

sbit tempk2=P1^4;

uchar tempkk;

uchar tempkl;

char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year;

月,年位闪的计数

sbit Set = P2^0; //模式切换键

sbit Up = P2^1; //加法按钮

sbit Down = P2^2; //减法按钮

sbit out = P2^3; //立刻跳出调整模式按钮----

sbit DQ = P1^0; //温度传送数据IO口

char done,count,temp,flag,up_flag,down_flag;

uchar temp_value; //温度值

uchar TempBuffer[5],week_value[2];

void show_time(); //液晶显示程序

/***********1602液晶显示部分子程序****************/ //秒,分,时到日,

//Port Definitions********************************************************** sbit LcdRs = P2^5;

sbit LcdRw = P2^6;

sbit LcdEn = P2^7;

sfr DBPort = 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口

//内部等待函

************************************************************************** unsigned char LCD_Wait(void)

{

LcdRs=0;

LcdRw=1; _nop_();

LcdEn=1; _nop_();

LcdEn=0;

return DBPort;

}

//向LCD写入命令或数************************************************************

#define LCD_COMMAND 0 // Command

#define LCD_DATA 1 // Data

#define LCD_CLEAR_SCREEN 0x01 // 清屏

#define LCD_HOMING 0x02 // 光标返回原点

void LCD_Write(bit style, unsigned char input)

{

LcdEn=0;

LcdRs=style;

LcdRw=0; _nop_();

DBPort=input; _nop_();//注意顺序

LcdEn=1; _nop_();//注意顺序

LcdEn=0; _nop_();

LCD_Wait();

}

//设置显示模式************************************************************ #define LCD_SHOW 0x04 //显示开

#define LCD_HIDE 0x00 //显示关

#define LCD_CURSOR 0x02 //显示光标

#define LCD_NO_CURSOR 0x00 //无光标

#define LCD_FLASH 0x01 //光标闪动 数据

#define LCD_NO_FLASH 0x00 //光标不闪动

void LCD_SetDisplay(unsigned char DisplayMode)

{

LCD_Write(LCD_COMMAND, 0x08|DisplayMode);

}

//设置输入模式************************************************************ #define LCD_AC_UP 0x02

#define LCD_AC_DOWN

#define LCD_MOVE

0x00 // default 0x01 // 画面可平移 0x00 //default #define LCD_NO_MOVE

void LCD_SetInput(unsigned char InputMode)

{

LCD_Write(LCD_COMMAND, 0x04|InputMode);

}

//初始化LCD************************************************************ void LCD_Initial()

{

LcdEn=0; LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵 LCD_Write(LCD_COMMAND,0x38); LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标 LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏 LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动 }

//液晶字符输入的位置************************

void GotoXY(unsigned char x, unsigned char y)

{

if(y==0) LCD_Write(LCD_COMMAND,0x80|x); if(y==1) LCD_Write(LCD_COMMAND,0x80|(x-0x40));

}

//将字符输出到液晶显示

void Print(unsigned char *str)

{

while(*str!='\0') {

}

} LCD_Write(LCD_DATA,*str); str++;

/***********DS1302时钟部分子程序******************/

typedef struct __SYSTEMTIME__

{

unsigned char Second; unsigned char Minute; unsigned char Hour; unsigned char Week; unsigned char Day; unsigned char Month; unsigned char Year; unsigned char DateString[11];

unsigned char TimeString[9];

}SYSTEMTIME; //定义的时间类型

SYSTEMTIME CurrentTime;

#define AM(X) X

#define PM(X) (X+12) // 转成24小时制

#define DS1302_SECOND 0x80 //时钟芯片的寄存器位置,存放时间 #define DS1302_MINUTE 0x82

#define DS1302_HOUR

#define DS1302_WEEK

#define DS1302_DAY

#define DS1302_MONTH 0x84 0x8A 0x86 0x88

#define DS1302_YEAR 0x8C

void DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数) {

unsigned char i;

ACC = d;

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

{

DS1302_IO = ACC0;

DS1302_CLK = 1; //相当于汇编中的 RRC

DS1302_CLK = 0;

ACC = ACC >> 1;

}

}

unsigned char DS1302OutputByte(void)

{

unsigned char i;

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

{

ACC = ACC >>1;

ACC7 = DS1302_IO;

DS1302_CLK = 1;

DS1302_CLK = 0;

}

return(ACC);

}

void Write1302(unsigned char ucAddr, unsigned char ucDa)

要写的数据

{

DS1302_RST = 0; DS1302_CLK = 0; DS1302_RST = 1; DS1302InputByte(ucAddr); //相当于汇编中的 RRC //实时时钟读取一字节(内部函数) //ucAddr: DS1302地址, ucData: // 地址,命令

DS1302InputByte(ucDa); // 写1Byte数据

DS1302_CLK = 1;

DS1302_RST = 0;

}

unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据 {

unsigned char ucData;

DS1302_RST = 0;

DS1302_CLK = 0;

DS1302_RST = 1;

DS1302InputByte(ucAddr|0x01); // 地址,命令

ucData = DS1302OutputByte(); // 读1Byte数据

DS1302_CLK = 1;

DS1302_RST = 0;

return(ucData);

}

void DS1302_GetTime(SYSTEMTIME *Time) //获取时钟芯片的时钟数据到自定义的结构型数组

{

}

void DateToStr(SYSTEMTIME *Time) //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]

{ if(hide_year<2) //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22

{

Time->DateString[0] = '2';

Time->DateString[1] = '0'; Time->DateString[2] = Time->Year/10 + '0'; Time->DateString[3] = Time->Year%10 + '0'; } else { Time->DateString[0] = ' '; Time->DateString[1] = ' '; Time->DateString[2] = ' '; Time->DateString[3] = ' '; } Time->DateString[4] = '/'; if(hide_month<2) { Time->DateString[5] = Time->Month/10 + '0'; Time->DateString[6] = Time->Month%10 + '0'; } unsigned char ReadValue; ReadValue = Read1302(DS1302_SECOND); Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_MINUTE); Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_HOUR); Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_DAY); Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_WEEK); Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_MONTH); Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_YEAR); Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);

else { Time->DateString[5] = ' '; Time->DateString[6] = ' '; } Time->DateString[7] = '/'; if(hide_day<2) { Time->DateString[8] = Time->Day/10 + '0'; Time->DateString[9] = Time->Day%10 + '0'; } else { Time->DateString[8] = ' '; Time->DateString[9] = ' '; } if(hide_week<2) { week_value[0] = Time->Week%10 + '0'-1; //星期的数据另外放到 week_value[]数组} else { week_value[0] = ' '; } week_value[1] = '\0'; Time->DateString[10] = '\0'; //字符串末尾加 '\0' ,判断结束字符 里,跟年,月,日的分开存放,因为等一下要在最后显示

}

void TimeToStr(SYSTEMTIME *Time) //将时,分,秒数据转换成液晶显示字符放到数组 TimeString[];

{ if(hide_hour<2)

{

Time->TimeString[0] = Time->Hour/10 + '0'; Time->TimeString[1] = Time->Hour%10 + '0'; } else { Time->TimeString[0] = ' '; Time->TimeString[1] = ' ';

}

Time->TimeString[2] = ':';

if(hide_min<2)

{ Time->TimeString[3] = Time->Minute/10 + '0'; Time->TimeString[4] = Time->Minute%10 + '0'; } else { Time->TimeString[3] = ' ';

Time->TimeString[4] = ' ';

}

Time->TimeString[5] = ':';

if(hide_sec<2)

{

Time->TimeString[6] = Time->Second/10 + '0'; Time->TimeString[7] = Time->Second%10 + '0'; }

else

{

Time->TimeString[6] = ' ';

Time->TimeString[7] = ' ';

}

Time->DateString[8] = '\0';

}

void Initial_DS1302(void) //时钟芯片初始化

{

unsigned char Second=Read1302(DS1302_SECOND); if(Second&0x80) //判断时钟芯片是否关闭 {

Write1302(0x8e,0x00); //写入允许

}

/***********ds18b20子程序*************************/ Write1302(0x8c,0x07); //以下写入初始化时间 日期:07/07/25.星期: 3. 时间: 23:59:55 Write1302(0x88,0x07); Write1302(0x86,0x25); Write1302(0x8a,0x07); Write1302(0x84,0x23); Write1302(0x82,0x59); Write1302(0x80,0x55); Write1302(0x8e,0x80); //禁止写入 }

/***********ds18b20延迟子函数(晶振12MHz )*******/

void delay_18B20(unsigned int i)

{

while(i--);

}

/**********ds18b20初始化函数**********************/

void Init_DS18B20(void)

{

}

/***********ds18b20读一个字节**************/

unsigned char ReadOneChar(void)

{

} uchar i=0; uchar dat = 0; for (i=8;i>0;i--) { DQ = 0; // 给脉冲信号 } return(dat); dat>>=1; DQ = 1; // 给脉冲信号 if(DQ) dat|=0x80; delay_18B20(4); unsigned char x=0; DQ = 1; //DQ复位 delay_18B20(8); //稍做延时 DQ = 0; //单片机将DQ拉低 delay_18B20(80); //精确延时 大于 480us DQ = 1; //拉高总线 delay_18B20(14); x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败 delay_18B20(20);

/*************ds18b20写一个字节****************/

void WriteOneChar(uchar dat)

{

unsigned char i=0;

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

{

DQ = 0;

DQ = dat&0x01;

delay_18B20(5);

DQ = 1;

dat>>=1;

}

}

/**************读取ds18b20当前温度************/

void ReadTemp(void)

{

unsigned char a=0;

unsigned char b=0;

unsigned char t=0;

Init_DS18B20();

WriteOneChar(0xCC); // 跳过读序号列号的操作

WriteOneChar(0x44); // 启动温度转换

delay_18B20(100); // this message is very important

Init_DS18B20();

WriteOneChar(0xCC); //跳过读序号列号的操作

WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器)

delay_18B20(100);

a=ReadOneChar(); //读取温度值低位

b=ReadOneChar(); //读取温度值高位

temp_value=b<<4;

temp_value+=(a&0xf0)>>4;

}

void temp_to_str() //温度数据转换成液晶字符显示

{

TempBuffer[0]=temp_value/10+'0'; //十位

TempBuffer[1]=temp_value%10+'0'; //个位

TempBuffer[2]=0xdf; //温度符号

TempBuffer[3]='C';

TempBuffer[4]='\0';

} 前两个就是温度

void Delay1ms(unsigned int count)

{

}

/*延时子程序*/

void mdelay(uint delay)

{ uint i;

for(;delay>0;delay--)

{for(i=0;i<62;i++) //1ms延时.

}

}

void outkey() //跳出调整模式,返回默认显示

{ uchar Second;

if(out==0||wireless_1==1)

{ mdelay(8);

count=0;

hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month=0,hide_year=0; Second=Read1302(DS1302_SECOND);

Write1302(0x8e,0x00); //写入允许

}

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Upkey()//升序按键

{

Up=1; if(Up==0||wireless_2==1) { mdelay(8); switch(count) Write1302(0x80,Second&0x7f); Write1302(0x8E,0x80); //禁止写入 done=0; while(out==0); while(wireless_1==1); {;} unsigned int i,j; for(i=0;i<count;i++) for(j=0;j<120;j++);

{case 1:

temp=Read1302(DS1302_SECOND); //读取秒数 temp=temp+1; //秒数加1

up_flag=1; //数据调整后更新标志

if((temp&0x7f)>0x59) //超过59秒,清零

temp=0; break;

case 2:

temp=Read1302(DS1302_MINUTE); //读取分数 temp=temp+1; //分数加1

up_flag=1;

if(temp>0x59) //超过59分,清零 temp=0;

break;

case 3:

temp=Read1302(DS1302_HOUR); //读取小时数 temp=temp+1; //小时数加1

up_flag=1;

if(temp>0x23) //超过23小时,清零

temp=0;

break;

case 4:

temp=Read1302(DS1302_WEEK); //读取星期数 temp=temp+1; //星期数加1

if(temp>0x7)

temp=1;

break;

temp=Read1302(DS1302_DAY); //读取日数

temp=temp+1; //日数加1 up_flag=1; case 5:

up_flag=1;

if(temp>0x31)

temp=1;

break;

case 6:

temp=Read1302(DS1302_MONTH); //读取月数 temp=temp+1; //月数加1

up_flag=1;

if(temp>0x12)

temp=1;

break;

case 7:

temp=Read1302(DS1302_YEAR); //读取年数 temp=temp+1; //年数加1

up_flag=1;

if(temp>0x85)

temp=0;

}

break; default:break; } while(Up==0); } while(wireless_2==1);

////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Downkey()//降序按键

{

Down=1; if(Down==0||wireless_3==1) { mdelay(8);

switch(count)

{case 1:

temp=Read1302(DS1302_SECOND); //读取秒数

减1 temp=temp-1; //秒数

down_flag=1; //数据调整后更新标志 if(temp==0x7f) //小于0秒,返回59秒

temp=0x59; break;

case 2:

temp=Read1302(DS1302_MINUTE); //读取分数 temp=temp-1; //分数减1

down_flag=1;

if(temp==-1)

temp=0x59; //小于0秒,返回59秒 break;

case 3:

temp=Read1302(DS1302_HOUR); //读取小时数

temp=temp-1; //小时数减1 if(temp==-1) temp=0x23; break; down_flag=1;

case 4:

temp=Read1302(DS1302_WEEK); //读取星期数 temp=temp-1; //星期数减1

down_flag=1;

if(temp==0)

temp=0x7;;

break;

case 5:

temp=Read1302(DS1302_DAY); //读取日数 temp=temp-1; //日数减1

down_flag=1;

if(temp==0) temp=31; break;

case 6:

temp=Read1302(DS1302_MONTH); //读取月数 temp=temp-1; //月数减1

down_flag=1;

if(temp==0)

temp=12; break;

case 7:

temp=Read1302(DS1302_YEAR); //读取年数 temp=temp-1; //年数减1

down_flag=1;

} if(temp==-1) temp=0x85; break; default:break; } while(Down==0); while(wireless_3==1); }

void Setkey()//模式选择按键

{

Set=1; if(Set==0||wireless_4==1) {

mdelay(8);

count=count+1; //Setkey按一次,count就加1

done=1; //进入调整模式

while(Set==0);

while(wireless_4==1);

} }

void keydone()//按键功能执行

{ uchar Second;

if(flag==0) //关闭时钟,停止计时

{ Write1302(0x8e,0x00); //写入允许

temp=Read1302(0x80);

Write1302(0x80,temp|0x80);

Write1302(0x8e,0x80); //禁止写入

flag=1;

}

Setkey(); //扫描模式切换按键 switch(count)

{case 1:do //count=1,调整秒 {

outkey(); //扫描跳出按钮 Upkey(); //扫描加按钮

Downkey(); //扫描减按钮 if(up_flag==1||down_flag==1) //数据更新,重新写入新的数据 { Write1302(0x8e,0x00); //写入允许 Write1302(0x80,temp|0x80); //写入新的秒数 Write1302(0x8e,0x80); //禁止写入 up_flag=0; down_flag=0; } hide_sec++; //位闪计数

if(hide_sec>3)

hide_sec=0;

show_time(); //液晶显示数据

}while(count==2);break; case 2:do //count=2,调整分 { hide_sec=0; outkey(); Upkey(); Downkey(); if(temp>0x60) temp=0; if(up_flag==1||down_flag==1) { Write1302(0x8e,0x00); //写入允许 Write1302(0x82,temp); //写入新的分数 Write1302(0x8e,0x80); //禁止写入

up_flag=0; down_flag=0; } hide_min++; if(hide_min>3) hide_min=0; show_time(); }while(count==3);break; case 3:do //count=3,调整小时 {

hide_min=0;

outkey();

Upkey(); Downkey(); if(up_flag==1||down_flag==1) { Write1302(0x8e,0x00); //写入允许 Write1302(0x84,temp); //写入新的小时数 Write1302(0x8e,0x80); //禁止写入 up_flag=0; down_flag=0; } hide_hour++; if(hide_hour>3) hide_hour=0;

show_time();

}while(count==4);break;

case 4:do //count=4,调整星期 {

hide_hour=0;

outkey(); Upkey(); Downkey(); if(up_flag==1||down_flag==1) { Write1302(0x8e,0x00); //写入允许 Write1302(0x8a,temp); //写入新的星期数 Write1302(0x8e,0x80); //禁止写入 up_flag=0; down_flag=0; } hide_week++; if(hide_week>3) hide_week=0;

show_time();

}while(count==5);break; case 5:do //count=5,调整日 { hide_week=0; outkey(); Upkey(); Downkey(); if(up_flag==1||down_flag==1) { Write1302(0x8e,0x00); //写入允许 Write1302(0x86,temp); //写入新的日数 Write1302(0x8e,0x80); //禁止写入 up_flag=0; down_flag=0; } hide_day++; if(hide_day>3) hide_day=0; show_time(); }while(count==6);break; case 6:do //count=6,调整月 {

hide_day=0;

outkey();

Upkey(); Downkey(); if(up_flag==1||down_flag==1) { Write1302(0x8e,0x00); //写入允许 Write1302(0x88,temp); //写入新的月数 Write1302(0x8e,0x80); //禁止写入 up_flag=0; down_flag=0; } hide_month++; if(hide_month>3)

hide_month=0;

show_time();

}while(count==7);break; case 7:do //count=7,调整年 {

hide_month=0;

outkey();

Upkey(); Downkey(); if(up_flag==1||down_flag==1) { Write1302(0x8e,0x00); //写入允许 Write1302(0x8c,temp); //写入新的年数 Write1302(0x8e,0x80); //禁止写入 up_flag=0; down_flag=0; } hide_year++; if(hide_year>3)

hide_year=0;

show_time();

}while(count==8);break; case 8: count=0;hide_year=0; //count8, 跳出调整模式,返回默认显示状态 Second=Read1302(DS1302_SECOND);

Write1302(0x8e,0x00); //写入允许

}

void show_time() //液晶显示程序

{

DS1302_GetTime(&CurrentTime); //获取时钟芯片的时间数据

TimeToStr(&CurrentTime); //时间数据转换液晶字符

DateToStr(&CurrentTime); //日期数据转换液晶字符

ReadTemp(); //开启温度采集程序

temp_to_str(); //温度数据转换成液晶字符

GotoXY(12,1); //液晶字符显示位置

Print(TempBuffer); //显示温度

GotoXY(0,1);

Print(CurrentTime.TimeString); //显示时间

GotoXY(0,0);

Print(CurrentTime.DateString); //显示日期

//GotoXY(15,0);

//Print(week_value); //显示星期 Write1302(0x80,Second&0x7f); Write1302(0x8E,0x80); //禁止写入 done=0; break; //count=7,开启中断,标志位置0并退出 default:break; }

GotoXY(11,0);

if(week_value[0]=='0') Print("SUN"); if(week_value[0]=='1') Print("MON"); if(week_value[0]=='2') Print("TUE"); if(week_value[0]=='3') Print("WED");

if(week_value[0]=='4') Print("THU");

if(week_value[0]=='5') Print("FRI");

if(week_value[0]=='6') Print("STA");

//Print("Week"); //在液晶上显示 字母 week

Delay1ms(400); //扫描延时

}

main()

{

flag=1; //时钟停止标志

LCD_Initial(); //液晶初始化

Init_DS18B20( ) ; //DS18B20初始化

Initial_DS1302(); //时钟芯片初始化 up_flag=0; down_flag=0; done=0; //进入默认液晶显示 wireless_1=0; wireless_2=0; wireless_3=0; wireless_4=0; lightk=1; lightled=0; lightld=1; ldk=1; beep=1; tempk1=1; tempk2=1; while(1) {

while(done==1)

keydone(); //进入调整模式

while(done==0)

{

show_time(); //液晶显示数据 flag=0;

Setkey(); /* { */ if(lightk==1) lightld=1; else lightld=0; if(ldk==0) {lightld=0;} else lightld=1;} //扫描各功能键

;;

if(tempk1==1)

tempkk=30; else

tempkk=40;

if(tempk2==1)

tempkl=10;

else tempkl=20;

;;

if(temp_value>tempkk||temp_value<tempkl||ldk==0||yanwu==0) beep=0;

else

} } beep=1; }

相关推荐