基于51单片机设计的带有测温功能的电子时钟汇总

合集下载

基于51单片机的多功能电子钟设计

基于51单片机的多功能电子钟设计

基于51单片机的多功能电子钟设计1. 本文概述随着现代科技的发展,电子时钟已成为日常生活中不可或缺的一部分。

本文旨在介绍一种基于51单片机的多功能电子钟的设计与实现。

51单片机因其结构简单、成本低廉、易于编程等特点,在工业控制和教学实验中得到了广泛应用。

本文将重点阐述如何利用51单片机的这些特性来设计和实现一个具有基本时间显示、闹钟设定、温度显示等功能的电子钟。

本文的结构安排如下:将详细介绍51单片机的基本原理和特点,为后续的设计提供理论基础。

接着,将分析电子钟的功能需求,包括时间显示、闹钟设定、温度显示等,并基于这些需求进行系统设计。

将详细讨论电子钟的硬件设计,包括51单片机的选型、时钟电路、显示电路、温度传感器电路等。

软件设计部分将介绍如何通过编程实现电子钟的各项功能,包括时间管理、闹钟控制、温度读取等。

本文将通过实验验证所设计的电子钟的功能和性能,并对实验结果进行分析讨论。

通过本文的研究,旨在为电子钟的设计提供一种实用、经济、可靠的方法,同时也为51单片机的应用提供一个新的实践案例。

2. 51单片机概述51单片机,作为一种经典的微控制器,因其高性能、低功耗和易编程的特性而被广泛应用于工业控制、智能仪器和家用电器等领域。

它基于Intel 8051微处理器的架构,具备基本的算术逻辑单元(ALU)、程序计数器(PC)、累加器(ACC)和寄存器组等核心部件。

51单片机的核心是其8位CPU,能够处理8位数据和执行相应的指令集。

51单片机的内部结构主要包括中央处理单元(CPU)、存储器、定时器计数器、并行IO口、串行通信口等。

其存储器分为程序存储器(ROM)和数据存储器(RAM)。

程序存储器通常用于存放程序代码,而数据存储器则用于存放运行中的数据和临时变量。

51单片机还包含特殊功能寄存器(SFR),用于控制IO端口、定时器计数器和串行通信等。

51单片机的工作原理基于冯诺伊曼体系结构,即程序指令和数据存储在同一块存储器中,通过总线系统进行传输。

51单片机实现基于DS1302_1602_18B20的多功能电子时钟_带测温功能

51单片机实现基于DS1302_1602_18B20的多功能电子时钟_带测温功能

#include<reg51.h>#define uchar unsigned char#define uint unsigned int/*------------------寄存器地址定义------------*/#define WRITE_SECOND 0x80#define WRITE_MINUTE 0x82#define WRITE_HOUR 0x84#define WRITE_DAY 0x86#define WRITE_MONTH 0x88#define WRITE_YEAR 0x8C#define WRITE_PROTECT 0x8E#define WRITE_WEEK 0x8A#define WRITE_CURRENT 0x90#define READ_SECOND 0x81#define READ_MINUTE 0x83#define READ_HOUR 0x85#define READ_DAY 0x87#define READ_MONTH 0x89#define READ_WEEK 0x8B#define READ_YEAR 0x8Dsbit RST=P3^5; //DS1302片选sbit DIO=P3^4; //DS1302数据信号sbit SCLK=P3^6; //DS1302时钟信号sbit ACC7=ACC^7;sbit ACC0=ACC^0;unsigned char count;sbit beep=P1^4;void INITIAL_1302();unsigned char READ_1302(unsigned char addr);void WRITE_1302(unsigned char addr,unsigned char date); sbit LCD_E=P2^7; //液晶使能端sbit LCD_RS=P2^6; //液晶数据命令选择端sbit LCD_RW=P2^5; //液晶读写选择端sbit key0=P3^2; //功能键sbit key1=P3^3; //增大键sbit key2=P3^4; //减小键sbit DQ=P3^7; //18b20温度输入输出端char hour,minute,second,week,day,month,year,tem; unsigned char num,flag;unsigned char str1[]=" 20 - - ";unsigned char str2[]=" : : C";void delay(unsigned char z);void LCD_WRITE_COM(unsigned char com);void LCD_WRITE_DA TA(unsigned char date);void LCD_WRITE_SFM(unsigned char addr,unsigned char date);void LCD_WRITE_NYR(unsigned char addr,unsigned char date);void LCD_WRITE_WEEK(unsigned char week);void LCD_INITIAL();void LCD_WRITE_TEMP(uchar addr,uchar temp);void keyscan();void INITIAL_TEMER0();uchar TMPH ,TMPL;void w1602c(uchar com);void w1602d(uchar data01);void delay2(uint ms);void delay3(uint us);uchar resert(void);uchar read_byte();void write_byte(uchar val);uint get_temp();void display();void delay3(uint us); //18b20uchar resert(void); //18b20uchar read_byte(); //18b20void write_byte(uchar val); //18b20uint get_temp(); //18b20void main(){LCD_INITIAL(); //液晶初始化INITIAL_1302(); //DS1302初始化INITIAL_TEMER0(); //定时器初始化while(1){keyscan(); //按键扫描if(flag==0) //当标志位为0,允许读取DS1302数据,将数据送入液晶显示{second=READ_1302(0x81);LCD_WRITE_SFM(10,second);minute=READ_1302(0x83);LCD_WRITE_SFM(7,minute);hour=READ_1302(0x85);LCD_WRITE_SFM(4,hour);week=READ_1302(0x8b);LCD_WRITE_WEEK(week);day=READ_1302(0x87);LCD_WRITE_NYR(9,day);month=READ_1302(0x89);LCD_WRITE_NYR(6,month);year=READ_1302(0x8d);LCD_WRITE_NYR(3,year);tem=get_temp();LCD_WRITE_TEMP(13,tem);}}}/**********************1602BU份******************************************************/void delay(unsigned char z) //1602de延时函数{unsigned char x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void LCD_WRITE_COM(unsigned char com){LCD_RS=0;LCD_RW=0;LCD_E=1;P0=com;delay(5);LCD_E=0;}void LCD_WRITE_DA TA(unsigned char date){LCD_RS=1;LCD_RW=0;LCD_E=1;P0=date;delay(5);LCD_E=0;}void LCD_WRITE_SFM(unsigned char addr,unsigned char date) {unsigned char shi,ge;shi=date/10;ge=date%10;LCD_WRITE_COM(0x80+0x40+addr);LCD_WRITE_DATA(0x30+shi);LCD_WRITE_DATA(0x30+ge);}void LCD_WRITE_NYR(unsigned char addr,unsigned char date) {char shi,ge;shi=date/10;ge=date%10;LCD_WRITE_COM(0x80+addr);LCD_WRITE_DATA(0x30+shi);LCD_WRITE_DATA(0x30+ge);}void LCD_WRITE_WEEK(unsigned char week){LCD_WRITE_COM(0x80+12);switch(week){case 1: LCD_WRITE_DA TA('M');delay(5);LCD_WRITE_DATA('O');delay(5);;LCD_WRITE_DATA('N');break;case 2: LCD_WRITE_DA TA('T');delay(5);LCD_WRITE_DATA('U');delay(5);LCD_WRITE_DATA('E');break;case 3: LCD_WRITE_DA TA('W');delay(5);LCD_WRITE_DATA('E');delay(5);LCD_WRITE_DATA('D');break;case 4: LCD_WRITE_DA TA('T');delay(5);LCD_WRITE_DATA('H');delay(5);LCD_WRITE_DATA('U');break;case 5: LCD_WRITE_DA TA('F');delay(5);LCD_WRITE_DATA('R');delay(5);LCD_WRITE_DATA('I');break;case 6: LCD_WRITE_DA TA('S');delay(5);LCD_WRITE_DATA('A');delay(5);LCD_WRITE_DATA('T');break;case 7: LCD_WRITE_DA TA('S');delay(5);LCD_WRITE_DATA('U');delay(5);LCD_WRITE_DATA('N');break;}}void LCD_WRITE_TEMP(uchar addr,uchar temp){char shi,ge;shi=temp/10;ge=temp%10;LCD_WRITE_COM(0x80+0x40+addr);LCD_WRITE_DATA(0x30+shi);LCD_WRITE_DATA(0x30+ge);}void LCD_INITIAL(){unsigned char i;LCD_WRITE_COM(0x38);LCD_WRITE_COM(0x0c);LCD_WRITE_COM(0x06); //经本人试验证明1602初始化不清屏也可实现LCD_WRITE_COM(0x80);for(i=0;i<16;i++){LCD_WRITE_DATA(str1[i]);delay(5);}LCD_WRITE_COM(0x80+0x40);//液晶第二行显示for(i=0;i<16;i++){LCD_WRITE_DATA(str2[i]);delay(5);}}/***************************1302部分***************************************************/void WRITE_1302(unsigned char addr,unsigned char date) {unsigned char i;RST=0;SCLK=0;RST=1;for(i=8;i>0;i--){SCLK=0;ACC=addr;DIO=ACC0;addr>>=1;SCLK=1;}for(i=8;i>0;i--){SCLK=0;ACC=date;DIO=ACC0;date>>=1;SCLK=1;}RST=0;}unsigned char READ_1302(unsigned char addr){unsigned char i,date1,date2;RST=0;SCLK=0;RST=1;for(i=8;i>0;i--){SCLK=0;ACC=addr;DIO=ACC0;addr>>=1;SCLK=1;}for(i=8;i>0;i--){ACC7=DIO;SCLK=1;ACC>>=1;SCLK=0;}RST=0;date1=ACC;date2=date1/16;date1=date1%16;date1=date1+date2*10;return(date1) ;}void INITIAL_1302(){WRITE_1302(WRITE_SECOND,READ_1302(READ_SECOND)&0x7f); //启动DS1302}/**************************键盘扫描部分***************************************************/void keyscan(){if(key0==0)//确认功能键按下{delay(20);if(key0==0)//去抖{while(!key0);//释放num++;switch(num){case 1: flag=1; //修改时间,禁止从DS1302读数据TR0=0; //定时器关LCD_WRITE_COM(0x0f); //光标开始闪烁LCD_WRITE_COM(0x80+3);//第一次按下,光标定位到年位置break;case 2: LCD_WRITE_COM(0x80+6);//第二次按下,光标定位到月位置break;case 3: LCD_WRITE_COM(0x80+9);//第三次按下,光标定位到日位置break;case 4: LCD_WRITE_COM(0x80+12);//第四次按下,光标定位到星期位置break;case 5: LCD_WRITE_COM(0x80+0x40+4);//第五次按下,光标定位到时位置break;case 6: LCD_WRITE_COM(0x80+0x40+7);//第六次按下,光标定位到分位置break;case 7: LCD_WRITE_COM(0x80+0x40+10);//第七次按下,光标定位到秒位置break;case 8: num=0;//第八次按下,记录清零LCD_WRITE_COM(0x0c);//不显示光标WRITE_1302(WRITE_PROTECT,0x00); //允许写操作WRITE_1302(0x80,(second/10*16)+second%10);//将调节后的秒写入DS1302WRITE_1302(0x82,(minute/10*16)+minute%10);//将调节后的分写入DS1302WRITE_1302(0x84,(hour/10*16)+hour%10);//将调节后的时写入DS1302WRITE_1302(0x8a,(week/10*16)+week%10);//将调节后的星期写入DS1302WRITE_1302(0x86,(day/10*16)+day%10);//将调节后的日写入DS1302WRITE_1302(0x88,(month/10*16)+month%10);//将调节后的月写入DS1302WRITE_1302(0x8c,(year/10*16)+year%10);//将调节后的年写入DS1302WRITE_1302(WRITE_PROTECT,0x80); //开写保护flag=0; //时间修改完毕,允许液晶从DS1302读数据TR0=1;break;}}}if(num!=0){if(key1==0)//确认增大键按下{delay(20);if(key1==0)//增大键确实按下{while(!key1);switch(num){case 1: year++;//调节年if(year==100)year=0;LCD_WRITE_NYR(3,year);//将调节后的年送入液晶显示LCD_WRITE_COM(0x80+3);//光标回到指定处break;case 2: month++;//调节月if(month==13)month=0;LCD_WRITE_NYR(6,month);//将调节后的月送入液晶显示LCD_WRITE_COM(0x80+6);//光标回到指定处break;case 3: day++;//调节日if(day==32)day=0;LCD_WRITE_NYR(9,day);//将调节后的日送入液晶显示LCD_WRITE_COM(0x80+9);//光标回到指定处break;case 4: week++;if(week==8)week=0;LCD_WRITE_WEEK(week);//将调节后的星期送入液晶显示LCD_WRITE_COM(0x80+12);//光标回到指定处break;case 5: hour++;if(hour==24)hour=0;LCD_WRITE_SFM(4,hour);//将调节后的小时送入液晶显示LCD_WRITE_COM(0x80+0x40+4);//光标回到指定处break;case 6: minute++;if(minute==60)minute=0;LCD_WRITE_SFM(7,minute);//将调节后的分送入液晶显示LCD_WRITE_COM(0x80+0x40+7);//光标回到指定处break;case 7: second++;if(second==60)second=0;LCD_WRITE_SFM(10,second);//将调节后的秒送入液晶显示LCD_WRITE_COM(0x80+0x40+10);//光标回到指定处break;default:break;}}}if(key2==0)//确认减小键按下{delay(20);if(key2==0)//减小键确实按下{while(!key2);switch(num){case 1: year--;//调节年if(year==-1)year=99;LCD_WRITE_NYR(3,year);LCD_WRITE_COM(0x80+3);break;case 2: month--;//调节月if(month==-1)month=12;LCD_WRITE_NYR(6,month);LCD_WRITE_COM(0x80+6);break;case 3: day--;//调节日if(day==-1)day=31;LCD_WRITE_NYR(9,day);LCD_WRITE_COM(0x80+9);break;case 4: week--;//调节星期if(week==0)week=7;LCD_WRITE_WEEK(week);LCD_WRITE_COM(0x80+12);break;case 5: hour--;//调节时if(hour==-1)hour=23;LCD_WRITE_SFM(4,hour);LCD_WRITE_COM(0x80+0x40+4);break;case 6: minute--;//调节分if(minute==-1)minute=59;LCD_WRITE_SFM(7,minute);LCD_WRITE_COM(0x80+0x40+7);break;case 7: second--;//调节秒if(second==-1)second=59;LCD_WRITE_SFM(10,second);LCD_WRITE_COM(0x80+0x40+10);break;default:break;}}}}}/*******************************蜂鸣器部分******************************************//*-----------定时器0初始化-------------------------*/void INITIAL_TEMER0(){TMOD=0x01;TH0=(65536-20000)/256;TL0=(65536-20000)%256; //晶振频率12MHZ 定时20ms作右TR0=1;EA=1;ET0=1;}/*-------------------------------------------*/void timer0()interrupt 1{TH0=(65536-20000)/256;TL0=(65536-20000)%256; //重装count++;if(count==50) //1秒到{count=0;beep=0; //蜂鸣器响delay(5);beep=1; //蜂鸣器灭}if(tem>=30){beep=0;}}/*****************************18b20部分*********************************************888*/void delay3(uint us){uint s;for(s=0;s<us;s++);}uchar resert(void){uchar ready;DQ=0;delay3(32) ;DQ=1;delay3(3);ready=DQ;delay3(25);return ready;}uchar read_byte(){uchar i,j;uchar value=0;for(i=0;i<8;i++){DQ=0;DQ=1;for(j=0;j<3;j++);if(DQ){value|=0x01<<i;}delay3(6) ;}return value;}void write_byte(uchar val) {uchar i,temp;for(i=0;i<8;i++){temp=val>>i;temp=temp&0x01;DQ=0;if(temp==1)DQ=1;delay3(5);DQ=1;}DQ=1;}uint get_temp(){float f_temp;uint temp;P2=0x00;resert();delay3(50);write_byte(0xcc);write_byte(0x44);resert();write_byte(0xcc);write_byte(0xbe);TMPL = read_byte();TMPH = read_byte();temp = TMPH;temp <<= 8;TMPL=TMPL&0xf0;temp = temp | TMPL;f_temp=temp*0.0625;temp=f_temp;return temp;}。

基于单片机的带温度显示的数字钟设计(c51语言编程)【开题报告】

基于单片机的带温度显示的数字钟设计(c51语言编程)【开题报告】

开题报告电气工程及其自动化基于单片机的带温度显示的数字钟设计(c51语言编程)一、课题研究意义及现状1980年因特尔公司推出了MCS-51单片机,近30年来,其衍生系列不断出现,从Atmel加入FLASH ROM,到philips加入各种外设,再到后来的Cygnal推出C8051F,使得以8051为核心的单片机在各个发展阶段的低端产品应用中始终扮演着一个重要的角色,其地位不断升高,资源越来越丰富,历经30年仍在生机勃勃地发展,甚至在SoC时代仍占有重要的一席之地。

单片机具有体积小、功能强、低功耗、可靠性高、价格低廉等一系列优点,不仅已成为工业测控领域智能仪表、机电一体化、实时控制、国防工业普遍采用的智能化控制工具,而且已渗入到人们工作和和生活的各个角落,有力地推动了各行业的技术改造和产品的更新换代,应用前景广阔。

C语言已经成为当前举世公认的高效简洁而又贴近硬件的编程语言之一。

将C语言向单片机8051上移植十余20世纪80年代的中后期,经过几十年的努力,C语言已成为专业化单片机上的实用高级语言。

C语言是一种编译型程序设计语言,它兼顾了多种高级语言的特点,并具备汇编语言的功能。

此外,C语言程序具有完善的模块程序结构,从而为软件开发中采用模块化程序设计方法提供了有力的保障。

与汇编语言相比,C51在功能、结构、可读性、可维护性上有明显的优势,因而易学易用。

另外C51可以缩短开发周期,降低成本,可靠性,可移植性好。

因此,使用C语言进行程序设计已成为软件开发的一个主流,用C语言进行8051单片机程序设计是单片机开发与应用的必然趋势。

随着人们生活水平的提高,对物质需求也越来越高,人们已不再满足于钟表原先简单的报时功能,希望出现一些新的功能,诸如环境温度显示、日历的显示、重要日期倒计时、显示跑表功能等,用以带来更大的方便。

而所有这些,又都是以数字化的电子时钟为基础的,不仅应用了数字电路技术,而且还加入了需要模拟电路技术和单片机技术。

51单片机课程设计(DS1302时钟、18B20温度计)

51单片机课程设计(DS1302时钟、18B20温度计)

摘要: 该设计实现了24小时制的时间显示及设定、年月日星期的显示及设定、闹钟的设定、温度的检测及显示等功能。

设计共分为四大部分,分别是控制部分、时钟部分、温度检测部分和人机交互部分。

以单片机(A T89C51)组成的最小系统为整个设计的控制核心,单片机通过对时钟芯片(DS1302)的控制完成时钟的功能,通过对温度传感器(18B20)的控制完成温度检测的功能,最后通过对数码管、蜂鸣器及按键的控制完成时间和温度的显示以及调整时间、设定闹钟等功能。

时间和温度的显示以及调整时间、设定闹钟等功能。

关键词:电子钟;温度计;单片机关键词:电子钟;温度计;单片机目录目录摘要: ......................................................................................................................1 第一章 设计任务设计任务设计任务 ...................................................................................................3 第二章 电路设计电路设计电路设计 ...................................................................................................3 2.1电路方案的比较 . (3)2.2根据设计绘制框图及原理图根据设计绘制框图及原理图.........................................................................5 第三章 工作原理工作原理工作原理 ...................................................................................................7 3.1 单片机的工作原理. (7)3.2 DS18B20的工作原理 (8)3.3DS1302的工作原理 (10)3.4数码管的工作原理 (12)第四章 调试与验证调试与验证 (12)4.1程序调试 (12)4.2仿真验证 (15)参考文献 (15)附录附录.....................................................................................................................16 附录一附录一 使用说明使用说明..............................................................................................16 附录二附录二 元件清单元件清单..............................................................................................16 附录三 pcb 版图版图...............................................................................................17 附录四附录四 程序清单程序清单 (18)第一章设计设计任务1、基本要求、基本要求)能够实现时间的正确显示,并且可以对表进行调整。

51单片机+ds1302+DS18b20温度时钟(电路图+C语言程序)

51单片机+ds1302+DS18b20温度时钟(电路图+C语言程序)

时钟电路图:*■11PCB板:酱时井務ft是用诵m-pdfMerisi 口叵因Fjr 齐舱 C :s ® 工细理沖缶皿ndm - * TfS ' 4' 包田U i > 'ir ft ZS:MZ fH钟些fl是用说町-Pdf Wirrcf闻礒雜sbit dis_ bitlsbit dis_ bit2sbit dis_ bit3sbit dis_ bit4sbit dis_ bit5sbit dis_ bit6sbit ledl _bitsbit led2 ! bit=P2A7; II定义数码管控制口=P2A6; II定义数码管控制口=卩2八4; II定义数码管控制口=卩2八3; II定义数码管控制口=P2A1; II定义数码管控制口=P2A0; II定义数码管控制口=P2A2; II定时LED勺控制口=P2A5; II定时LED勺控制口单片机程序:/*===================================================================调试要求:1. MCU:AT89S52 芯片或AT89C522. 晶振:12MHz功能:多功能时钟+温度计/#inelude <reg52. h>#inelude vintrins . h>訂开始 LJ-雲匕®务如1痒3月计ttVl. •呈T』d"吐拠席射■ w耳pg文宇■[豹…SS时軽件思冃说#define uehar #define uint unsigned char unsigned intsbit s1_bit =P1A 0; // 定义S1 控制口 sbit s2_bit =P01; // 定义 S2控制口 sbit s3_bit =P02; // 定义 S3控制口 sbit dq_ds18b20 =P3A3;// 定义控制 DS18B20 sbit speak =P3A7; //定义蜂鸣器控制口sbit clk_ds1302 =P3A6; // 定义控制 DS1302勺时钟线 sbit io_ds1302 =P3A5;//定义控制DS1302勺串行数据 sbit rest_ds1302 =P3A4;#define smg_data P0 //定义数码管数据口void delay_3us(); //3US 的延时程序 void delay_8us(ui nt t);//8US 延时基准程序void delay_50us(ui nt t); //void display1(uchar dis_data); void display2(uchar dis_data); void display3(uchar dis_data); void display4(uchar dis_data); void display5(uchar dis_data); void display6(uchar dis_data);void init_t0(); //定时器0初始化函数 void dis_led(); //LED 处理函数 void judge_s1(); //S1 按键处理函数void judge_s2(); //S2 按键处理函数 void judge_s3(); //S3 按键处理函数void dis(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1); 示子程序 void dis_sa n( uchar s6,uchar s5,uchar s4,uchar s3,uchar s1,uchar san); 〃闪烁显示子程序 void judge_dis(); //显示处理函数 void judge_clock(); // 显示处理函数 void set_ds1302(); // 设置时间void get_ds1302();// 读取当前时间void w_1byte_ds1302(uchar t); // 向 DS130写一个字节的数据 uchar r_1byte_ds1302(); // 从DS130读一个字节的数据//DS18B20测温函数定义延时50*T 微妙函数的声明//数码管1显示子程序 //数码管2显示子程序 //数码管3显示子程序 //数码管4显示子程序 //数码管5显示子程序 //数码管6显示子程序//显 s2,ucharvoid w_1byte_ds18b20(uchar value); // 向DS18B2写一个字节ucharr_1byte_ds18b20( void ); // 从DS18B2读取一个字节的数据voidrest_ds18b20( void ); //DS18B20复位程序void readtemp_ds18b20( void ); // 读取温度void dis_temp(); //温度显示函数//共阳数码管断码表const uchar tabl1[16] ={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,// 0 1 2 3 4 50x82,0xf8,0x80,0x90,0x86,0x87,0xFF,//6 7 8 9 E T B0xc6,0xbf,0xff };// C -const uchar tabl3[] ={ 0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09 };uchar t0_crycle;uchar hour_co un t, minu te_c oun t,sec on d_co un t,msec ond_count;uchar clock_hour,clock_m inu te;uchar coun tdow n_sec ond;uchar coun tdow n_hour,co un tdow n_min ute;uchar clock_en; //闹钟关闭和开启的标志,1开启,0关闭uchar flag1,sec on d_flag,za ncun 1,za ncun 2,za ncun3;uchar zancun4 ,za ncun 5,za ncun 6,za ncun7;uchar clock_flag,co un tdow n_flag;uchar msec on d_mi nute,msec on d_sec on d,mseco nd_mseco nd,mseco nd_flag; // 秒表相关参数uint speak_c ount;uchar templ,temph,temp_flag;uchar t_b,t_s,t_g,t_x,temp_flag2; //从左到右分别存储温度百位,十位,个位,小数位uchar tab23[3]; 〃二{0x40,0x59,0x23,0x28,0x11,0x06,0x09};// 上电时默认的时间//主程序void main(){P3 =0x00;flag1 =0;zancun3 =0;msecond_minute =0; //置秒表相关参数为0msecond_second =0;msec on d_msec ond =0;speak =1;//关闭蜂鸣器speak_co unt =0;clock_hour =0;clock_m inute =0;clock_flag =0;countdown_flag =0; //倒计时标志位为0clock_en =0;//开机时默认关闭闹钟ini t_t0();TRO =1;//// set_ds1302();〃设置DS1302勺初始时间//接下来开始编写让数码管显示的程序while (1){get_ds1302();judge_dis(); // 显示处理judge_s1();judge_s2();judge_s3();judge_clock(); //闹钟处理程序} _}void timerO() interrupt 1{TH0=(65536-50000)/256;TL0=(65536 - 50000)%256; t0_crycle ++;if (t0_crycle ==2) // 0.1 秒{t0_crycle =0;msec on d_flag =1;msec ond_count ++;if (msecond_count==10)//1 秒{ _msec on d_co unt =0;sec on d_flag =1;}}}//**************************************************//显示处理函数void judge_dis(){if (flag1 ==0){if (second_flag ==1){ _zancun7 ++;sec on d_flag =0;} _if (zancun7 <1){if (temp_flag2 ==1){ 一readtemp_ds18b20(); // 读取温度temp_flag2 =0;厂dis_temp(); //温度显示函数}if (zancun7 >=1){temp_flag2 =1;zancun4 =hour_count &0xf0;zancun4 >>=4;zancun5 =minute_count&0xf0;zancun5 >>=4;zancun6 =sec on d_co unt&0xf0;zancun6 >>=4;dis(za ncun4 ,hour_co unt &0x0f,za ncun5,minu te_co unt &0x0f,za ncun 6,sec ond_ cou nt &0x0f);dis_led();if (zancun7 ==5)zancun7 =0;}}if (flag1 !=0){switch (flag1){case 1:dis(5,10,11,1,12,12); // 显示SET1led1_bit =1;led2_bit =1;break;case 2:dis(5,10,11,2,12,12); // 显示SET2break;case 3:dis(5,10,11,3,12,12); // 显示SET3break;case 4:dis(5,10,11,4,12,12); // 显示SET4break;case 5:dis(5,10,11,5,12,12); // 显示SET5break;case 6:dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,12,1); break;case 7:dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,12,2); break;case 8:dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,12,3); break;case 9: //进入修改时间,时间分位个位闪烁dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,12,4); break;case 10: //进入修改闹钟,闹钟小时十位闪烁dis_san(zancunl / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,zancun3,1); break;case 11://进入修改闹钟,闹钟小时个位闪烁dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2%0,12,zancun3,2); break;case 12: //进入修改闹钟,闹钟小时十位闪烁dis_sa n(zan cu n1 / 10,za ncun1 %10,za ncun 2/ 10,za ncu n2%0,12,za ncun 3,3);break;case 13: //进入修改闹钟,闹钟小时个位闪烁dis_sa n(zan cu n1 / 10,za ncun1 %10,za ncun 2/ 10,za ncu n2%0,12,za ncun 3,4);break;case 14: //进入修改闹钟的开关dis_sa n(zan cu n1 / 10,za ncun1 %10,za ncun 2/ 10,za ncu n2%0,12,za ncun 3,6);break;case 15:dis_sa n(zancun1 / 10,za ncun1 %10,za ncun 2/ 10,za ncun 2%0,za ncun3/ 10,za ncun 3%10,1);break;case 16:dis_san(zancun1 / 10,zancunl %10,zancun2/10,zancun2%0,zancun3/ 10,zancun3%10,2);break;case 17:dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2%0,zancun3/ 10,zancun 3%10,3);break;case 18:dis_sa n(zancun1 / 10,za ncun1 %10,za ncun 2/ 10,za ncun 2%0,za ncun3/ 10,za ncun 3%10,4);break;case 19:dis_sa n(zancun1 / 10,za ncun1 %10,za ncun 2/ 10,za ncun 2%0,za ncun3/ 10,za ncun 3%10,5);break;case 20:dis_sa n(zancun1 / 10,za ncun1 %10,za ncun 2/ 10,za ncun 2%0,za ncun3/ 10,za ncun 3%10,6);break;case 21:if (second_flag ==1){ _sec on d_flag =0;countdown_second --;if (countdown_second ==255){ _coun tdow n_sec ond =59;countdown_minute --;if (countdown_minute ==255){ _coun tdow n_min ute =59;countdown_hour --;if (countdown_hour ==255){flag1 =22;coun tdow n_min ute =0;coun tdow n_hour =0;coun tdow n_sec ond =0;coun tdow n_flag=1;_ } } } }dis(countdown_hour / 10,countdown_hour %10,countdown_minute / 10,countdown _minute%10,countdown_second/ 10,countdown_second%10); //break; case 22:{ speak =1;}dis(countdown_hour / 10,countdown_hour %10,countdown_minute / 10,countdown _minute%10,countdown_second/ 10,countdown_second%10); //break; case 23: dis(msecond_minute / 10,msecond_minute%10,msecond_second/ 10,msecond_sec on d%10,mseco nd_msec on d%0,12);break; case 24:if (msecond_flag ==1) { _msec on d_flag =0; msec on d_msec ond ++;if (msecond_msecon (==10){msec on d_msec ond =0; msec on d_sec ond ++;if (msecond_second==60) { _msecond_second =0; msec ond_minute ++;if (countdown_flag { _speak=0;if (second_flag { _sec on d_flag coun tdow n_flag} _ } else>0 &&countdown_flag <7)==1) =0; ++;if (msecond_minute==1OO) { _msec ond_minute =99;flagl =23;}}}}dis(msecond_minute / 10,msecond_minute%10,msecond_second/ 10,msecond_sec on d%10,mseco nd_msec on d%0,12);break;case 25:dis(zancun3 / 10,zancun3 %0,zancun2 / 10,zancun2 %10,zancun1 /10,zancun1 %0 );break;default :break;}}}//**************************************************〃S1按键处理函数void judge_s1(){ _s1_bit =1;//置IO为1,准备读入收据if (s1_bit ==0)//判断是否有按键按下{delay_50us(1); //延时,去除机械抖动if (s1_bit ==0){switch (flag1){case 0:case 1:case 2:case 3:case 4:case 6:case 7:case 8:case 10:case 11:case 12:case 13:case 15:case 16:case 17:case 18:case 19: flag1++;break;case 9: flag1=6;break;case 14: flag1=10;break;case 20: flag1=15;break;case 5:case 21:case 22:case 23: //系统从秒表状态复位case 24: //系统从秒表状态复位case 25: //系统从计数器复位flag1 =0;break;default :break;}while (s1_bit ==0){ _judge_dis();}〃等待按键释放}}}〃************************************************** 〃S2按键处理函数void judge_s2(){ _s2_bit =1; //置IO为1,准备读入收据if (s2_bit ==0)//判断是否有按键按下=0;{delay_50us(1); //延时,去除机械抖动 if (s2_bit ==0) { switch (flagl) { flag1 =6; zancun4 =hour_count &0xf0;zancun4 >>=4; zancun6 =hour_count &0x0f;zancun1=zancun4*10+zancun6; //zancun 1=hour_co unt; zancun5 =minute_count &0xf0; zancun5 >>=4; zancun6 =minute_count &0x0f; zancun2 =za ncun5* 10+za ncun6; case 1: //在显示SET 状态下按S2牛,进入修改时间 // zancun2=minu te_co unt; break; case 2: //在显示SET2犬态下按S2,进入设置闹钟 zancunl =clock_hour; zancun2 =clock_m inu te; flagl =10; break; case 6: //修改时钟小时十位状态下按 case 7: //修改时钟小时个位状态下按 case 8: //修改时钟分钟十位状态下按 case 9: //修改时钟分钟个位状态下按 〃zancun4=za ncun 1/10; 测S:SM tab23[2] =zancun1/10* 16+za ncu n1%10; tab23[1] hour_c ount minu te_c ount sec ond_co unt tab23[0]set_ds1302(); flag1//zancun 5=za ncun2&0 xf0; //zancun 5>>=4; =zancun2/10* 16+za ncu n2%10; =tab23[2]; =tab23[1]; =0; //设置DS130的初始时间 =0;break; case 10: //修改闹钟小时十位状态下按S2case 11: //修改闹钟小时个位状态下按S2case 12: //修改闹钟分钟十位状态下按S2 case 13: //修改闹钟分钟个位状态下按S2 case 14: //修改闹钟使能状态下按S2clock_hour clock_m inute clock_e n flag1=zancun1; =zancun2; =zancun3;=0;break;case 3:flagl =15;zancunl =co un tdow n_hour;zancun2 =co un tdow n_minu te;zancun3 =co un tdow n_sec ond;break;case 15:case 16:case 17:case 18:case 19:case 20:coun tdow n_hour =zancun1;coun tdow n_minute =za ncun2;coun tdow n_sec ond =za ncun3;flag1 =21;coun tdow n_flag =0;break;case 22:flag1 =21;break;case 21:flag1 =22;break;case 4:flag1 =23; //秒表暂停msec ond_minute =0;msecond_second =0;msec on d_msec ond =0;break;case 23:flag1 =24;break;case 24:flag1 =23;break;case 5:flagl =25;//进入计数器模式zancunl =0;zancun2 =0;zancun3 =0;break; default :break;}while (s2_bit ==0){ _judge_dis();}//等待按键释放}}}//**************************************************//S3按键处理函数void judge_s3(){ _s3_bit =1;//置IO为1,准备读入收据if (s3_bit ==0)//判断是否有按键按下{delay_50us(1); //延时,去除机械抖动if (s3_bit ==0){ _switch (flag1){case 6: //修改时间小时的十位数zancun1 +=10;if (zancun1 >=24)zancun1 =zancun 1%10;break;case 7: //修改时间小时的个位数za ncun1 =za ncu n1/10* 10+(za ncun1 %10+1) %10;if (zancun1 >=24)zancun1 =20;break;case 8: //修改时间分钟的十位数zancun2 +=10;if (zancun2 >=60)zancun2-=60;break;case 9: //修改时间分钟的个位数za ncun2 =za ncun2/10* 10+(za ncun2 %10+1) %10;break;case 10: //修改闹钟小时的十位数zancunl +=10;if (zancunl >=24)zancunl =zancun 1%10; break;case 11: //修改闹钟小时的个位数zancunl =za ncu n1/10* 10+(za ncun1 %10+1) %10;if (zancun1 >=24)zancun1 =20;break;case 12: //修改闹钟分钟的十位数zancun2 +=10;if (zancun2 >=60)zancun2-=60; break;case 13: //修改闹钟分钟的个位数zan cu n2 =za ncun2/10* 10+(za ncun2 %10+1) %10;break;case 14:zancun3 A=1;break;case 15: //修改倒计时小时的十位数zancun1 +=10;if (zancun1 >=100)zancun 1 -=100; break;case 16: //修改倒计时小时的个位数zancun1 =za ncu n1/10* 10+(za ncun1 %10+1) %10;break;case 17: //修改倒计时分钟的十位数zancun2 +=10;if (zancun2 >=60)zancun2-=60; break;case 18: //修改倒计时分钟的个位数zan cu n2 =za ncun2/10* 10+(za ncun2 %10+1) %10;break;case 19: //修改倒计时秒的十位数zancun3 +=10;if (zancun3 >=60)zancun3-=60; break;case 20: //修改倒计时秒的个位数zan cu n3 =za ncun3/10* 10+(za ncun3 %10+1) %10;break;case 21:case 22: //coun tdow n_hour =zancun1;coun tdow n_minute =za ncun2;coun tdow n_sec ond =za ncun3;flagl =21;break;case 23:case 24: //秒表复位flag1 =24;msec ond_minute =0;msecond_second =0;msec on d_msec ond =0;break;case 25:zancun1 ++;if (zancun1 ==100){zancun1 =0;zancun2 ++;if (zancun2 ==100){zancun2 =0;zancun3 ++;}}break;default : break;}while (s3_bit ==0){ _judge_dis();}〃等待按键释放}}} //显示处理函数void judge_clock() {zancun4 =hour_count &0xf0;zancun4 >>=4;zancun6 =hour_count &0x0f;zancun4 *=10;zancun4 +=za ncun6;zancun5=minute_count &0xf0;if (san ==1){zancun5 >>=4;zancun6 =minute_count &0x0f;zancun5 *=10;zancun5 +=za ncun6;if (msecond_count<=5) {speak =0; speak_co unt ++;}else{speak =1;}}else{speak =1;}}〃****************************************////闪烁显示子程序void dis_sa n( uchar s6,uchar s5,uchar s4,uchar s3,uchars1,uchar san){if (clock_hour ==zancun4 &&clock_minute ==zancun5){ 一 一if (clock_en { _ speak_co unt clock_flag speak_co unt} _ } else{clock_flag =0;} _if{ (clock_flag ==1 ==1&&clock_flag ==0)=0; //开启蜂鸣器=1;=0;&&speak_count <400)s2,ucharif (msecond_count<5) { _ display1(s6);}}else{display1(s6);}if (san ==2){if (msecond_count<5) { _ display2(s5);}}else{display2(s5);}if (san ==3){if (msecond_count<5) { _ display3(s4);}}else{display3(s4);}if (san ==4){if (msecond_count<5) { _ display4(s3);}}else{display4(s3);}if (san ==5){if (msecond_count<5){ _ display5(s2);}}else{display5(s2);}if (san ==6){if (msecond_count<5){ _ display6(s1);}}else{ display6(s1);}}〃****************************************//时钟显示程序void dis(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1) { display1(s6);display2(s5);display3(s4);display4(s3);display5(s2);display6(s1);}〃********************************************************************************************void init_tO(){ _TMOD0x01;〃设定定时器工作方式1,定时器定时50毫秒TH0=(65536-50000)/256;TL0=(65536- 50000)%256;EA=1; //开总中断ET0=1; //允许定时器0中断t0_crycle =0; //定时器中断次数计数单元}//LED处理函数void dis_led(){if (msecond_count<5){ _Ied1_bit =1;Ied2_bit =1;}else{led1_bit =0;led2_bit =0;}}〃***************************************************************//功能:把数据1显示在数码管1上void display6(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit6 =0; // 锁存数据delay_50us(40); dis_bit6 =1;}〃***************************************************************//功能:把数据1显示在数码管1上void display5(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit5 =0; // 锁存数据delay_50us(40);dis_bit5 =1;} _〃***************************************************************//功能:把数据1显示在数码管1上void display4(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit4 =0; // 锁存数据delay_50us(40);dis_bit4 =1;} 〃***************************************************************//功能:把数据1显示在数码管1上void display3(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit3 =0; // 锁存数据delay_50us(40);dis_bit3 =1;}〃***************************************************************//功能:把数据1显示在数码管1上void display1(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit1 =0; // 锁存数据delay_50us(40);dis_bit1 =1;}〃***************************************************************//功能:把数据1显示在数码管1上void display2(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit2 =0; // 锁存数据delay_50us(40);dis_bit2 =1;}〃******************************************************************* *******************************// 函数名称:void delay_50US(unsigned int t)//功能:延时50*t(us)void delay_50us(uint t){ _unsigned char j;for (;t >0;t --){for (j =19;j >0;j --);}}〃******************************************************************* ************〃8微秒延时基准程序void delay_8us(uint t){while (-- t);}************〃3微秒延时程序void delay_3us() {}〃******************************************************************* ************//子程序功能:向DS18B2写一字节的数据void w_1byte_ds18b20(uchar value){uchar i =0;for (i =0;i <8;i ++){dq_ds18b20 =1;delay_3us();dq_ds18b20 =0; delay_8us(2);if ( value & 0x01) dq_ds18b20 =1; 〃DQ = 1 delay_50us(1); // 延时50us 以上delay_8us(2);value >>=1;}dq_ds18b20 =1; //DQ = 1}//读一个字节uchar r_1byte_ds18b20( void){ 一一uchar i =0;uchar value = 0;for (i =0;i <8;i ++){value >>=1;dq_ds18b20 =0;// DQ_L;delay_3us();dq_ds18b20 =1; 〃DQ_H;delay_8us(2);if (dq_ds18b20==1) value |= 0x80;delay_8us(6); // 延时40us}dq_ds18b20 =1;return value ;}11 ・**************************************************〃ds18b20复位子程序void rest_ds18b20( void){rest:delay_3us(); // 稍做延时delay_3us();dq_ds18b20 =1;delay_3us();dq_ds18b20 =0;// DQ_L; delay_50us(11); 〃480us<T<960usdq_ds18b20 =1; // 拉高总线delay_8us(5);if (dq_ds18b20==1){return ;}delay_50us(2); // 延时90usif (dq_ds18b20==1){return ;}else{goto rest;}}〃****************************************************//读取温度void readtemp_ds18b20( void){ _uchar temp32;rest_ds18b20();w_1byte_ds18b20(0xcc); //跳过读序列号的操作w_1byte_ds18b20(0x44); // 启动温度转换delay_8us(2);rest_ds18b20();w_1byte_ds18b20(0xcc); //跳过读序列号的操作w_1byte_ds18b20(0xbe); //读取温度寄存器等(共可读9个寄存器)前两个就是温度templ =r_1byte_ds18b20();temph =r_1byte_ds18b20();if ((temph &0xf0)) //判断温度的正负性{temp_flag =0; //温度为负数标志temph =-temph;tempi =-templ;t_x =tabl3[templ & OxOf]; // 计算温度的小数temp32 =temph & OxOf;temp32 <<=4;tempi >>=4;temp32 =temp32 | tempi;t_b =temp32/100%10; //计算温度的百位数据t_s =temp32/10%0;〃计算温度的十位数据t_g =temp32%0;〃计算温度的个位数据5else //为正数{t_x =tabl3[templ & 0x0f]; // 计算温度的小数temp32 =temph & 0x0f;temp32 <<=4;templ >>=4;temp32 =temp32 | templ;t_b =temp32/100%10; //计算温度的百位数据t_s =temp32/10%0;〃计算温度的十位数据t_g =temp32%0;〃计算温度的个位数据temp_flag =1;} _}void dis_temp() //温度显示函数{ _if (temp_flag =1){ _if (t_b ==0){dis(12,12,t_s,t_g,13,12);}else{dis(12,t_b,t_s,t_g,13,12);}}else{dis(14,t_b,t_s,t_g,13,12);}}/ / """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" / / , ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ############ //;子程序名:w_1byte_ds1302//;功能:向DS130写一个字节的数据void w_1byte_ds1302(uchar t){uchar i;for (i =0;i <8;i ++){if (t & 0x01){io_ds1302=1;}else{io_ds1302 =0;}clk_ds1302 =1;delay_3us();delay_3us();clk_ds1302 =0;delay_3us();delay_3us();t >>=1;}}/ / , ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ######//;子程序名:r_1byte_ds1302()//;功能:从DS130读一个字节的数据uchar r_1byte_ds1302(){ 一一uchar i,temp11 =0;io_ds1302 =1;//置10为1,准备读入数据for (i =0;i <8;i ++){temp11 >>=1;if (io_ds1302) temp11 |= 0x80;clk_ds1302 =1;delay_3us();delay_3us();clk_ds1302 =0;delay_3us();}return (temp11);}/ / """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""/ / , JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ """""""""""""""ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff//;子程序名:setbds1302//;功能:设置DS130初始时间,并启动计时void set_ds1302(){uchar i,j;rest_ds1302 =0;delay_3us();clk_ds1302 =0;delay_3us();rest_ds1302 =1;delay_3us();w_1byte_ds1302(0x8e); // 写控制命令字delay_3us();w_1byte_ds1302(0x00); // 写保护关闭clk_ds1302 =1;delay_3us();for (i =0,j =0x80;i <7;i ++,j +=2){rest_ds1302 =0;delay_3us();clk_ds1302 =0;delay_3us();rest_ds1302 =1;delay_3us();w_1byte_ds1302(j);delay_3us();w_1byte_ds1302(tab23[i]);delay_3us();delay_3us();clk_ds1302 =1;delay_3us();rest_ds1302 =0;delay_3us();delay_3us();} _rest_ds1302 =0;delay_3us();clk_ds1302 =0;delay_3us();rest_ds1302 =1;delay_3us();w_1byte_ds1302(0x8e); delay_3us();w_1byte_ds1302(0x80); clk_ds1302 =1;delay_3us();rest_ds1302 =0;delay_3us();}/ / """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" / / , ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff //;子程序名:get1302void get_ds1302(){ _uchar temp11[7],i,j;for (i =0;i <7;i ++){temp11[i] =0;}for (i =0,j =0x81;i <7;i ++,j +=2){rest_ds1302 =0;delay_3us();clk_ds1302 =0;delay_3us();delay_3us();w_1byte_ds1302(j);temp11[i] =r_1byte_ds1302();delay_3us();clk_ds1302 =1;delay_3us();rest_ds1302 =0;delay_3us();} _if (temp11[0] != 0xff){second_count =temp11[0]; }if (temp11[1] != 0xff) // 数据验证{minute_count =temp11[1]; }if (temp11[2] != 0xff) // 数据验证{hour_count =temp11[2]; }// date=temp[3];//mon th=temp[4];// week=temp[5];//year=temp[6];}/*===================================================================调试要求:1. MCU:AT89S52 芯片或AT89C522. 晶振:12MHz功能:多功能时钟+温度计/#inelude <reg52. h>#inelude vintrins . h>sbit dis_bit1 =P2A 7; //定义数码管控制口sbit dis_bit2 =卩2八6;//定义数码管控制口sbit dis_bit3 =卩2八4;//定义数码管控制口sbit dis_bit4 =卩2八3;//定义数码管控制口sbit dis_bit5 =卩2八1; //定义数码管控制口sbit dis_bit6 =P2A0; //定义数码管控制口sbit led1_bit =卩2八2; // 定时 LED 勺控制口sbit led2_bit =卩2八5; // 定时 LED 勺控制口sbit s1_bit =P1A0; // 定义S1 控制口sbit s2_bit =P01; // 定义 S2空制口sbit s3_bit =P02; // 定义 S3控制口sbit dq_ds18b20 =P3A3;// 定义控制 DS18B20 sbit speak =P3A7; //定义蜂鸣器控制口sbit clk_ds1302 =P3A6; // 定义控制 DS1302勺时钟线 sbit io_ds1302 =P3A5;//定义控制DS1302勺串行数据sbit rest_ds1302 =P3A4;#define smg_data P0 //定义数码管数据口 void delay_3us(); //3US 的延时程序 void delay_8us(ui nt t); //8US 延时基准程序void delay_50us(ui nt t); // void display1(uehardis_data); voiddisplay2(uehar dis_data); void display3(uehar dis_data); void display4(uehar dis_data); void display5(uehar dis_data); void display6(uehar dis_data);void init_t0(); //定时器0初始化函数void dis_led(); //LED 处理函数void judge_s1();//S1 按键处理函数 void judge_s2(); //S2 按键处理函数void judge_s3(); //S3 按键处理函数 void dis(uehar s6,uehar s5,uehar s4,uehar s3,uehar s2,uehar s1); 示子程序 void dis_sa n( uchar s6,uehar s5,uehar s4,uehar s3,uehars1,uchar san); 〃闪烁显示子程序void judge_dis(); //显示处理函数void judge_clock(); // 显示处理函数void set_ds1302(); // 设置时间void get_ds1302(); // 读取当前时间#define uehar#define uintunsigned char unsigned int延时50*T 微妙函数的声明//数码管1显示子程序 //数码管2显示子程序 //数码管3显示子程序//数码管4显示子程序//数码管5显示子程序//数码管6显示子程序 //显s2,ueharvoid w_1byte_ds1302(uchar t); // 向DS130写一个字节的数据uchar r_1byte_ds1302(); // 从DS130读一个字节的数据〃*******************************************************************//DS18B20测温函数定义void w_1byte_ds18b20(uchar value); // 向DS18B2写一个字节ucharr_1byte_ds18b20( void ); // 从DS18B2读取一个字节的数据voidrest_ds18b20( void ); //DS18B20复位程序void readtemp_ds18b20( void ); // 读取温度void dis_temp(); //温度显示函数//共阳数码管断码表const uchar tabl1[16] ={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,// 0 1 2 3 4 50x82,0xf8,0x80,0x90,0x86,0x87,0xFF,//6 7 8 9 E T B0xc6,0xbf,0xff };// C -const uchar tabl3[] ={ 0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09 };uchar t0_crycle;uchar hour_co un t, minu te_c oun t,sec on d_co un t,msec ond_count;uchar clock_hour,clock_m inu te;uchar coun tdow n_sec ond;uchar coun tdow n_hour,co un tdow n_min ute;uchar clock_en; //闹钟关闭和开启的标志,1开启,0关闭uchar flag1,sec on d_flag,za ncun 1,za ncun 2,za ncun3;uchar zancun4 ,za ncun 5,za ncun 6,za ncun7;uchar clock_flag,co un tdow n_flag;uchar msec on d_mi nute,msec on d_sec on d,mseco nd_mseco nd,mseco nd_flag; // 秒表相关参数uint speak_c ount;uchar templ,temph,temp_flag;uchar t_b,t_s,t_g,t_x,temp_flag2; //从左到右分别存储温度百位,十位,个位,小数位上电时默认的uchar tab23[3]; 〃二{0x40,0x59,0x23,0x28,0x11,0x06,0x09};//时间//主程序void main(){P3 =0x00;flag1 =0;zancun3 =0;msecond_minute =0; //置秒表相关参数为0msecond_second =0;msec on d_msec ond =0;speak =1;//关闭蜂鸣器speak_co unt =0;clock_hour =0;clock_m inute =0;clock_flag =0;countdown_flag =0; //倒计时标志位为0clock_en =0;//开机时默认关闭闹钟ini t_t0();TR0 =1;//// set_ds1302();〃设置DS130的初始时间//接下来开始编写让数码管显示的程序while (1){get_ds1302();judge_dis(); // 显示处理judge_s1();judge_s2();judge_s3();judge_clock(); //闹钟处理程序} _}void timer0() interrupt 1{TH0=(65536-50000)/256;TL0=(65536- 50000)%256;t0_crycle ++;if (t0_crycle ==2) // 0.1 秒{t0_crycle =0;msec on d_flag =1;msec ond_count ++;if (msecond_count==10)//1 秒。

基于51单片机的万年历与温度检测报警系统

基于51单片机的万年历与温度检测报警系统

基于51单片机的万年历与温度检测报警系统摘要随着社会发展需求的改变,电子万年历是一个应用非常广泛的实用日常计时工具,带有显示世纪,年,月,日,星期,时,分,秒和按键可调时间及其按键设置闹钟的功能,同时具有月末自动更新,闰年补偿功能等多种功能。

温度检测报警系统也是在日常生活和工业应用非常广泛的工具,能实时采集周围的温度信息进行显示,程序内部设定有报警上下限,根据应用环境不同可设定不同的报警上下限。

此系统是基于STC89C52单片机设计的,包含液晶显示模块,DS12C887实时时钟模块,DS18B20温度采集模块,键盘扫描模块,报警模块,HX1838红外接收头模块。

STC89C52作为控制核心,具有功耗低,功能强等特点,电压可选5VUSB 供电。

显示模块采用12864液晶动态显示,相对数码管而言经济实用,占用空间小,对于显示数字、字母最为合适,而且与单片机连线简单,占用IO口相对较少。

实时时钟芯片DS12C887是一款与DS12C885实时时钟兼容的替代产品,该器件提供RTC/日历、定时闹钟等功能,如果检测到主电源故障,该器件可自动切换到备用电源供电,DS12C887将石英晶体与电池集成在一起,在断电后仍可精确走10年。

温度检测报警模块采用数字式温度传感器DS18B20,该芯片具有精度高,测量范围广等优点,易与单片机连接,模块电路组成简单并同时具有温度报警功能。

关键词:STC89C52,DS12C887,DS18B20,12864液晶显示,电子万年历,采集周围设备温度、温度报警一、设计要求与方案论证1.1设计要求设计一个能够实现世纪,年,月,日,星期,小时,分,秒显示附带温度检测显示的实时时钟电子万年历,同时具有时间调节和闹钟设置功能,以及时间预设报警、温度报警、报警解除等功能。

该产品共设有四个按键,每个按键具有多种功能,充分利用各个按键。

也可利用红外遥控来进行实时调节,体现时尚方便的特性,并且通过编程还可以控制12864液晶显示,随心所欲。

51单片机+ds1302+DS18b20温度时钟(电路图+C语言程序)

51单片机+ds1302+DS18b20温度时钟(电路图+C语言程序)

时钟电路图:PCB板:单片机程序:/*=================================================================== =调试要求:1.MCU:AT89S52芯片或AT89C522.晶振:12MHz功能:多功能时钟+温度计====================================================================* /#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit dis_bit1=P2^7;//定义数码管控制口sbit dis_bit2=P2^6;//定义数码管控制口sbit dis_bit3=P2^4;//定义数码管控制口sbit dis_bit4=P2^3;//定义数码管控制口sbit dis_bit5=P2^1;//定义数码管控制口sbit dis_bit6=P2^0;//定义数码管控制口sbit led1_bit=P2^2;//定时LED的控制口sbit led2_bit=P2^5;//定时LED的控制口sbit s1_bit=P1^0; //定义S1控制口sbit s2_bit=P1^1; //定义S2控制口sbit s3_bit=P1^2; //定义S3控制口sbit dq_ds18b20=P3^3;//定义控制DS18B20sbit speak=P3^7; //定义蜂鸣器控制口sbit clk_ds1302=P3^6;//定义控制DS1302的时钟线sbit io_ds1302=P3^5;//定义控制DS1302的串行数据sbit rest_ds1302=P3^4;#define smg_data P0//定义数码管数据口void delay_3us();//3US的延时程序void delay_8us(uint t);//8US延时基准程序void delay_50us(uint t);//延时50*T微妙函数的声明void display1(uchar dis_data);//数码管1显示子程序void display2(uchar dis_data);//数码管2显示子程序void display3(uchar dis_data);//数码管3显示子程序void display4(uchar dis_data);//数码管4显示子程序void display5(uchar dis_data);//数码管5显示子程序void display6(uchar dis_data);//数码管6显示子程序void init_t0();//定时器0初始化函数void dis_led();//LED处理函数void judge_s1();//S1按键处理函数void judge_s2();//S2按键处理函数void judge_s3();//S3按键处理函数void dis(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1);//显示子程序void dis_san(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1,uchar san);//闪烁显示子程序void judge_dis();//显示处理函数void judge_clock();//显示处理函数void set_ds1302();//设置时间void get_ds1302();//读取当前时间void w_1byte_ds1302(uchar t);//向DS1302写一个字节的数据uchar r_1byte_ds1302();//从DS1302读一个字节的数据//******************************************************************* ****//DS18B20测温函数定义void w_1byte_ds18b20(uchar value);//向DS18B20写一个字节uchar r_1byte_ds18b20(void);//从DS18B20读取一个字节的数据void rest_ds18b20(void);//DS18B20复位程序void readtemp_ds18b20(void);//读取温度void dis_temp();//温度显示函数//共阳数码管断码表const uchar tabl1[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,// 0 1 2 3 4 50x82,0xf8,0x80,0x90,0x86,0x87,0xFF,//6 7 8 9 E T B0xc6,0xbf,0xff};// C -const uchar tabl3[]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07, 0x08,0x08,0x09,0x09};uchar t0_crycle;uchar hour_count,minute_count,second_count,msecond_count;uchar clock_hour,clock_minute;uchar countdown_second;uchar countdown_hour,countdown_minute;uchar clock_en;//闹钟关闭和开启的标志,1开启,0关闭uchar flag1,second_flag,zancun1,zancun2,zancun3;uchar zancun4,zancun5,zancun6,zancun7;uchar clock_flag,countdown_flag;uchar msecond_minute,msecond_second,msecond_msecond,msecond_flag;//秒表相关参数uint speak_count;uchar templ,temph,temp_flag;uchar t_b,t_s,t_g,t_x,temp_flag2;//从左到右分别存储温度百位,十位,个位,小数位uchar tab23[3];//={0x40,0x59,0x23,0x28,0x11,0x06,0x09};//上电时默认的时间//主程序void main(){P3=0x00;flag1=0;zancun3=0;msecond_minute=0;//置秒表相关参数为0msecond_second=0;msecond_msecond=0;speak=1;//关闭蜂鸣器speak_count=0;clock_hour=0;clock_minute=0;clock_flag=0;countdown_flag=0;//倒计时标志位为0clock_en=0;//开机时默认关闭闹钟init_t0();TR0=1;//// set_ds1302();//设置DS1302的初始时间//接下来开始编写让数码管显示的程序while(1){get_ds1302();judge_dis();//显示处理judge_s1();judge_s2();judge_s3();judge_clock();//闹钟处理程序}}void timer0() interrupt 1{TH0=(65536-50000)/256;TL0=(65536-50000)%256;t0_crycle++;if(t0_crycle==2)// 0.1秒{t0_crycle=0;msecond_flag=1;msecond_count++;if(msecond_count==10)//1秒{msecond_count=0;second_flag=1;}}}//************************************************** //显示处理函数void judge_dis(){if(flag1==0){if(second_flag==1){zancun7++;second_flag=0;}if(zancun7<1){if(temp_flag2==1){readtemp_ds18b20();//读取温度temp_flag2=0;}dis_temp();//温度显示函数}if(zancun7>=1){temp_flag2=1;zancun4=hour_count&0xf0;zancun4>>=4;zancun5=minute_count&0xf0;zancun5>>=4;zancun6=second_count&0xf0;zancun6>>=4;dis(zancun4,hour_count&0x0f,zancun5,minute_count&0x0f,zancun6,second_ count&0x0f);dis_led();if(zancun7==5)zancun7=0;}}if(flag1!=0){switch(flag1){case 1:dis(5,10,11,1,12,12);//显示SET1led1_bit=1;led2_bit=1;break;case 2:dis(5,10,11,2,12,12);//显示SET2break;case 3:dis(5,10,11,3,12,12);//显示SET3break;case 4:dis(5,10,11,4,12,12);//显示SET4break;dis(5,10,11,5,12,12);//显示SET5break;case 6:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,1);break;case 7:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,2);break;case 8:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,3);break;case 9://进入修改时间,时间分位个位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,4);break;case 10://进入修改闹钟,闹钟小时十位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,1);break;case 11://进入修改闹钟,闹钟小时个位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,2);break;case 12://进入修改闹钟,闹钟小时十位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,3);break;case 13://进入修改闹钟,闹钟小时个位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,4);break;case 14://进入修改闹钟的开关dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,6);break;case 15:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun 3%10,1);break;dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun 3%10,2);break;case 17:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun 3%10,3);break;case 18:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun 3%10,4);break;case 19:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun 3%10,5);break;case 20:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun 3%10,6);break;case 21:if(second_flag==1){second_flag=0;countdown_second--;if(countdown_second==255){countdown_second=59;countdown_minute--;if(countdown_minute==255){countdown_minute=59;countdown_hour--;if(countdown_hour==255){flag1=22;countdown_minute=0;countdown_hour=0;countdown_second=0;countdown_flag=1;}}}}dis(countdown_hour/10,countdown_hour%10,countdown_minute/10,countdown _minute%10,countdown_second/10,countdown_second%10);//break;case 22:if(countdown_flag>0 && countdown_flag<7){speak=0;if(second_flag==1){second_flag=0;countdown_flag++;}}else{speak=1;}dis(countdown_hour/10,countdown_hour%10,countdown_minute/10,countdown _minute%10,countdown_second/10,countdown_second%10);//break;case 23:dis(msecond_minute/10,msecond_minute%10,msecond_second/10,msecond_sec ond%10,msecond_msecond%10,12);break;case 24:if(msecond_flag==1){msecond_flag=0;msecond_msecond++;if(msecond_msecond==10){msecond_msecond=0;msecond_second++;if(msecond_second==60){msecond_second=0;msecond_minute++;if(msecond_minute==100){msecond_minute=99;flag1=23;}}}}dis(msecond_minute/10,msecond_minute%10,msecond_second/10,msecond_sec ond%10,msecond_msecond%10,12);break;case 25:dis(zancun3/10,zancun3%10,zancun2/10,zancun2%10,zancun1/10,zancun1%10 );break;default:break;}}}//**************************************************//S1按键处理函数void judge_s1(){s1_bit=1;//置IO为1,准备读入收据if(s1_bit==0)//判断是否有按键按下{delay_50us(1);// 延时,去除机械抖动if(s1_bit==0){switch(flag1){case 0:case 1:case 2:case 3:case 4:case 6:case 7:case 8:case 10:case 11:case 12:case 13:case 15:case 16:case 17:case 18:case 19:flag1++;break;case 9:flag1=6;break;case 14:flag1=10;break;case 20:flag1=15;break;case 5:case 21:case 22:case 23://系统从秒表状态复位case 24://系统从秒表状态复位case 25://系统从计数器复位flag1=0;break;default:break;}while(s1_bit==0){judge_dis();}//等待按键释放}}}//************************************************** //S2按键处理函数void judge_s2(){s2_bit=1;//置IO为1,准备读入收据if(s2_bit==0)//判断是否有按键按下{delay_50us(1);// 延时,去除机械抖动if(s2_bit==0){switch (flag1){case 1: //在显示SET1状态下按S2件,进入修改时间 flag1=6;zancun4=hour_count&0xf0;zancun4>>=4;zancun6=hour_count&0x0f;zancun1=zancun4*10+zancun6;//zancun1=hour_count;zancun5=minute_count&0xf0;zancun5>>=4;zancun6=minute_count&0x0f;zancun2=zancun5*10+zancun6;// zancun2=minute_count;break;case 2://在显示SET2状态下按S2,进入设置闹钟zancun1=clock_hour;zancun2=clock_minute;flag1=10;break;case 6://修改时钟小时十位状态下按S2件case 7://修改时钟小时个位状态下按S2件case 8://修改时钟分钟十位状态下按S2件case 9://修改时钟分钟个位状态下按S2件//zancun4=zancun1/10;tab23[2]=zancun1/10*16+zancun1%10;//zancun5=zancun2&0xf0;//zancun5>>=4;tab23[1]=zancun2/10*16+zancun2%10;hour_count=tab23[2];minute_count=tab23[1];second_count=0;tab23[0]=0;set_ds1302();//设置DS1302的初始时间flag1=0;break;case 10://修改闹钟小时十位状态下按S2case 11://修改闹钟小时个位状态下按S2case 12://修改闹钟分钟十位状态下按S2case 13://修改闹钟分钟个位状态下按S2case 14://修改闹钟使能状态下按S2clock_hour=zancun1;clock_minute=zancun2;clock_en=zancun3;flag1=0;break;case 3:flag1=15;zancun1=countdown_hour;zancun2=countdown_minute;zancun3=countdown_second;break;case 15:case 16:case 17:case 18:case 19:case 20:countdown_hour=zancun1;countdown_minute=zancun2;countdown_second=zancun3;flag1=21;countdown_flag=0;break;case 22:flag1=21;break;case 21:flag1=22;break;case 4:flag1=23;//秒表暂停msecond_minute=0;msecond_second=0;msecond_msecond=0;break;case 23:flag1=24;break;case 24:flag1=23;break;flag1=25;//进入计数器模式zancun1=0;zancun2=0;zancun3=0;break;default:break;}while(s2_bit==0){judge_dis();}//等待按键释放}}}//**************************************************//S3按键处理函数void judge_s3(){s3_bit=1;//置IO为1,准备读入收据if(s3_bit==0)//判断是否有按键按下{delay_50us(1);// 延时,去除机械抖动if(s3_bit==0){switch (flag1){case 6://修改时间小时的十位数zancun1+=10;if(zancun1>=24)zancun1=zancun1%10;break;case 7://修改时间小时的个位数zancun1=zancun1/10*10+(zancun1%10+1)%10;if(zancun1>=24)zancun1=20;break;case 8://修改时间分钟的十位数zancun2+=10;if(zancun2>=60)zancun2-=60;break;case 9://修改时间分钟的个位数zancun2=zancun2/10*10+(zancun2%10+1)%10;case 10://修改闹钟小时的十位数zancun1+=10;if(zancun1>=24)zancun1=zancun1%10;break;case 11://修改闹钟小时的个位数zancun1=zancun1/10*10+(zancun1%10+1)%10;if(zancun1>=24)zancun1=20;break;case 12://修改闹钟分钟的十位数zancun2+=10;if(zancun2>=60)zancun2-=60;break;case 13://修改闹钟分钟的个位数zancun2=zancun2/10*10+(zancun2%10+1)%10;break;case 14:zancun3^=1;break;case 15://修改倒计时小时的十位数zancun1+=10;if(zancun1>=100)zancun1-=100;break;case 16: //修改倒计时小时的个位数zancun1=zancun1/10*10+(zancun1%10+1)%10;break;case 17://修改倒计时分钟的十位数zancun2+=10;if(zancun2>=60)zancun2-=60;break;case 18: //修改倒计时分钟的个位数zancun2=zancun2/10*10+(zancun2%10+1)%10;break;case 19://修改倒计时秒的十位数zancun3+=10;if(zancun3>=60)zancun3-=60;break;case 20: //修改倒计时秒的个位数zancun3=zancun3/10*10+(zancun3%10+1)%10;break;case 21:case 22://countdown_hour=zancun1;countdown_minute=zancun2;countdown_second=zancun3; flag1=21;break;case 23:case 24://秒表复位flag1=24;msecond_minute=0;msecond_second=0;msecond_msecond=0;break;case 25:zancun1++;if(zancun1==100){zancun1=0;zancun2++;if(zancun2==100){zancun2=0;zancun3++;}}break;default:break;}while(s3_bit==0){judge_dis();}//等待按键释放}}}//**************************************** //显示处理函数void judge_clock(){zancun4=hour_count&0xf0;zancun4>>=4;zancun6=hour_count&0x0f;zancun4*=10;zancun4+=zancun6;zancun5=minute_count&0xf0;zancun5>>=4;zancun6=minute_count&0x0f;zancun5*=10;zancun5+=zancun6;if(clock_hour==zancun4 && clock_minute==zancun5){if(clock_en==1 && clock_flag==0){speak_count=0;//开启蜂鸣器clock_flag=1;speak_count=0;}}else{clock_flag=0;}if(clock_flag==1 && speak_count<400){if(msecond_count<=5){speak=0;speak_count++;}else{speak=1;}}else{speak=1;}}//****************************************////闪烁显示子程序void dis_san(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1,uchar san){if(san==1){{display1(s6);}}else{display1(s6);}if(san==2){if(msecond_count<5){display2(s5);}}else{display2(s5);}if(san==3){if(msecond_count<5){display3(s4);}}else{display3(s4);}if(san==4){if(msecond_count<5){display4(s3);}}else{display4(s3);}if(san==5){{display5(s2);}}else{display5(s2);}if(san==6){if(msecond_count<5){display6(s1);}}else{display6(s1);}}//****************************************//时钟显示程序void dis(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1) {display1(s6);display2(s5);display3(s4);display4(s3);display5(s2);display6(s1);}//******************************************************************* *************************void init_t0(){TMOD=0x01;//设定定时器工作方式1,定时器定时50毫秒TH0=(65536-50000)/256;TL0=(65536-50000)%256;EA=1;//开总中断ET0=1;//允许定时器0中断t0_crycle=0;//定时器中断次数计数单元}//**************************************************//LED处理函数void dis_led(){if(msecond_count<5){led1_bit=1;led2_bit=1;}else{led1_bit=0;led2_bit=0;}}//*************************************************************** //功能:把数据1显示在数码管1上void display6(uchar dis_data){smg_data=tabl1[dis_data];//送显示断码dis_bit6=0;//锁存数据delay_50us(40);dis_bit6=1;}//*************************************************************** //功能:把数据1显示在数码管1上void display5(uchar dis_data){smg_data=tabl1[dis_data];//送显示断码dis_bit5=0;//锁存数据delay_50us(40);dis_bit5=1;}//*************************************************************** //功能:把数据1显示在数码管1上void display4(uchar dis_data){smg_data=tabl1[dis_data];//送显示断码dis_bit4=0;//锁存数据delay_50us(40);dis_bit4=1;}//*************************************************************** //功能:把数据1显示在数码管1上void display3(uchar dis_data){smg_data=tabl1[dis_data];//送显示断码dis_bit3=0;//锁存数据delay_50us(40);dis_bit3=1;}//***************************************************************//功能:把数据1显示在数码管1上void display1(uchar dis_data){smg_data=tabl1[dis_data];//送显示断码dis_bit1=0;//锁存数据delay_50us(40);dis_bit1=1;}//***************************************************************//功能:把数据1显示在数码管1上void display2(uchar dis_data){smg_data=tabl1[dis_data];//送显示断码dis_bit2=0;//锁存数据delay_50us(40);dis_bit2=1;}//******************************************************************* *******************************//函数名称:void delay_50US(unsigned int t)//功能:延时50*t(us)void delay_50us(uint t){unsigned char j;for(;t>0;t--){for(j=19;j>0;j--);}}//******************************************************************* ************//8微秒延时基准程序void delay_8us(uint t){while(--t);}//******************************************************************* ************//3微秒延时程序void delay_3us(){;;}//******************************************************************* ************//子程序功能:向DS18B20写一字节的数据void w_1byte_ds18b20(uchar value){uchar i=0;for(i=0;i<8;i++){dq_ds18b20=1;delay_3us();dq_ds18b20=0;delay_8us(2);if (value& 0x01) dq_ds18b20=1; //DQ = 1delay_50us(1); //延时50us 以上delay_8us(2);value>>=1;}dq_ds18b20=1; //DQ = 1}//读一个字节uchar r_1byte_ds18b20(void){uchar i=0;uchar value= 0;for (i=0;i<8;i++){value>>=1;dq_ds18b20=0;// DQ_L;delay_3us();dq_ds18b20=1; //DQ_H;delay_8us(2);if(dq_ds18b20==1) value|=0x80;delay_8us(6); //延时40us}dq_ds18b20=1;return value;}//;**************************************************//ds18b20复位子程序void rest_ds18b20(void){rest:delay_3us(); //稍做延时delay_3us();dq_ds18b20=1;delay_3us();dq_ds18b20=0;// DQ_L;delay_50us(11);//480us<T<960usdq_ds18b20=1;//拉高总线delay_8us(5);if(dq_ds18b20==1){return;}delay_50us(2); //延时90usif(dq_ds18b20==1){return;}else{goto rest;}}//****************************************************//读取温度void readtemp_ds18b20(void){uchar temp32;rest_ds18b20();w_1byte_ds18b20(0xcc); //跳过读序列号的操作w_1byte_ds18b20(0x44); //启动温度转换delay_8us(2);rest_ds18b20();w_1byte_ds18b20(0xcc); //跳过读序列号的操作w_1byte_ds18b20(0xbe); //读取温度寄存器等(共可读9个寄存器)前两个就是温度templ=r_1byte_ds18b20();temph=r_1byte_ds18b20();if((temph&0xf0))//判断温度的正负性{temp_flag=0;//温度为负数标志temph=-temph;templ=-templ;t_x=tabl3[templ & 0x0f];//计算温度的小数temp32=temph & 0x0f;temp32<<=4;templ>>=4;temp32=temp32 | templ;t_b=temp32/100%10;//计算温度的百位数据t_s=temp32/10%10;//计算温度的十位数据t_g=temp32%10;//计算温度的个位数据}else//为正数{t_x=tabl3[templ & 0x0f];//计算温度的小数temp32=temph & 0x0f;temp32<<=4;templ>>=4;temp32=temp32 | templ;t_b=temp32/100%10;//计算温度的百位数据t_s=temp32/10%10;//计算温度的十位数据t_g=temp32%10;//计算温度的个位数据temp_flag=1;}}void dis_temp()//温度显示函数{if(temp_flag=1){if(t_b==0){dis(12,12,t_s,t_g,13,12);}else{dis(12,t_b,t_s,t_g,13,12);}}else{dis(14,t_b,t_s,t_g,13,12);}}//;################################################################## ############//;子程序名:w_1byte_ds1302//;功能:向DS1302写一个字节的数据void w_1byte_ds1302(uchar t){uchar i;for(i=0;i<8;i++){if(t & 0x01){io_ds1302=1;}else{io_ds1302=0;}clk_ds1302=1;delay_3us();delay_3us();clk_ds1302=0;delay_3us();delay_3us();t>>=1;}}//;################################################################## ######//;子程序名:r_1byte_ds1302()//;功能:从DS1302读一个字节的数据uchar r_1byte_ds1302(){uchar i,temp11=0;io_ds1302=1;//置IO为1,准备读入数据for(i=0;i<8;i++){temp11>>=1;if(io_ds1302) temp11 |= 0x80;clk_ds1302=1;delay_3us();delay_3us();clk_ds1302=0;delay_3us();}return(temp11);}//;################################################################## ###############//;子程序名:setbds1302//;功能:设置DS1302初始时间,并启动计时void set_ds1302(){uchar i,j;rest_ds1302=0;delay_3us();clk_ds1302=0;delay_3us();rest_ds1302=1;delay_3us();w_1byte_ds1302(0x8e);//写控制命令字 delay_3us();w_1byte_ds1302(0x00);//写保护关闭 clk_ds1302=1;delay_3us();rest_ds1302=0;for(i=0,j=0x80;i<7;i++,j+=2){rest_ds1302=0;delay_3us();clk_ds1302=0;delay_3us();rest_ds1302=1;delay_3us();w_1byte_ds1302(j);delay_3us();w_1byte_ds1302(tab23[i]);delay_3us();delay_3us();clk_ds1302=1;delay_3us();rest_ds1302=0;delay_3us();delay_3us();}rest_ds1302=0;delay_3us();clk_ds1302=0;delay_3us();rest_ds1302=1;delay_3us();w_1byte_ds1302(0x8e);delay_3us();w_1byte_ds1302(0x80);clk_ds1302=1;delay_3us();rest_ds1302=0;delay_3us();}//;#################################################################-------//;子程序名:get1302void get_ds1302(){uchar temp11[7],i,j;for(i=0;i<7;i++){temp11[i]=0;}for(i=0,j=0x81;i<7;i++,j+=2){rest_ds1302=0;delay_3us();clk_ds1302=0;delay_3us();rest_ds1302=1;delay_3us();w_1byte_ds1302(j);temp11[i]=r_1byte_ds1302();delay_3us();clk_ds1302=1;delay_3us();rest_ds1302=0;delay_3us();}if(temp11[0]!=0xff){second_count=temp11[0];}if(temp11[1]!=0xff)// 数据验证{minute_count=temp11[1];}if(temp11[2]!=0xff)//数据验证{hour_count=temp11[2];}// date=temp[3];//month=temp[4];// week=temp[5];//year=temp[6];}/*=================================================================== =调试要求:1.MCU:AT89S52芯片或AT89C522.晶振:12MHz功能:多功能时钟+温度计====================================================================* /#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit dis_bit1=P2^7;//定义数码管控制口sbit dis_bit2=P2^6;//定义数码管控制口sbit dis_bit3=P2^4;//定义数码管控制口sbit dis_bit4=P2^3;//定义数码管控制口sbit dis_bit5=P2^1;//定义数码管控制口sbit dis_bit6=P2^0;//定义数码管控制口sbit led1_bit=P2^2;//定时LED的控制口sbit led2_bit=P2^5;//定时LED的控制口sbit s1_bit=P1^0; //定义S1控制口sbit s2_bit=P1^1; //定义S2控制口sbit s3_bit=P1^2; //定义S3控制口sbit dq_ds18b20=P3^3;//定义控制DS18B20sbit speak=P3^7; //定义蜂鸣器控制口sbit clk_ds1302=P3^6;//定义控制DS1302的时钟线sbit io_ds1302=P3^5;//定义控制DS1302的串行数据sbit rest_ds1302=P3^4;#define smg_data P0//定义数码管数据口void delay_3us();//3US的延时程序void delay_8us(uint t);//8US延时基准程序void delay_50us(uint t);//延时50*T微妙函数的声明void display1(uchar dis_data);//数码管1显示子程序void display2(uchar dis_data);//数码管2显示子程序void display3(uchar dis_data);//数码管3显示子程序void display4(uchar dis_data);//数码管4显示子程序void display5(uchar dis_data);//数码管5显示子程序void display6(uchar dis_data);//数码管6显示子程序void init_t0();//定时器0初始化函数void dis_led();//LED处理函数void judge_s1();//S1按键处理函数void judge_s2();//S2按键处理函数void judge_s3();//S3按键处理函数void dis(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1);//显示子程序void dis_san(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchars1,uchar san);//闪烁显示子程序void judge_dis();//显示处理函数void judge_clock();//显示处理函数void set_ds1302();//设置时间void get_ds1302();//读取当前时间void w_1byte_ds1302(uchar t);//向DS1302写一个字节的数据uchar r_1byte_ds1302();//从DS1302读一个字节的数据//******************************************************************* ****//DS18B20测温函数定义void w_1byte_ds18b20(uchar value);//向DS18B20写一个字节uchar r_1byte_ds18b20(void);//从DS18B20读取一个字节的数据void rest_ds18b20(void);//DS18B20复位程序void readtemp_ds18b20(void);//读取温度void dis_temp();//温度显示函数//共阳数码管断码表const uchar tabl1[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,// 0 1 2 3 4 50x82,0xf8,0x80,0x90,0x86,0x87,0xFF,//6 7 8 9 E T B0xc6,0xbf,0xff};// C -const uchar tabl3[]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07, 0x08,0x08,0x09,0x09};uchar t0_crycle;uchar hour_count,minute_count,second_count,msecond_count;uchar clock_hour,clock_minute;uchar countdown_second;uchar countdown_hour,countdown_minute;uchar clock_en;//闹钟关闭和开启的标志,1开启,0关闭uchar flag1,second_flag,zancun1,zancun2,zancun3;uchar zancun4,zancun5,zancun6,zancun7;uchar clock_flag,countdown_flag;uchar msecond_minute,msecond_second,msecond_msecond,msecond_flag;//秒表相关参数uint speak_count;uchar templ,temph,temp_flag;uchar t_b,t_s,t_g,t_x,temp_flag2;//从左到右分别存储温度百位,十位,个位,小数位uchar tab23[3];//={0x40,0x59,0x23,0x28,0x11,0x06,0x09};//上电时默认的时间//主程序void main(){P3=0x00;flag1=0;zancun3=0;msecond_minute=0;//置秒表相关参数为0msecond_second=0;msecond_msecond=0;speak=1;//关闭蜂鸣器speak_count=0;clock_hour=0;clock_minute=0;clock_flag=0;countdown_flag=0;//倒计时标志位为0clock_en=0;//开机时默认关闭闹钟init_t0();TR0=1;//// set_ds1302();//设置DS1302的初始时间//接下来开始编写让数码管显示的程序while(1){get_ds1302();judge_dis();//显示处理judge_s1();judge_s2();judge_s3();judge_clock();//闹钟处理程序}}void timer0() interrupt 1{TH0=(65536-50000)/256;TL0=(65536-50000)%256;t0_crycle++;if(t0_crycle==2)// 0.1秒{t0_crycle=0;msecond_flag=1;msecond_count++;if(msecond_count==10)//1秒{msecond_count=0;second_flag=1;}}}//**************************************************//显示处理函数void judge_dis(){if(flag1==0){if(second_flag==1){zancun7++;second_flag=0;}if(zancun7<1){if(temp_flag2==1){readtemp_ds18b20();//读取温度temp_flag2=0;}dis_temp();//温度显示函数}if(zancun7>=1){temp_flag2=1;zancun4=hour_count&0xf0;zancun4>>=4;zancun5=minute_count&0xf0;zancun5>>=4;zancun6=second_count&0xf0;zancun6>>=4;dis(zancun4,hour_count&0x0f,zancun5,minute_count&0x0f,zancun6,second_ count&0x0f);dis_led();if(zancun7==5)zancun7=0;}}if(flag1!=0){switch(flag1){case 1:dis(5,10,11,1,12,12);//显示SET1led1_bit=1;led2_bit=1;break;case 2:dis(5,10,11,2,12,12);//显示SET2break;case 3:dis(5,10,11,3,12,12);//显示SET3break;case 4:dis(5,10,11,4,12,12);//显示SET4break;case 5:dis(5,10,11,5,12,12);//显示SET5break;case 6:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,1);break;case 7:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,2);break;case 8:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,3);break;case 9://进入修改时间,时间分位个位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,4);break;case 10://进入修改闹钟,闹钟小时十位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,1);break;case 11://进入修改闹钟,闹钟小时个位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,2);break;case 12://进入修改闹钟,闹钟小时十位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,3);break;case 13://进入修改闹钟,闹钟小时个位闪烁dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,4);break;case 14://进入修改闹钟的开关dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,6);break;case 15:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun 3%10,1);break;case 16:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun 3%10,2);break;case 17:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun 3%10,3);break;case 18:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun 3%10,4);break;case 19:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun 3%10,5);break;case 20:dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,zancun3/10,zancun 3%10,6);break;case 21:if(second_flag==1)。

基于51单片机的多功能电子钟的设计

基于51单片机的多功能电子钟的设计

B-1 多功能电子钟设计报告组员:彭希灵、冯旭鑫、张正鹏完成时间:2016年5月9日目录1.摘要 (4)2.设计任务 (4)2.1基本要求 (4)2.2发挥部分 (4)3.方案论证与比较 (5)3.1显示部分 (5)3.2时钟部分 (5)3.3闹铃部分 (6)3.4温度采集部分 (6)4.总体方案 (6)4.1工作原理 (6)4.2总体设计 (6)5.系统硬件设计 (7)5.1 STC89C51单片机最小系统 (7)5.2时钟模块 (8)5.3 LCD液晶显示模块 (9)5.4闹钟响铃模块 (10)5.5温度测量模块 (10)6.系统软件设计 (11)6.1 main模块 (11)6.2 ds1302模块 (11)6.3 lcd12864模块 (12)6.4 key模块 (12)6.5 ringlock模块 (13)6.6 menu模块和DS18B20模块 (13)7.测试与结果分析 (13)8.总结 (14)参考文献 (14)附录一 (15)附录二 (16)1.摘要本设计采用LCD12864液晶屏幕显示系统,以STC89C52单片机为核心,由铃声响铃模块、DS1302时钟控制模块、LCD12864显示模块、键盘控制模块、菜单模块和DS18B20温度模块等功能模块组成。

基于题目的基本要求,本系统对时间显示、闹钟的设定和控制以及时间日期的设定进行了重点设计。

此外,还扩展了掉电存储、红外遥控、温度采集等功能。

本系统大部分功能由软件来实现。

在该设计中不仅成功的实现了题中的基本要求,多数发挥部分也得到了实现,而且还具有一定的创新功能。

2.设计任务2.1基本要求(1)准确计时,以数字形式显示年月、日、时、分、秒。

(2)小时以24小时计时形式,分秒计时为60进位,日期平年和闰年将自行更换。

(3)采用矩阵按键和4个独立按键对电子表进行控制,可进行闹钟设定、控制及时间日期的设定。

(4)闹钟功能:可任意设定闹钟时间,一旦走时到该时间,能以蜂鸣器发声、LED发光的形式告警提示。

毕业设计论文—基于51单片机的温度报警电子时钟设计,附原程序

毕业设计论文—基于51单片机的温度报警电子时钟设计,附原程序

编号:审定成绩:重庆邮电大学毕业设计(论文)设计(论文)题目:基于51单片机的温度报警电子时钟的设计学院名称:自动化学院学生姓名:杨召专业:电气工程与自动化班级:0830905学号:2009212598指导教师:李锐答辩组负责人:填表时间:2013 年 5 月重庆邮电大学教务处制摘要基于单片机的定时和控制装置在许多行业有着广泛的应用,而电子时钟是其中最基本的,但带有温度报警的电子时钟却不多见。

在基于51单片机的温度报警电子时钟电路中,除了基本的单片机系统和外围电路外,还需要外部的控制和显示装置。

本电路主要以单片机AT89S52为核心而设计,通过单片机对信息的分析与处理,控制外围设备。

系统由复位模块、晶振模块、时钟模块、温度模块、测温模块、蜂鸣模块及显示模块共七个模块组成。

本设计以单片机AT89S52为切入点,通过使用AT89S52连接外接晶振的调节来确定一个合适的振荡周期,从而确定出内部的机器周期,通过单片机与DS1302的信息交互来设计出时钟程序,即设计出了电子时钟的核心。

然后在核心电路的基础上设计出了相应的扩展电路,使本设计更加实用。

本设计能够实现年月日和十分秒的正常显示和时间调节,也能根据需要设定闹铃,还能检测周围环境温度并送LCD1602显示,当环境温度超过设定的上限温度或者低于下限温度时蜂鸣器响起且警报灯闪烁。

【关键词】单片机1602LCD 温度检测DS1302ABSTRACTBased on single-chip timing and control device has been widely applied in many industries, and the electronic clock is one of the most basic electronic clock with temperature alarm is rare.51 microcontroller-based temperature alarm electronic clock circuit, in addition to the basic SCM system and the peripheral circuit, external control and display device. The circuit microcontroller AT89S52 as the core design, analysis and processing of information through the microcontroller to control peripheral devices. The system consists of the reset module, crystal module, clock module, module temperature, temperature measurement module, beep module and display module of seven modules.The design of single-chip AT89S52 as the starting point, through the using AT89S52 connection adjustment of the external crystal oscillator to determine an appropriate period of oscillation in order to determine the internal machine cycle design, information exchange through the MCU and the DS1302 clock program design the core of the electronic clock. Then out on the basis of the core circuit design corresponding to the expansion of the circuit, so that the design is more practical.This design can be achieved adjust the date and tenth of seconds the normal display and time, also need to set an alarm, can also detect ambient temperature and sent LCD1602 display, when the ambient temperature exceeds the set limit temperature or below the lower limit temperature when the buzzer sounds and the warning light is flashing.【Key words】Micro control unit LCD1602 Temperature detection DS1302目录前言 (1)第一章绪论 (3)第一节研究背景和意义 (3)第二节电子时钟的发展史 (4)一、电子时钟的发展史 (4)第三节单片机介绍 (4)一、单片机的发展 (4)二、单片机的组成及特点 (5)第四节本章小结 (6)第二章系统设计 (7)第一节方案设计与论证 (7)一、键盘方式论证 (7)二、显示方式论证 (7)三、计时方式论证 (7)四、测温方式论证 (8)第二节系统的硬件设计 (8)一、AT89S52简介 (9)2、AT89S52单片机硬件结构的特点 (11)二、显示部分电路的设计 (12)三、时钟模块设计 (17)四、温度电路 (19)五、蜂鸣电路 (20)六、复位模块 (21)七、按键模块 (21)第三节系统的软件设计 (22)一、系统程序框图 (22)二、各模块的子程序设计 (23)第四节本章小结 (29)第三章系统的仿真、制作与调试 (30)第一节Proteus仿真 (30)一、Proteus操作见面简介 (30)二、系统仿真电路原理图设计 (31)三、仿真结果 (32)第二节电路硬件焊接制作与调试 (34)一、电路焊接 (34)二、系统调试 (34)三、调试中遇到的问题及解决方法 (35)第三节本章小结 (38)结论 (39)致谢 (40)参考文献 (41)附录 (43)一、英文原文: (43)二、英文翻译: (54)三工程设计图纸: (63)四、源程序 (64)前言20世纪末,电子技术获得了非常快速的发展,现代电子产品几乎渗透到了社会的各个领域,家用电子就是其中之一。

基于51单片机的多功能电子时钟的设计

基于51单片机的多功能电子时钟的设计

基于51单片机的多功能电子时钟的设计Abstract:The design of a multi-functional electronic clock based on 51 single-chip microcontroller is presented in this paper. The clock is designed with the purpose of providing userswith accurate timekeeping, a variety of alarm clock settings, as well as other useful features such as temperature display and automatic daylight saving time adjustment. The clock employs a 4-digit LED display to show the clock time, and it is also equipped with buttons that facilitate easy programming and adjustment of its functions. The system operates on a 5V power supply and is designed to be compact and user-friendly.Introduction:Electronic clocks have become a ubiquitous feature in modern society, with nearly every household and workplace owning at least one. The accuracy and versatility of these clocks make them a highly useful tool for everyday life. However, with the rise of mobile devices, many people have begun to rely solely on their smartphones for timekeeping purposes. Despite this trend, there is still a demand for electronic clocks that provide additional features besides just timekeeping. This paper presents the design of a multi-functional electronic clock based on 51 single-chip microcontroller, which can cater to this demand.Design:The electronic clock was designed using a 51 single-chip microcontroller as the main control unit. This was chosen dueto its high processing power, low cost, and widespread availability. The clock was designed to be highly accurate, employing a real-time clock module to ensure precise timekeeping. The clock displays the time on a 4-digit LED display, with separate displays for hours, minutes and seconds. The display is of the common anode type, and its brightness can be adjusted using a potentiometer.The clock provides various alarm clock functions, including a snooze function and the ability to set multiple alarms. These functions are accessed using buttons on the clock, which make programming and adjustment easy. The clock also has a temperature display function, which uses a temperature sensor to provide accurate temperature readings. The display can show the temperature in either Celsius or Fahrenheit, depending on user preference. In addition, the clock has an automatic daylight saving time adjustment function, which adjusts the clock time automatically according to the user's location.Results:The electronic clock performed exceptionally well, accurately keeping time and providing all the functions as intended. The clock's design was compact and unobtrusive, making it suitable for both home and office use. The clock's ability to adjust for daylight saving time automatically was also highly appreciated by users, as it eliminated the need for manual adjustments several times a year.Conclusion:In conclusion, the design of a multi-functional electronic clock based on 51 single-chip microcontroller was presented in this paper. The clock proved to be highly accurate and versatile, offering a variety of usefulfunctions in addition to timekeeping. The compact and user-friendly design of the clock makes it suitable for a wide range of applications, including both home and office use. The clock's automatic daylight saving time adjustment function proved to be particularly useful, eliminating the need for manual adjustments.。

(整理)基于51单片机多功能电子时钟报告

(整理)基于51单片机多功能电子时钟报告

单片机课程设计报告多功能电子数字钟姓名:学号:班级:指导教师:目录一课程设计题目-------------------------------- 3 二电路设计--------------------------------------- 4 三程序总体设计思路概述------------------- 5 四各模块程序设计及流程图---------------- 6 五程序及程序说明见附录------------------- ** 六课程设计心得及体会---------------------- 11 七参考资料--------------------------------------- 12一题目及要求本次单片机课程设计在Proteus软件仿真平台下实现,完成电路设计连接,编程、调试,仿真出实验结果。

具体要如下:用8051单片机设计扩展6位数码管的静态或动态显示电路,再连接几个按键和一个蜂鸣器报警电路,设计出一个多功能电子钟,实现以下功能:(1)走时(能实现时分秒,年月日的计时)(2)显示(分屏切换显示时分秒和年月日,修改时能定位闪烁显示)(3)校时(能用按键修改和校准时钟)(4)定时报警(能定点报时)本次课程设计要求每个学生使用Proteus仿真软件独立设计制作出电路图、完成程序设计和系统仿真调试,验收时能操作演示。

最后验收检查结果,评定成绩分为:(1)完成“走时+显示+秒闪”功能----及格(2)完成“校时修改”功能----中等(3)完成“校时修改位闪”----良好(4)完成“定点报警”功能,且使用资源少----优秀二电路设计(电路设计图见附件电路图)(1)采用89C51型号单片机(2)采用8位共阴数码管(3)因为单片机输出高电平时输出的电流不足以驱动数码管,所以在P0口与8位数码管之间加74LS373来驱动数码管(4)P2口与数码管选择位直接加74LS138译码器(5)蜂鸣器接P3.7口。

基于AT89S51单片机的电子时钟(带温度显示)

基于AT89S51单片机的电子时钟(带温度显示)

基于A T89S51单片机的电子时钟(带温度显示)设计摘要:本设计以数字集成电路技术为基础,单片机技术为核心。

软件设计采用模块化结构,C语言编程。

系统通过LCD显示数据,可以显示日期(年、月、日、时、分、秒)以及温度。

在内容安排上首先描述系统硬件工作原理,着重介绍了各硬件接口技术和各个接口模块的功能;其次,详细的阐述了程序的各个模块和实现过程。

关键词:单片机;电子时钟;温度传感器;DS1302;DS18B20;LCD1602基于A T89S51单片机的电子时钟(带温度显示)设计摘要 .......................................................................................................................................................... 错误!未定义书签。

1 设计要求 (2)2 方案论证与设计 (2)2.1 用可编程逻辑器件设计 (2)2.1.1控制器部分 (3)2.2 显示部分的方案选择.............................................................................................................. 错误!未定义书签。

2.3 系统设计 ................................................................................................................................. 错误!未定义书签。

2.3.1 晶体振荡器电路………………………………………………………………………………..错误!未定义书签。

2.3.2 分频器电路………………………………………………………………………………..错误!未定义书签。

基于51单片机的电子时钟和温度测量

基于51单片机的电子时钟和温度测量

//延时 //复位置高
//Extended Function Set :8BIT 设置,RE=0: basic instruction
//大于 100uS 的延时程序 //Function Set
////大于 37uS 的延时程序 //Display on Control
TransferData('T',1);delay2(5); TransferData('U',1);delay2(5); TransferData('E',1); break;
TransferData('W',1);delay2(5); TransferData('E',1);delay2(5); TransferData('D',1); break;
b<<=8; t=a+b;
return(t); }
#ifndef _18B20_H #define _18B20_H
#include<reg52.h> #define uint unsigned int #define uchar unsigned char #include<math.h> #include<INTRINS.H>
//uint temp;
//uchar flag_get,count,num,minute,second;
/******************************************************************/
/*
函数声明
*/
/******************************************************************/

基于51单片机的多功能电子时钟设计

基于51单片机的多功能电子时钟设计

设计研发2021.07基于51单片机的多功能电子时钟设计杨洁,叶晶晶(黔南民族师范学院物理与电子科学学院,贵州都匀,558000 )摘要:单片机体积小、重量轻、抗干扰能力强、环境要求不高、价格低廉、可靠性高、灵活性好、深受初学者喜欢。

以STC90C58为核心控制芯片,DS1302为时钟芯片,DS18B20釆集温度,完成多功能电子时钟的设计。

该设计能够准确显示年、月、日、星期、时、分、秒及温度,通过按键可以调整年、月、日、星期、时、分、秒、12/24小时转换、整点提示以及闹钟,还可显示阴阳历。

关键词:电子时钟;单片机;阴阳历转换;DS1302 ; DS18B20Design of Multi-function Clock Based on 51 MCUYang Jie, Ye Jingjing(College of physics and electronic science, Qiannan Normal University for N&tionalities, DuyunGuizhou, 558000)Abstract : MCU is small in size, light in weight, strong in anti-interference ability, low in environmentai requirements, low in price, high in reliability, good in flexibility, and is popular among beginners. Stc90c58 as the core control chip, DS1302 as the clock chip, DS18B20 temperature acquisition, complete the design of multi —functional electronic clock. The design can accurately display the year, month, day, week, hour, minute, second and temperatore. Through the button, you can adjust the year, month, day, week, hour, minute, second, 12/24-hour conversion, whole point prompt and alarm clock, and display the lunar calendar.Keywords : Electronic clock ; MCU ; The lunar conversion ; DS 1302 ; DS18B200引言目前单片机的使用已经十分广泛,本次设计的多功能电 子钟能完成年、月、日、星期、时、分、秒的显示与调整,并且还 添加了温度、阴阳历转换显示及闹钟、12/24小时转换、整点提示等功能,有较强的应用性。

基于51单片机的电子时钟设计

基于51单片机的电子时钟设计

基于51单片机的电子时钟设计
电子时钟是一种使用电子元件和计算机技术制造的时计,它可以显示年、月、日、时、分、秒等时间信息,并且具有显示精确、功能齐全、操
作简便等特点。

本文将基于51单片机设计一个电子时钟。

一、硬件设计:
1.时钟模块:我们可以使用DS1302时钟模块作为实时时钟芯片,它
可以提供精确的时间信息,并且可以通过单片机与之进行通信。

2.显示模块:我们可以使用共阳数码管进行时间的显示,将时钟设计
成6位7段显示器。

3.按键模块:我们可以使用按键作为输入方式,通过按键调整时间信息。

二、软件设计:
1.初始化:首先,我们需要初始化时钟模块和显示模块,使它们正常
工作。

同时,设置时钟的初始时间为系统当前时间。

2.获取时间:通过与时钟模块的通信,获取当前的时间信息,包括年、月、日、时、分、秒等。

3.显示时间:将获取到的时间信息通过显示模块显示出来,分别显示
在6个数码管上。

4.时间调整:通过按键模块的输入,判断用户是否需要调整时间。


果需要,可以通过按键的不同组合来调整时、分、秒等时间信息。

5.刷新显示:通过不断更新显示模块的输入信号来实现时钟的流动性,保持秒针不断运动的效果。

6.时间保存:为了保证时钟断电后依然能够保持时间,我们需要将时
钟模块获取到的时间信息保存在特定的EEPROM中。

7.闹钟功能:可以通过按键设置闹钟,当到达闹钟时间时,会通过蜂
鸣器发出响声。

以上就是基于51单片机的电子时钟设计方案。

通过对硬件和软件的
综合设计,我们可以实现一个功能齐全的电子时钟。

基于单片机的带温度显示的数字钟设计(c51语言编程)

基于单片机的带温度显示的数字钟设计(c51语言编程)

基于单片机的带温度显示的数字钟设计(c51语言编程)开题报告电气工程及其自动化一、课题研究意义及现状1980年因特尔公司推出了MCS-51单片机,近30年来,其衍生系列不断出现,从Atmel加入FLASH ROM,到philips加入各种外设,再到后来的Cygnal推出C8051F,使得以8051为核心的单片机在各个发展阶段的低端产品应用中始终扮演着一个重要的角色,其地位不断升高,资源越来越丰富,历经30年仍在生机勃勃地发展,甚至在SoC时代仍占有重要的一席之地。

单片机具有体积小、功能强、低功耗、可靠性高、价格低廉等一系列优点,不仅已成为工业测控领域智能仪表、机电一体化、实时控制、国防工业普遍采用的智能化控制工具,而且已渗入到人们工作和和生活的各个角落,有力地推动了各行业的技术改造和产品的更新换代,应用前景广阔。

C语言已经成为当前举世公认的高效简洁而又贴近硬件的编程语言之一、将C语言向单片机8051上移植十余20世纪80年代的中后期,经过几十年的努力,C语言已成为专业化单片机上的实用高级语言。

C语言是一种编译型程序设计语言,它兼顾了多种高级语言的特点,并具备汇编语言的功能。

此外,C语言程序具有完善的模块程序结构,从而为软件开发中采用模块化程序设计方法提供了有力的保障。

与汇编语言相比,C51在功能、结构、可读性、可维护性上有明显的优势,因而易学易用。

另外C51可以缩短开发周期,降低成本,可靠性,可移植性好。

因此,使用C语言进行程序设计已成为软件开发的一个主流,用C语言进行8051单片机程序设计是单片机开发与应用的必然趋势。

随着人们生活水平的提高,对物质需求也越来越高,人们已不再满足于钟表原先简单的报时功能,希望出现一些新的功能,诸如环境温度显示、日历的显示、重要日期倒计时、显示跑表功能等,用以带来更大的方便。

而所有这些,又都是以数字化的电子时钟为基础的,不仅应用了数字电路技术,而且还加入了需要模拟电路技术和单片机技术。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

、职业技能训练之电子技术课程设计报告学院电子与信息学院设计题目基于51单片机设计的带有测温功能的电子时钟班级XXX姓名XXX学号XXX指导教师XXX时间2012年06月25日目录一、设计要求二、课程设计的方案、目的及意义三、硬件设计方案四、软件设计方案五、总结六、参考资料一、设计要求用51单片机设计带温度显示的电子时钟,具体要求如下:1、利用DS1302时钟芯片实现时钟功能模块。

2、时钟要求可以调节时间:年、月、日、时、分、秒。

3、利用LCD1602显示。

4、利用DS18B20芯片实现温度功能模块。

5、利用按键完成各项功能。

二、课程设计方案、目的及意义1、总体方案:用STC89C51单片机作为CPU主控制器,DS1302时钟芯片提供准确时钟信号,DS18B20温度传感器采集温度信息,三个按键进行加减调整、功能切换作用,通过LCD1602对外多功能显示。

2、具体方案:CPU控制所有模块,通过循环反复从DS1302中读取时钟信息,传送至LCD1602显示,得到基本时钟功能。

当分为59,秒为56时开始,每隔一秒LED 灯点亮240毫秒,0分0秒时LED灯点亮700毫秒。

从而实现整点光报时。

定时循环从DS18B20中读取温度信息,传送至LCD1602显示,得到基本温度计功能。

当温度高于30度(包括30度)时,点亮红色LED灯,提醒当天为高温天气。

低于0度时,点亮蓝色LED灯,提醒当天为冰冻天气。

键盘使用扫面方式,MENU键控制功能切换,完成时钟和温度间的转换。

OK键控制时间调整与确定,UP、DOWN键调节时间,R、L 键选择调整对象。

进入调整时,暂停DS1302数据读取,并将改变的时间数据写入DS1302,并送LCD1602显示,同时,启动LCD1602光标闪烁,确定调整对象,完成人机对话。

退出调整时,停止写入数据,重新读取DS1302时钟信息。

从而完善时钟功能。

3、目的及意义可作为产品生产,作为居家的时钟显示与温度计。

三、硬件设计方案1、原理图2、PCB图3、各功能模块分析(一)、主控制器:STC单片机89C51功能:程序存储器16K、RAM数字存储器1280、可直接通过串口下载程序,单一+5V电源供电,五个中断源的中断控制系统,片内振荡器和时钟产生电路,石英晶体和微调电容需要外接。

CPU:由运算和控制逻辑组成,同时还包括中断系统和部分外部特殊功能寄存器。

RAM:用以存放可以读写的数据,如运算的中间结果、最终结果以及欲显示的数据。

ROM:用以存放程序、一些原始数据和表格。

I/O口:四个8位并行I/O口,既可用作输入,也可用作输出。

P0口做I/O 口需接上拉电阻。

T/C:两个定时/记数器,既可以工作在定时模式,也可以工作在记数模式。

(二)、LCD1602显示模块介绍:工业字符型液晶,能够同时显示16x02即32个字符(16列2行)。

管脚信息:显示模式设置:显示开关及功能设置:数据指针设置:写时序:注:R3调节显示屏对比度(三)、DS1302时钟芯片管脚信息:VCC:Vcc1为后备电源,VCC2为主电源。

在主电源关闭的情况下,也能保持时钟的连续运行。

DS1302由Vcc1或Vcc2两者中的较大者供电。

当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。

当Vcc2小于Vcc1时,DS1302由Vcc1供电。

X1、X2:X1和X2是振荡源,外接32.768kHz晶振。

RST:RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。

RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。

当RST 为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。

如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。

上电运行时,在Vcc>2.0V之前,RST必须保持低电平。

只有在SCLK为低电平时,才能将RST置为高电平。

I/O为串行数据输入输出端(双向),后面有详细说明。

SCLK:SCLK为时钟输入端。

日历寄存器:注:(1):小时寄存器的位7用于定义DS1302是运行于12小时模式还是24小时模式。

当为高时,选择12小时模式。

在12小时模式下,位5为低时为AM,高时为PM。

在24小时模式下,位5是第二个10小时位。

(2)、秒寄存器的位7定义为时钟暂停标志。

当该位置为1时,时钟振荡器停止,DS1302处于低功耗状态;该位置0是,时钟开始运行。

(3)、控制寄存器的位7是写保护位,其他7位均置为0。

在任何的对时钟和RAM的写操作之前,WP位必须为0。

当WP位1时,写保护位防止对任一寄存器的写操作。

控制字节:注:控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。

数据读写及时序:在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。

同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。

(四)、DS18B20温度传感器管脚信息:GND:接地DQ:数据I/OVDD:电源存储器:控制字节:Skip ROM [CCh]:允许总线控制器不用提供64 位ROM 编码就使用存储器操作命令,在单点总线情况下右以节省时间。

Convert T[44h]:开始温度转换。

Read Scratchpad[BEh]:读取暂存器和CRC 字节,知道9字节时序:读时间隙:当从DS12B20读取数据时,主机生成读时间隙。

当主机把数据线从逻辑高电平拉到逻辑低电平的时候,写时间隙开始。

数据线必须保持至少1μs,从DS18B20 输出的数据在读时间隙的下降沿出现后15μs 内有效。

因此,主机在读时间隙开始后必须停止把I/O 脚驱动为低电平15μs,以读取I/O 脚状态。

在读时间隙的结尾,I/O 引脚将被外部上拉电阻拉到高电平。

所有读时间隙必须最少60μs,包括两个读周期间至少1μs的恢复时间。

写时间隙:当主机把数据线从逻辑高电平拉到逻辑低电平的时候,写时间隙开始。

所有写时间隙必须最少持续60μs,包括两个写周期间至少1μs 的恢复时间。

I/O 线电平变低后,DS18B20 在一个15μs 到60μs 的窗口内对I/O 线采样。

如果线上是高电平,就是写1,如果线上是低电平,就是写0。

主机要生成一个写时间隙,必须把数据线拉到低电平然后释放,在写时间隙开始后的15μs 内允许数据线拉到高电平。

主机要生成一个写0 时间隙,必须把数据线拉到低电平并保持60μs。

(六)、按键部分原理:键盘扫描,先将P3.6口置零,此时扫描S5~S8,如果P3.0~P3.3中有为0,则说明有对应键按下。

然后将P3.7口置零,此时扫描S1~S4,如果P3.0~P3.3中有为0,则说明有对应键按下。

四、软件设计方案部分程序代码(一)主程序:#include<reg52.h>#include"lcd1602.h" //包含头文件,直接引用显示文件#include"ds18b20.h"#include "DS1302.h"#define uchar unsigned char#define uint unsigned int#define TIMER0_COUNT 0xEE11sbit mode=P3^0; //设定修改位数sbit plus=P3^1; //加键sbit dec=P3^2; //减键uchar count,s1num,timer0_tick,count=0;typedef struct{char hour;char minute;char second;}time;typedef struct{uint year;char month;char day;}date;time now={11,20,7}; //显示时间初始值date today={12,6,16};char code dayofmonth[]={31,28,31,30,31,30,31,31,30,31,30,31}; //设定月份数组,用以判定12个月的最大值char code weekday[7][10]={"Week1 ","Week2 ","Week3 ","Week4 ","Week5 ","Week6 ","Week7 "}; //设定行星期显示数uchar monthday(uchar year,uchar month){if(month==2 && year%4==0) //用以判定是否为润年,其2月有29天return(29);elsereturn(28); //非闰年时的该月份天数28}void display_week() //由年月日计算星期,用以显示星期数{char days;days=(today.day+1+2*today.month+3*(today.month+1)/5+today.year+today.year/4-to day.year/100+today.year/400)%7;display_string(&weekday[days][0]);}static void timer0_initialize(void) //timer0 initialize{EA=0; //设置不接受所有中断timer0_tick=0;TR0=0; //关闭Timer0TMOD=0X01; //设置Timer0为模式2,16位工作模式TL0=(TIMER0_COUNT & 0X00FF); //设置Timer0低八位数值TH0=(TIMER0_COUNT >> 8); //设置Timer0高八位数值PT1=1; //设置Timer0的优先级为最高ET0=1; //设置接受Timer0的中断TR0=1; //启动Timer0EA=1; //设置系统接受中断}void write_time(uchar add,uchar number) //写时间{gotoxy(2,add);display_data(number);}void write_riqi(uchar add,uchar number) //写日期{gotoxy(1,add);display_data(number);}void keyscan() //按键扫描程序{uchar mode_num; //设定mode_num,来判断是哪一位要修改,当mode_num为零时,为非修改模式if(mode==0) //"修改位"的选择{delay(5); //延时if(mode==0) //当外部按键mode没按下一次时,都使mode_num自加,即mode_num表示为按键mode按下的次数{ mode_num++;while(!mode);TR0=0;write_com(0x0f);}if(mode_num==1) gotoxy(1,1); //当mode_num为1时,为年份改变位,光标移到(1,2)if(mode_num==2) gotoxy(1,4); //当mode_num为2时,为月份改变位,光标移到(1,5)if(mode_num==3) gotoxy(1,7); //当mode_num为3时,为日期改变位,光标移到(1,8)if(mode_num==4) gotoxy(2,1); //当mode_num为4时,为小时改变位,光标移到(2,2)if(mode_num==5) gotoxy(2,4); //当mode_num为5时,为分钟改变位,光标移到(2,5)if(mode_num==6) gotoxy(2,7); //当mode_num为6时,为秒数改变位,光标移到(2,8)if(mode_num==7) //当mode_num为7时,退出修改模式{mode_num=0; //非修改模式时,将mode_num置零,有助于判断是否为修改模式write_com(0x0c);TR0=1;}}if(mode_num!=0) //为修改模式时,加减键的处理子程序{if(plus==0) //当加键为零,即外部触发一次时,进行以下处理{delay(5); //延时if(plus==0) //延时再次判断加键,防止抖动{if(mode_num==1) //当为年份改变时,年份自加一,并且显示修改后的日期{today.year++;write_riqi(1,today.year); //因为年份主要是最后两位在改变,所以除以100来计算年份值,除以100求得的商值为十位gotoxy(1,14);display_week(); //因为改变日期都会改变周数,所以要重新显示}if(mode_num==2) //以下处理同上{today.month++;if(today.month==13) today.month=1; //特别注意,月份不能超过12,当为13时,要将月份置1write_riqi(4,today.month); //除以10来计算月份值,除以10求得的商值为十位gotoxy(1,14);display_week();}if(mode_num==3) //以下处理同上{today.day++;if(today.day>monthday(today.year,today.month)) //特别要判断每个月份的最大值,不能超过此数,超过后要将天数置一today.day=1;write_riqi(7,today.day); //除以10来计算月份值,除以10求得的商值为十位gotoxy(1,14);display_week();}if(mode_num==4) //以下处理同上{now.hour++;if(now.hour==24) now.hour=0; //小时不能超过24write_time(1,now.hour);}if(mode_num==5) //以下处理同上{now.minute++;if(now.minute==60) now.minute=0;write_time(4,now.minute);}if(mode_num==6) //以下处理同上{now.second++;if(now.second==60) now.second=0;write_time(7,now.second);}}}if(dec==0) //减键的处理和加键处理处理相反{delay(5);if(dec==0){if(mode_num==1){today.year--;write_riqi(1,today.year);gotoxy(1,14);display_week();}if(mode_num==2){today.month--;if(today.month==0) today.month=12; //要注意月份的最小值为1,当减为零时,要讲月份置为12write_riqi(4,today.month); //除以10来计算月份值,除以10求得的商值为十位gotoxy(1,14);display_week();}if(mode_num==3){today.day--;if(today.day==0) //当天数减为0时,要重新赋值,为上一个月的最大值today.day=monthday(today.year,today.month);write_riqi(7,today.day); //除以10来计算月份值,除以10求得的商值为十位gotoxy(1,14);display_week();}if(mode_num==4){now.hour--;if(now.hour<0) now.hour=23; //当小时数小于0时,要重新赋值,置为23write_time(1,now.hour);}if(mode_num==5){now.minute--;if(now.minute<0) now.minute=59; //注意点同上write_time(4,now.minute);}if(mode_num==6){now.second--;if(now.second<0) now.second=59; //注意点同上write_time(7,now.second);}}}}}void display_temp() //显示温度子程序{uint wendu; //设置wendu变量来存放从18b20读取的温度uchar A1,A2; //A1用来存放温度值的十位,A2存放个位tmpchange(); //启动温度转换wendu=tmp(); //读取温度值A1=wendu/10; //求A1值A2=wendu%10; //求A2值gotoxy(2,10);display_data(A1); //显示A1值display_string("."); //用小数点分开个位和小数write_date(int_to_char[A2]); //向lcd写数据,并且注意要转换A2数据类型}void timer0(void) interrupt 1{TR0=0;TL0=(TIMER0_COUNT & 0X00FF);//设置Timer0低八位数值TH0=(TIMER0_COUNT >> 8);//设置Timer0高八位数值TR0=1;count++;if(count==30) display_temp(); //延时,当count=30时,显示温度,并延时if(count==200) //当count自加到200时,开始判断此时时、分、秒的值,并进行转换{count=0;now.second++;if(now.second==60) //当秒达到60时,向分进位,且秒数置零{now.second=0;now.minute++;if(now.minute==60) //当分达到60时,向时进位,且分数置零{now.minute=0;now.hour++;if(now.hour==24) //当时达到24时,向天进位,且时数置零{now.hour=0;today.day++;if(today.day>monthday(today.year,today.month)) //判断天数,当超过本月最大天数时,向月份进位,且天数置一{today.day=1;today.month++;if(today.month==13) //判断月份,当月份超过12时,向年份进位,月份置一{today.month=1;today.year++;}write_riqi(4,today.month); //在位置4处,向lcd写月份}write_riqi(7,today.day); //在位置7处,向lcd写天数gotoxy(1,14);display_week();}write_time(1,now.hour); //在位置1处,向lcd写时数}write_time(4,now.minute); //在位置4处,向lcd写分数}write_time(7,now.second); //在位置7处,向lcd写秒数}}void main(){SYSTEMTIME CurrentTime;LcdInitiate(); //初始化lcdtimer0_initialize(); //初始化内部定时器Initial_DS1302(); //初始化DS1302DateToStr(&CurrentTime); //从DS1302读取日期TimeToStr(&CurrentTime); //从DS1302读取时间gotoxy(1,1);display_string(CurrentTime.DateString); //显示日期gotoxy(1,10);display_week(); //显示周几gotoxy(2,1);display_string(CurrentTime.TimeString); //显示时间gotoxy(2,10);display_string("00.0C"); //显示温度while(1) keyscan();}(二)DS1302时钟模块#include <reg52.h>#include <intrins.h>#ifndef _REAL_TIMER_DS1302_2003_7_21_#define _REAL_TIMER_DS1302_2003_7_21_sbit DS1302_CLK = P1^6; //实时时钟时钟线引脚sbit DS1302_IO = P1^7; //实时时钟数据线引脚sbit DS1302_RST = P1^5; //实时时钟复位线引脚sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;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[9];unsigned char TimeString[9];}SYSTEMTIME; //定义的时间类型#define AM(X) X#define PM(X) (X+12) // 转成24小时制#define DS1302_SECOND 0x80 //时钟芯片的寄存器位置,存放时间,如0x80放的的秒数#define DS1302_MINUTE 0x82#define DS1302_HOUR 0x84#define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8C#define DS1302_RAM(X) (0xC0+(X)*2) //用于计算DS1302_RAM 地址的宏RAM命令控制字地址:0xC0-0xFDvoid DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数){unsigned char i;ACC = d;for(i=8; i>0; i--){DS1302_IO = ACC0; //将IO线上的数据存放在ACC中DS1302_CLK = 1; //特别注意,DS1302写一数据时,CLK要产生一负脉冲DS1302_CLK = 0;ACC = ACC >> 1; //每次移位一位}}unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数){unsigned char i;for(i=8; i>0; i--){ACC = ACC >>1; //将前一个下降沿读出的数据右移一位从而读出该次读出的数放入ACC7ACC7 = DS1302_IO;DS1302_CLK = 1;DS1302_CLK = 0; //SCLK下降沿读出DS1302的数}return(ACC);}void Write1302(unsigned char ucAddr, unsigned char ucDa) //其中Addr为DS1302地址, ucData为要写的数据{DS1302_RST = 0; //写数据时,要注意RST产生一上升沿,CLK为低电平DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr); // 地址,命令DS1302InputByte(ucDa); // 写1字节数据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(); // 读1字节数据DS1302_CLK = 1;DS1302_RST = 0;return(ucData);}void DS1302_SetProtect(bit flag) //是否写保护{if(flag)Write1302(0x8E,0x80); //0x8E 控制字节地址,bit7=WP WP=1 禁止数据写入DS1302elseWrite1302(0x8E,0x00); //WP=0 允许写入DS1302}void DS1302_SetTime(unsigned char Address, unsigned char Value) // 设置时间函数{DS1302_SetProtect(0);Write1302(Address, ((Value/10)<<4 | (Value%10))); //读写数据时要特别注意数据的处理,要写的数据要进行拼凑,将Value数据的十位取出,放入高四位,Value 的个位放在低四位上}void DS1302_GetTime(SYSTEMTIME *Time){unsigned char ReadValue; //用来传递读取1302的数据ReadValue = Read1302(DS1302_SECOND);//读取秒数,存放在ReadValue变量中Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将ReadValue数据的第4、5、6位取出,实际上就是秒数的十位,但是以二进制的形式表示,所以要进行移位,向右移四位,在乘以10,在加上ReadValue变量中秒数的,将十六进制的数化成十进制数表示,并放在Time->Second中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); //同上}void DateToStr(SYSTEMTIME *Time) //年份转换成可供lcd显示的字段子程序{Time->DateString[0] = Time->Year/10 + '0'; //Time->DateString[0]中存放的就是要显示年的十位Time->DateString[1] = Time->Year%10 + '0'; //Time->DateString[1]中存放的就是要显示年的个位Time->DateString[2] = '-'; //年和月份之间用-分开Time->DateString[3] = Time->Month/10 + '0'; //Time->DateString[3]中存放的就是要显示月份的十位Time->DateString[4] = Time->Month%10 + '0'; //Time->DateString[4]中存放的就是要显示月份的个位Time->DateString[5] = '-';Time->DateString[6] = Time->Day/10 + '0'; //Time->DateString[6]中存放的就是要显示日的十位Time->DateString[7] = Time->Day%10 + '0'; //Time->DateString[7]中存放的就是要显示日的个位Time->DateString[8] = '\0'; //记住,结束时要添加'\0',以作为结束标志}void TimeToStr(SYSTEMTIME *Time) //时间转换成可供lcd显示的字段子程序{Time->TimeString[0] = Time->Hour/10 + '0';Time->TimeString[1] = Time->Hour%10 + '0';Time->TimeString[2] = ':';Time->TimeString[3] = Time->Minute/10 + '0';Time->TimeString[4] = Time->Minute%10 + '0';Time->TimeString[5] = ':';Time->TimeString[6] = Time->Second/10 + '0';Time->TimeString[7] = Time->Second%10 + '0';Time->TimeString[8] = '\0';}void Initial_DS1302(void) //DS1302的初始化程序{unsigned char Second=Read1302(DS1302_SECOND);if(Second&0x80) //BIT7=CH CH=0振荡器允许工作,CH=1,振荡器停止DS1302_SetTime(DS1302_SECOND,0);}#endif(三)DS18B20温度模块#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intuint temp; // 温度变量sbit DS=P1^0; //定义数据传输接口void delay1(uchar count) //延时{while(count>0) count--;}void reset(void) //送初值和初始命令{DS=0;delay1(100);DS=1;delay1(4);delay1(200);}bit read_bit(void) //读一比特,特别注意对于18b20,要读数据时,一定要产生DS正脉冲,然后才传送数据{bit temp;DS=0;_nop_();DS=1;_nop_();temp=DS;delay1(200);return temp;}uchar read_byte(void) //读一字节的数据{uchar i,byte=0;bit j;for(i=0;i<8;i++){byte=_cror_(byte ,1); //将byte数据向右循环一位,每次都取出最高位j=read_bit(); //设定j为读取进来的一比特数if(j==0) byte=byte|0x00; //当j=0时,即读取一字节数完毕,取出次字节数else byte=byte|0x80; //每次取出最高位}return byte; //返回字节数}void write_byte(uchar command) //写一字节到18b20{uchar i;for(i=0;i<8;i++) //用i来设定一字节的数据{if((command & 0x01)==0) //取出最低位为零时,DS要产生一个负脉冲脉冲{DS=0;delay1(8);DS=1;_nop_();}else //否则产生一上升沿{DS=0;_nop_();DS=1;delay1(8);}command=_cror_(command,1);}}void tmpchange(void) //启动18b20{reset();write_byte(0xcc); //直接向18b20发送温度变换命令write_byte(0x44); //启动18b20进行温度转换}uint tmp() //获取温度{float tt;uchar a,b;reset();write_byte(0xcc); //直接向18b20发送温度变换命令write_byte(0xbe); //读取温度寄存器的温度值a=read_byte();//读低八位b=read_byte();//读高八位temp=b;temp<<=8; //因为18b20处理接受到的数据要进行处理,先将高八位左移4位temp=temp|a; //在和低八位相或,整合取得的数据tt=temp*0.0625;temp=tt*10+0.5;return temp;}(四)LCD1602显示模块#include<reg52.h> //包含单片机寄存器的头文件#include<intrins.h> //包含_nop_()函数定义的头文件#define uchar unsigned char#define uint unsigned intsbit rs=P2^0;//寄存器选择信号sbit rw=P2^1; //读写控制信号线sbit lcden=P2^2; //使能信号线sbit BF=P0^7; //忙碌标志位,将BF位定义为P0.7引脚#define lcd_mode 0x38#define display_cursor 0x0f#define undisplay_cursor 0x0cchar code int_to_char[]={'0','1','2','3','4','5','6','7','8','9'};//********************************************************void delay(uint x) //延时程序{uint a,b;for(a=x;a>0;a--)for(b=10;b>0;b--);}//******************************************************** unsigned char BusyTest(void){bit result;rs=0; //根据规定,RS为低电平,RW为高电平时,可以读状态rw=1;lcden=1; //E=1,才允许读写_nop_(); //空操作_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间result=BF; //将忙碌标志电平赋给resultlcden=0;return result;}/*****************************************************函数功能:将模式设置指令或显示地址写入液晶模块入口参数:dictate***************************************************/void WriteInstruction (unsigned char dictate){while(BusyTest()==1); //如果忙就等待rs=0; //根据规定,RS和R/W同时为低电平时,可以写入指令rw=0;lcden=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,// 就是让E从0到1发生正跳变,所以应先置"0"_nop_();_nop_(); //空操作两个机器周期,给硬件反应时间P0=dictate; //将数据送入P0口,即写入指令或地址_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间lcden=1; //E置高电平_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间lcden=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令}void write_com(uchar com) //写命令{P0=com; //写命令,记住时序问题rs=0; //rs要为低电平lcden=0; //使lcd使能端产生一个正脉冲delay(10);lcden=1;delay(10);lcden=0;}void WriteAddress(unsigned char x){WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x"}//********************************************************void write_date(unsigned char y) //写数据{{while(BusyTest()==1);rs=1; //RS为高电平,RW为低电平时,可以写入数据rw=0;lcden=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,P0=y; //将数据送入P0口,即将数据写入液晶模块_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间lcden=1; //E置高电平_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间lcden=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令}}//********************************************************void LcdInitiate(void){delay(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间WriteInstruction(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口delay(5); //延时5msWriteInstruction(0x38);delay(5);WriteInstruction(0x38);delay(5);WriteInstruction(0x0d); //显示模式设置:显示开,有光标,光标闪烁delay(5);WriteInstruction(0x0c); //显示模式设置:光标右移,字符不移delay(5);WriteInstruction(0x01); //清屏幕指令,将以前的显示内容清除delay(5);}//********************************************************void display_string(char *p) //写字符串{while(*p){write_date(*p);delay(20);p++;}}//********************************************************void gotoxy(uchar x,uchar y) //设置移动坐标{if(x==1)write_com(0x80+y);elsewrite_com(0xc0+y);}//******************************************************** void display_data(char number) //显示数据{uchar x,y;x=number/10; //将取得的数据转换成十进制y=number%10;write_date(int_to_char[x]);write_date(int_to_char[y]);}(五)键盘扫描部分char fun,flag,flag2,adjust,wei,adt; //按键功能标志位sbit rr=P3^7;sbit ll=P3^6;sbit anjian=P1^6; //按键灯光提醒sbit right=P3^3;sbit left=P3^2;sbit up=P3^1;sbit down=P3^0;sbit menu=P3^3;sbit ok=P3^2;void keyscan() //调整时间按键程序{uchar i;ll=0;if(fun==1) //功能1,时钟情况下{if(ok==0) //判断OK键摁下{delay_MS(5); //去抖动if(ok==0){while(!ok); //松手监测anjian=0; //提示灯点亮delay_MS(240);anjian=1;flag++; //按键计数ds1302_write_byte(write_wp,0x00); //DS1302暂停ds1302_write_byte(write_sec,0x80);ds1302_write_byte(write_wp,0x80);if(flag==2) //调整时间完毕,退出调整{wei=0;adt=0;ds1302_write_time();flag=0;}adjust=1; //允许调整时间标志位lcd1602_write_command(0x0d);lcd1602_write_command(0x80+0x03);}}ll=1;rr=0;if(adjust==1){if(right==0) //判断左移按键{delay_MS(5);if(right==0){while(!right);anjian=0;delay_MS(240);anjian=1;wei++; //移动位置标志adt=1;if(wei==1){lcd1602_write_command(0x0d); //显示光标lcd1602_write_command(0x80+0x03);}……if(wei==8) //循环移动{wei=1;lcd1602_write_command(0x0d);lcd1602_write_command(0x80+0x03);}}}……if(adt==1){if(up==0) //时间加1{delay_MS(5);if(up==0){while(!up);anjian=0;delay_MS(240);anjian=1;if(wei==1){time1[1]=time1[1]+1;if(time1[1]==80){time1[1]=0;}ds1302_write_time(); //写入调整后的时间ds1302_read_time(); //显示调整后的时间for(i=1;i<8;i++)TempData[i]=time1[i];change();display();lcd1602_write_command(0x0d);lcd1602_write_command(0x80+0x03);}……ll=1;}}}void keyscan1() //主功能键的扫描{ll=0;if(menu==0){delay_MS(5);if(menu==0){while(!menu);anjian=0;delay_MS(240);anjian=1;fun++;if(fun==1){flag=1;flag2=1;EA=0;shizhong();delay_MS(1000);flag=0;}if(fun==2){flag=1;flag2=1;wendu();delay_MS(1000);EA=1;flag2=0;fun=0;}}}ll=1;}五、总结通过课程设计,锻炼了独立进行课题制作的能力,从画原理图,元器件的选用,电路的设计,阅读芯片资料,程序的编写,调试中,进一步掌握单片机技术,提高编程能力。

相关文档
最新文档