单片机万年历汇编闹钟时间可调程序(LCD1602_DS18B20_DS1302_MAX810L)
- 格式:doc
- 大小:842.97 KB
- 文档页数:33
/*********************************************//* Filename :万年历** Describe : 时间星期日期温度高低温报警** Designer :潜力狼** Date :2012-07-16/*********************************************/#include<reg52.h>#include<intrins.h>/**********************************************//************ 接口定义如下***************//**********************************************/sbit SCK = P1^7; //时钟sbit SDA = P2^3; //数据sbit RST = P1^3; //DS1302复位(片选)sbit E=P1^2;//1602使能引脚sbit RW=P2^1;//1602读写引脚sbit RS=P2^0;//1602数据/命令选择引脚#define uchar unsigned char#define uint unsigned int#define DS1302_W_ADDR 0xBE#define DS1302_R_ADDR 0xBF#define jump_ROM 0xCC //DS18B20#define start 0x44 //DS18B20#define read_EEROM 0xBE //DS18B20sbit DQ = P1^4;unsigned char TMPH_DS18B20,TMPL_DS18B20;/****************************************************/uchar num,m,n;uchar time1[7]={0x50,0x59,0x23,0x31,0x12,0x07,0x12};//秒分时日月周年10-08-15 23:59:50 ****注意没有code 才可以做指针变量(地址)//uchar time1[7]={50,59,23,31,12,07,12};//此种十进制表示需要转换成BCD码才能写入DS1302 ,而且这样表达,在液晶上显示困难char code table[] = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};//液晶显示0~9数字的LCD字型码值(ASCII码)void delay(uint z){while(z--);}void delay_1ms(uchar z){uint i,j;for(i=0;i<z;i++)for(j=0;j<128;j++);}void write_DS1302_byte(uchar dat) {uchar i;//RST=1;for(i=0;i<8;i++){SDA=dat&0x01;SCK=1;dat>>=1;SCK=0;}}uchar read_DS1302_byte(void) {uchar i,temp=0;for(i=0;i<8;i++){temp>>=1;if(SDA)temp|=0x80;SCK=1;SCK=0;}return temp;}void reset_DS1302(){RST=0;SCK=0;RST=1;}void clear_DS1302_WP(){reset_DS1302();RST=1; //?write_DS1302_byte(0x8e);write_DS1302_byte(0);SDA=0; //?RST=0; // ?}void set_DS1302_WP(){reset_DS1302();RST=1;write_DS1302_byte(0x8e);write_DS1302_byte(0x80);SDA=0;RST=0;}void set_time(uchar *timedata){uchar i;//,temp;/* for(i=0;i<7;i++) //时钟显示的7个数BCD码转换{temp=timedata[i]/10;timedata[i]=timedata[i]%10;timedata[i]=temp*16+timedata[i];} */clear_DS1302_WP();reset_DS1302();write_DS1302_byte(DS1302_W_ADDR);//写入写地址指令for(i=0;i<7;i++){write_DS1302_byte(timedata[i]);delay(10);}write_DS1302_byte(0); //??????SDA=0;RST=0;set_DS1302_WP();}void read_time(uchar *timedata){uchar i;clear_DS1302_WP();reset_DS1302();write_DS1302_byte(DS1302_R_ADDR);for(i=0;i<7;i++){timedata[i]=read_DS1302_byte();delay(10);}SDA=0;RST=1;set_DS1302_WP();}/****************************************//*LCD1602 函数体*//****************************************///uchar code table[]="Time: ";//uchar code table1[]="Data:20";uchar code week[]="MonTueWenThuFriSatSun";void write_LCD1602_cmd(uchar del) // 写入命令函数{RS=0;//RS=0时,一个高脉冲读取命令RW=0;E=0; //可以省略不写delay_1ms(5);P0=del;delay_1ms(5);E=1; //E从0到1再跳变到0,即一个高脉冲delay_1ms(5);E=0;}void write_LCD1602_data(uchar del) //写入数据函数{RS=1; //RS=1时,一个高脉冲读取数据RW=0;E=0;delay_1ms(5);P0=del;delay_1ms(5);E=1;//E从0到1再跳变到0,即一个高脉delay_1ms(5);E=0;}void LCD1602_init(){write_LCD1602_cmd(0x38);write_LCD1602_cmd(0x0e);write_LCD1602_cmd(0x06);//wcmd(0x80); //命令数据0x80是让液晶从第一位开始显示}/********************************************************/ /* 温度传感器DS18B20 对温度的采集*//********************************************************/ uchar Reset_DS18B20(void){uchar deceive_ready;DQ = 0;delay(29);DQ = 1;delay(3);deceive_ready = DQ;delay(25);return(deceive_ready);}uchar read_DS18B20_bit(void){uchar i;DQ = 0;DQ = 1;for(i=0; i<3; i++);return(DQ);}void write_DS18B20_bit(uchar bitval){DQ=0;if(bitval==1)DQ=1;delay(5);DQ=1;}uchar read_DS18B20_byte(void){uchar i,m,receive_data;m = 1;receive_data = 0;for(i=0; i<8; i++){if(read_DS18B20_bit()){receive_data = receive_data + (m << i);}delay(6);}return(receive_data);}void write_DS18B20_byte(uchar val){uchar i,temp;for(i=0; i<8; i++){temp = val >> i;temp = temp & 0x01;write_DS18B20_bit(temp);delay(5);}}void main(){uint temp;//DS18B20LCD1602_init();set_time(&time1);while(1){Reset_DS18B20();write_DS18B20_byte(jump_ROM);write_DS18B20_byte(start);Reset_DS18B20();write_DS18B20_byte(jump_ROM);write_DS18B20_byte(read_EEROM);TMPL_DS18B20 = read_DS18B20_byte();TMPH_DS18B20 = read_DS18B20_byte();temp = TMPL_DS18B20/16 + TMPH_DS18B20*16;m = table[temp/10%10];n = table[temp%10];/* if(temp>32|temp<20) //蜂鸣器报警!!!{Bell=0;delay_1ms(200);Bell=1;} */read_time(&time1);write_LCD1602_cmd(0x80);write_LCD1602_data(' ');write_LCD1602_data(time1[2]/16+48); //时write_LCD1602_data(time1[2]%16+48);write_LCD1602_data(':');write_LCD1602_data(time1[1]/16+48); // 分write_LCD1602_data(time1[1]%16+48);write_LCD1602_data(':');write_LCD1602_data(time1[0]%16+48);write_LCD1602_data(' ');write_LCD1602_cmd(0x80+12); //英文缩写星期switch(time1[5]%16) //{case 1:write_LCD1602_data(week[0]);write_LCD1602_data(week[1]);write_LCD1602_data(week[2]);break;case 2:write_LCD1602_data(week[3]);write_LCD1602_data(week[4]);write_LCD1602_data(week[5]);break;case 3:write_LCD1602_data(week[6]);write_LCD1602_data(week[7]);write_LCD1602_data(week[8]);break;case 4:write_LCD1602_data(week[9]);write_LCD1602_data(week[10]);write_LCD1602_data(week[11]);break;case 5:write_LCD1602_data(week[12]);write_LCD1602_data(week[13]);write_LCD1602_data(week[14]);break;case 6:write_LCD1602_data(week[15]);write_LCD1602_data(week[16]);write_LCD1602_data(week[17]);break;case 7:write_LCD1602_data(week[18]);write_LCD1602_data(week[19]);write_LCD1602_data(week[20]);break;}write_LCD1602_cmd(0x80+0x40);write_LCD1602_data(2+48); //显示2write_LCD1602_data(0+48); //显示0write_LCD1602_data(time1[6]/16+48); //显示12年write_LCD1602_data(time1[6]%16+48);write_LCD1602_data('-');write_LCD1602_data(time1[4]/16+48); //月write_LCD1602_data(time1[4]%16+48);write_LCD1602_data('-');write_LCD1602_data(time1[3]%16+48);write_LCD1602_data(' ');write_LCD1602_data(m); //温度write_LCD1602_data(n);//write_LCD1602_data(temp/10%10+48);//直接转换为LCD字型码(ASCII码)显示温度//write_LCD1602_data(temp%10+48);write_LCD1602_data(0xdf);write_LCD1602_data('C');}}。
1 课设所需软件简介1.1 Keil uVision4的简要介绍2009年2月发布Keil μVision4,Keil μVision4引入灵活的窗口管理系统,使开发人员能够使用多台监视器,并提供了视觉上的表面对窗口位置的完全控制的任何地方。
新的用户界面可以更好地利用屏幕空间和更有效地组织多个窗口,提供一个整洁,高效的环境来开发应用程序。
新版本支持更多最新的ARM芯片,还添加了一些其他新功能。
2011年3月ARM公司发布最新集成开发环境RealView MDK开发工具中集成了最新版本的Keil uVision4,其编译器、调试工具实现与ARM器件的最完美匹配。
Keil C51开发系统基本知识Keil C51开发系统基本知识1. 系统概述Keil C51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows界面。
另外重要的一点,只要看一下编译后生成的汇编代码,就能体会到Keil C51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。
在开发大型软件时更能体现高级语言的优势。
下面详细介绍Keil C51开发系统各部分功能和使用。
2. Keil C51单片机软件开发系统的整体结构C51工具包的整体结构,uVision与Ishell分别是C51 for Windows和for Dos 的集成开发环境(IDE),可以完成编辑、编译、连接、调试、仿真等整个开发流程。
开发人员可用IDE本身或其它编辑器编辑C或汇编源文件。
然后分别由C51及C51编译器编译生成目标文件(.OBJ)。
目标文件可由LIB51创建生成库文件,也可以与库文件一起经L51连接定位生成绝对目标文件(.ABS)。
ABS文件由OH51转换成标准的Hex文件,以供调试器dScope51或tScope51使用进行源代码级调试,也可由仿真器使用直接对目标板进行调试,也可以直接写入程序存贮器如EPROM中。
使用独立的Keil仿真器时,注意事项:* 仿真器标配11.0592MHz的晶振,但用户可以在仿真器上的晶振插孔中换插其他频率的晶振。
基于52单片机的万年历显示(采用实时芯片DS1302芯片+LCD1602液晶显示)仿真图:/************************************************************-- THE LCD1602 DISPLAY LIB -—COPYRIGHT (C) 2014 BY LLH-— ALL RIGHTS RESERVED —-ATTENTION:延时不能过长,否则无法与DS1302同步(最好小于1ms)*************************************************************/#ifndef __LCD1602_DIS_H__#define __LCD1602_DIS_H__#define uint unsigned int#define uchar unsigned charsbit lcd_rs=P2^0;sbit lcd_rw=P2^1;sbit lcd_en=P2^2;/**********延时子程序************/void delay(uint z){uint x,y;for(x=z;x〉0;x—-)for(y=65;y〉0;y--);//60刚好和DS1302同步}/***********写命令子程序**********/void write_com(uchar com){lcd_rs=0;lcd_rw=0;P0=com;delay(1);lcd_en=1;delay(1);lcd_en=0;}/***********写数据子程序**********/void write_data(uchar date){lcd_rs=1;lcd_rw=0;P0=date;delay(1);lcd_en=1;delay(1);lcd_en=0;}/**********初始化子程序************/void init_LCD1602(){lcd_en=0;write_com(0x38); //显示模式设置:16*2显示,5*7点阵,8位数据接口write_com(0x0c); //开显示,不显示光标write_com(0x06); //指针、光标自动加一,整屏不移动write_com(0x80); //初始位置设置}/*********显示子程序***********/void display(uchar *str){while(*str!='\0’){write_data(*str);str++;}}#endifDS1302的H文件:/******************************************************************—— THE DS1302 REAL_TIME LIB —-COPYRIGHT (C) 2014 BY LLH-- ALL RIGHTS RESERVED ——ATTENTION:不能使用(i=0;i<8;i++),否则,液晶无法显示确切的时间(???);星期的显示多了一天(???)********************************************************************/#ifndef __DS1302_REAL_TIME_H__#define __DS1302_REAL_TIME_H__#define uint unsigned int#define uchar unsigned charsbit DS1302_RST=P1^5;sbit DS1302_SCLK=P1^6;sbit DS1302_IO=P1^7;sbit ACC0=ACC^0;sbit ACC7=ACC^7;typedef struct{uchar second;uchar minute;uchar hour;uchar week;uchar day;uchar month;uchar year;uchar date_str[11];uchar time_str[9];}date_time;/**************写数据定义*****************/#define DS1302_SECOND 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 ST 0x00/*************单字节写数据子程序**************/void single_byte_write(uchar date){uchar i;ACC=date;for(i=8;i〉0;i--) //不能使用(i=0;i〈8;i++),否则,液晶只显示00000{DS1302_IO=ACC0;DS1302_SCLK=1;DS1302_SCLK=0;ACC=ACC>>1;}}/*************单字节读数据子程序**************/uchar single_byte_read( ){uchar i;for(i=8;i>0;i--){ACC=ACC>〉1;ACC7=DS1302_IO;DS1302_SCLK=1;DS1302_SCLK=0;}return ACC;}/**************控制字的写入****************/void write_command(uchar addr,uchar dat){DS1302_SCLK=0;DS1302_RST=0;DS1302_RST=1;single_byte_write(addr);single_byte_write(dat);DS1302_SCLK=1;DS1302_RST=0;}/**************读取芯片内部的数据****************/uchar read_data(uchar address){uchar r_data;DS1302_SCLK=0;DS1302_RST=0;DS1302_RST=1;single_byte_write(address|0x01);//若没加(或0x01)ds1302和lcd1602都无法正常显示(?)r_data=single_byte_read();DS1302_SCLK=1;DS1302_RST=0;return r_data;}/************初始化子程序************/void init_DS1302(){uchar temp;temp=read_data(DS1302_SECOND);if(temp&0x80){write_command(0x8e,0x00); //启动读写write_command(0x84,0x00);//设置24小时模式write_command(DS1302_SECOND,ST); //写入当前时间数据}}/*************读取时间、并实现BCD和十进制间的转化***************//****************************************************************十进制转8421编码:32/10 = 3*16= 48(十进制)= 30(16进制)32%10 = 230+2 = 32 * 16 + 32 % 10 = 32(8421编码)(即:a/10*10+a%10)8421编码转十进制:51 / 16 = 5 * 10(16进制) = 50(十进制)51 % 16 = 150 + 1 = 51 / 16 + 51 % 16 = 51(十进制)(即:a/16*10+a%16)*****************************************************************/void get_time(date_time *Time){uchar value;value=read_data(DS1302_SECOND);Time—〉second=(value/16)*10+(value%16);value=read_data(DS1302_MINUTE);Time—〉minute=(value/16)*10+(value%16);value=read_data(DS1302_HOUR);(完整word版)万年历(DS1302+LCD1602【程序、仿真、完整】) Time-〉hour=(value/16)*10+(value%16);value=read_data(DS1302_WEEK);Time—〉week=(value/16)*10+(value%16-1);//星期的显示数值比正确值多一value=read_data(DS1302_DAY);Time-〉day=(value/16)*10+(value%16);value=read_data(DS1302_MONTH);Time—>month=(value/16)*10+(value%16);value=read_data(DS1302_YEAR);Time-〉year=(value/16)*10+(value%16);}/**************年-月-日-星期“字符”显示***************/void date_to_str(date_time *Time){Time-〉date_str[0]=Time-〉year/10+’0’; //加’0’转化成字符Time—〉date_str[1]=Time—〉year%10+’0';Time->date_str[2]='—’;Time->date_str[3]=Time->month/10+'0';Time->date_str[4]=Time-〉month%10+'0’;Time—>date_str[5]=’—’;Time-〉date_str[6]=Time-〉day/10+'0';Time—>date_str[7]=Time—>day%10+’0’;Time-〉date_str[8]=’-’;Time->date_str[9]=Time—〉week%10+’0’;Time-〉date_str[10]='\0';}/**************时-分-秒“字符”显示***************/void time_to_str(date_time *Time){Time—>time_str[0]=Time->hour/10+’0';Time-〉time_str[1]=Time—〉hour%10+’0';Time—>time_str[2]=’-';Time—>time_str[3]=Time—>minute/10+'0’;Time—>time_str[4]=Time—>minute%10+'0’;Time->time_str[5]='—';Time->time_str[6]=Time->second/10+'0';Time->time_str[7]=Time—>second%10+'0';Time-〉time_str[8]=’\0';}#endif万年历C文件:/********************************************************* TITLE: 实时时钟FUNCTION: DS1302+LCD1602显示实时时钟WRITER: LINLIANHUO(完整word版)万年历(DS1302+LCD1602【程序、仿真、完整】) TIME: 2014-07-30REMARK: matters need attention**********************************************************/#include 〈reg51.h〉#include <string.h〉#include ”DS1302。
#include<reg51.h>#include<intrins.h>#define uint unsigned int#define uchar unsigned charuint nian,yue,ri,week,shi,fen,miao,shuju,naoshi,naofen;uchar ds1302_addr,ds1302_data,temp,temp1,bz=0,shanshuo=0;uchar r0,r1,nh,nl,yh,yl,rh,rl,sh,sl,fh,fl,mh,ml,wh,wl,nsh,nsl,nfh,nfl; uchar moshibz,jiabz,jianbz,kaishibz,naobz,speek;uchartab[11]={0Xc0,0Xf9,0Xa4,0Xb0,0X99,0X92,0X82,0Xf8,0X80,0X90,0xff}; sbit rst=P1^0;sbit clk=P1^1;sbit io=P1^2;sbit DQ=P1^3;sbit zz=P1^7;sbit moshi=P1^6;sbit jia=P1^5;sbit jian=P1^4;sbit kaishi=P3^1;sbit nao=P3^0;sbit led=P2^7;sbit ACC0=ACC^0;sbit ACC7=ACC^7;/*****************延时函数*********************/void d elay(uchar k) //延时程序,约0.1ms{uchar n,m;for(n=0;n<k;n++){for(m=0;m<120;m++);}}/*****************写地址子函数*********************/void w rit_addr(uchar ds1302_addr) //读ds1302 函数{ACC=ds1302_addr;rst=1;for(r1=8;r1>0;r1--){io=ACC0;clk=0;clk=1;ACC=ACC>>1;}}/*****************写数据子函数*********************/void w rit_data(uchar ds1302_data){ACC=ds1302_data;rst=1;for(r1=8;r1>0;r1--){io=ACC0;clk=0;clk=1;ACC=ACC>>1;}rst=0;}/*****************写入ds1302函数*********************/ void write(uchar add,ss) {clk=0;_nop_();rst=0;_nop_();rst=1;_nop_();writ_addr(add);_nop_();writ_data(ss);_nop_();clk=1;_nop_();rst=0;_nop_();}uchar read_data(void) {for(r1=8;r1>0;r1--){ACC7=io;clk=1;clk=0;ACC=ACC>>1;}return ACC;}/*****************读ds1302函数*********************/ void read(uchar addc) { uchar kk;clk=0;_nop_();_nop_();rst=1;_nop_();writ_addr(addc);_nop_();kk=read_data();_nop_();clk=1;_nop_();rst=0;_nop_();ds1302_data=(kk/16)*10+(kk%16); }/*****************//读ds1302 函数*********************/void r ed_dsl302(void){read(0x8d);nian=ds1302_data;read(0x8b);week=ds1302_data;read(0x89);yue=ds1302_data;read(0x87);ri=ds1302_data;read(0x85);shi=ds1302_data;read(0x83);fen=ds1302_data;read(0x81);miao=ds1302_data;}/*****************//写ds1302函数*********************//*void writl302(void){write(0x8e,0x00);write(0x8c,nian);write(0x8a,week);write(0x88,yue);write(0x86,ri);write(0x84,shi);write(0x82,fen);write(0x80,miao);*//*****************初始化函数*********************/void t0_init(void){IE=0X82;TMOD=0X01;TH0=0x3c;TL0=0XB0;TR0=1;r0=0;}/*****************定时器0函数*********************/void t imer() interrupt 1 {TH0=0x3c; //TL0=0XB0;r0++;if(r0==10){r0=0;shanshuo=~shanshuo;}}/*****************闹钟显示函数*********************/void n aozhong(void){P2=0xff;P2=tab[nsh];P0=0xfb;delay(2);P0=0xFF;P2=0xff;P2=tab[nsl];P0=0xF7;delay(2);P0=0xFF;P2=0xff;P2=tab[nfh];P0=0xfe;delay(2);P0=0xFF;P2=tab[nfl];P0=0xFd;delay(2);P0=0xFF;P2=0xff;P2=tab[wh];P0=0xbf;delay(2);P0=0xFF;P2=0xff;P2=tab[wl];P0=0x7f;delay(2);P0=0xFF;P2=0xff;P2=tab[mh];P0=0xef;delay(2);P0=0xFF;P2=0xff;P2=tab[ml];P0=0xdf;delay(2);P0=0xFF;}/*****************全部显示函数************************/ void d isplay(void){if(speek==1){naozhong();}else{P2=0xff;P2=tab[mh];P0=0xef;delay(2);P0=0xFF;P2=0xff;P2=tab[ml];P0=0xdf;delay(2);P2=0xff;P2=tab[fh]; P0=0xfb; delay(2);P0=0xFF;P2=0xff;P2=tab[fl]; P0=0xF7; delay(2);P0=0xFF;P2=0xff;P2=tab[sh]; P0=0xfe; delay(2);P0=0xFF;P2=0xff;P2=tab[sl]; P0=0xFd; delay(2);P0=0xFF;P2=0xff;P2=tab[rh]; P3=0xbf; delay(2);P3=0xFF;P2=0xff;P2=tab[rl]; P3=0x7f; delay(2);P3=0xFF;P2=0xff;P2=tab[yh]; P3=0xef; delay(2);P3=0xFF;P2=0xff;P2=tab[yl]; P3=0xdf; delay(2);P3=0xFF;P2=0xff;P2=tab[nh];delay(2);P3=0xFF;P2=0xff;P2=tab[nl];P3=0xF7;delay(2);P3=0xFF;P2=0xff;zz=0;P2=tab[week];delay(2);zz=1;P2=0xff;P2=tab[wh];P0=0xbf;delay(2);P0=0xFF;P2=0xff;P2=tab[wl];P0=0x7f;delay(2);P0=0xFF;}P2=0xff;P2=tab[wh];P0=0xbf;delay(2);P0=0xFF;P2=0xff;P2=tab[wl];P0=0x7f;delay(2);P0=0xFF;}/*****************闹钟切换函数*********************/ void n aokey(void){if(nao==0){if(naobz==0){naobz=1;speek=!speek;}}if(nao!=0){naobz=0;}}/*****************按键函数*********************/ void k ey(void){if(kaishi==0){if(kaishibz==0){kaishibz=1;bz=7;}}if(kaishi!=0){kaishibz=0;}if(moshi==0){if(moshibz==0){moshibz=1;if(bz==7){bz=0;}else{bz++;}}}if(moshi!=0){moshibz=0;}}/*****************按键加函数*********************/ void s hangtiao(void){if(jia==0){if(jiabz==0){jiabz=1;if(shuju==59){shuju=0;}else{shuju++;}}}if(jia!=0){jiabz=0;}}/*****************按键减函数*********************/void x iatiao(void){if(jian==0){if(jianbz==0){jianbz=1;if(shuju==0){shuju=20;}else{shuju--;}}}if(jian!=0){jianbz=0;}}/*****************分离函数*********************/void f enli(void){if(fen==59&miao==56){led=0;}else{led=1;}if(speek==1){if(bz==1){shuju=naoshi; //先用十进制家,加完后必须转化成十六进制写入shangtiao();xiatiao();naoshi=shuju;if(shanshuo==1){nsh=10;nsl=10;}else{nsh=naoshi/10;nsl=naoshi%10;}}else{nsh=naoshi/10;nsl=naoshi%10;if(bz==2){shuju=naofen;shangtiao();xiatiao();naofen=shuju;if(shanshuo==1){nfh=10;nfl=10;}else{nfh=naofen/10;nfl=naofen%10;}}else{bz=0;nfh=naofen/10;nfl=naofen%10;}}}else{if(bz==1){shuju=nian; //先用十进制家,加完后必须转化成十六进制写入shangtiao();xiatiao();nian=shuju;nian=(nian/10)*16+(nian%10);write(0x8c,nian);nian=(nian/16)*10+(nian%16);if(shanshuo==1){nh=10;nl=10;}else{nh=nian/10;nl=nian%10;}}else{nh=nian/10;nl=nian%10;if(bz==2){shuju=yue;shangtiao();xiatiao();yue=shuju;yue=(yue/10)*16+(yue%10);write(0x88,yue);yue=(yue/16)*10+(yue%16);if(shanshuo==1){yh=10;yl=10;}else{yh=yue/10;yl=yue%10;}}else{yh=yue/10;yl=yue%10;if(bz==3){shuju=ri;shangtiao();xiatiao();ri=shuju;ri=(ri/10)*16+(ri%10);write(0x86,ri);ri=(ri/16)*10+(ri%16);if(shanshuo==1){rh=10;rl=10;}else{rh=ri/10;rl=ri%10;}}else{rh=ri/10;rl=ri%10;if(bz==4){shuju=shi;shangtiao();xiatiao();shi=shuju;shi=(shi/10)*16+(shi%10);write(0x84,shi);shi=(shi/16)*10+(shi%16);if(shanshuo==1){sh=10;sl=10;}else{sh=shi/10;sl=shi%10;}}else{sh=shi/10;sl=shi%10;if(bz==5){shuju=fen;shangtiao();xiatiao();fen=shuju;fen=(fen/10)*16+(fen%10);write(0x82,fen);fen=(fen/16)*10+(fen%16);if(shanshuo==1){fh=10;fl=10;}else{fh=fen/10;fl=fen%10;}}else{fh=fen/10;fl=fen%10;if(bz==6){shuju=week;shangtiao();xiatiao();week=shuju;week=(week/10)*16+(week%10);write(0x82,week);week=(week/16)*10+(week%16);if(shanshuo==1){week=10;}else{;}}else{;}}}}}}}mh=miao/10;ml=miao%10;wh=temp/10;wl=temp%10;}/***********ds18b20延迟子函数(晶振12MHz)*******/void delay_18B20(unsigned int i){while(i--);}/**********ds18b20初始化函数**********************/void Init_DS18B20(void){unsigned char x=0;DQ = 1; //DQ复位delay_18B20(8); //稍做延时DQ = 0; //单片机将DQ拉低delay_18B20(80); //精确延时大于480usDQ = 1; //拉高总线delay_18B20(14);x = DQ;//稍做延时后如果x=0则初始化成功x=1则初始化失败delay_18B20(20);}/***********ds18b20读一个字节**************/unsigned char ReadOneChar(void){unsigned char i=0;unsigned char dat=0;for (i=8;i>0;i--){DQ=0; //给脉冲信号dat>>=1;DQ=1;//给脉冲信号if(DQ)dat|=0x80;delay_18B20(4);}return(dat);}/*************ds18b20写一个字节****************/void WriteOneChar(unsigned char 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 wendu(void){uchar a=0;uchar b=0;uchar flag; //初始化是否成功标志位0,成功1,失败Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0x44);//启动温度转换delay_18B20(100); // this message is very importantInit_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE);//读取温度寄存器等(共可读9个寄存器)前两个就是温度delay_18B20(100);a=ReadOneChar();//读取温度值低8位b=ReadOneChar();//读取温度值高8位if(flag)//初始化失败{a=0x00;b=0x00;}temp1=b<<4;temp1+=(a&0xf0)>>4;//小数点前的数据// temp2=a&0x0f;//小数点后的数据temp=temp1;//temp=((b*256+a)>>4);//当前采集温度值除16得实际温度值//temp1 = t/100%10;//温度值十位// temp2 = t/10%10; //温度值个位// temp3 = t%10; //温度值十分位}/*****************比较函数*********************/void b ijiao(void){if(shi==naofen&fen==naoshi){led=0;if(naofen==naofen+1){led=1;}}else{led=1;}}/**********************主函数**********************/void m ain(void){bz=0;shanshuo=1;nian=0x13;yue=0x8;ri=0x11;shi=0x20;fen=0x44;miao=0x10;week=0x07;// writl302(); //因为ds1302只须写入一次,所以将此处屏蔽。
#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit lcdws=P2X; 〃1602 管脚定义sbit Icde n=P2P;sbit Icdrs=P2A2;sbit key仁卩2人3; //闹钟设置键sbit key2=P2A4;sbit key3=P1A5;〃功能键定义sbit key4=P1A6;〃增大键定义sbit key5=P1A7;〃减小键定义uchar shi,fen,miao,ashi,afen,amiao,year,month,day,week; uchar s1num=0,s1num2=0,temp;bit flag;float f_temp;uint i,d;uchar code table2[]={0x20,0x20,0x2e,0x20,0xdf,0x43};uchar code table[]="20 - - ";uchar code table1[]=" : : ";sbit ds=P1A0;//ds18b20 信号线sbit beep=P1A4; // 蜂鸣器管脚定义sbit ACC_7 = ACCA7; //位寻址寄存器定义sbit SCLK = P1A2; // DS1302 时钟信号sbit DIO= P1A1; // DS1302 数据信号sbit CE = P1A3;//地址、数据发送子程序//void delay2(uint ms)// {// uchar t;// while(ms--); for(t=0;t<120;t++);//}// void playmusic()// {// uint i2=0,j2,k2;// while(jiepai[i2]!=0||song[i2]!=0)// {// for(j2=0;j2<jiepai[i2]*20;j2++)// {// beep=~beep;// for(k2=0;k2<song[i2]/3;k2++);// }// delay2(10);// i2++;// }// }void write_1302( uchar addr,uchar dat ) {uchar i,temp;CE=0; SCLK=0;//CE 引脚为低,数据传送中止// 清零时钟总线CE = 1; //CE 引脚为高,逻辑控制有效// 发送地址for ( i=8; i>0; i-- ) // 循环8 次移位{SCLK = 0; temp = addr;DIO = (bit)(temp&0x01);addr >>= 1;SCLK = 1;}// 发送数据for ( i=8; i>0; i-- ){SCLK = 0; temp = dat;DIO = (bit)(temp&0x01);dat >>= 1;SCLK = 1;}CE = 0;}// 数据读取子程序uchar Read1302 ( uchar addr ){unsigned char i,temp,dat1,dat2;CE=0;SCLK=0;CE = 1;// 发送地址for ( i=8; i>0; i-- ){SCLK = 0; temp = addr;DIO = (bit)(temp&0x01);addr >>= 1;// 每次传输低字节// 右移一位// 循环8 次移位// 每次传输低字节// 右移一位SCLK = 1;}// 读取数据 for ( i=8; i>0; i-- ){ACC_7=DIO; SCLK = 1; ACC>>=1; SCLK = 0;}CE=0;dat1=ACC; dat2=dat1/16;// 十六进制转十进制 dat1=dat1%16; dat1=dat1+dat2*10; return (dat1);}// 初始化 DS1302void Initial(void) // 初始化 1302 {write_1302 (0x8e,0x00);write_1302 (0x80,0x56); write_1302 (0x82,0x58); write_1302 (0x84,0x23); write_1302 (0x86,0x30); write_1302 (0x88,0x09); write_1302 (0x8c,0x10); write_1302 (0x8a,0x01); write_1302 (0x8e,0x80);void delay(uint z)// 延时 1ms{uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--);}void write_com(uchar com)//1602 写命令 {lcdrs=0; lcden=0; P0=com; delay(5); lcden=1; delay(5); lcden=0;}void write_data(uchar date)//1602 写数据{ lcdrs=1; lcden=0; P0=date; delay(5); lcden=1; delay(5); lcden=0;}void dsreset(void) //DS18B20 ,初始化函数{ uint i; ds=0; i=103; while(i>0)i--; ds=1; i=4; while(i>0)i--;}// 数据进制转换2010 年 09 月 30 日 23 点 58 分 56 秒 星期一// 允许写保护 // 秒位初始化 // 分钟初始化 // 小时初始化 // 日初始化// 月初始化 // 年初始化 // 日期始化 // 禁止写保护bit tempreadbit(void)// 读1 位数据函数{ uint i; bit dat; ds=0;i++; ds=1;i++;i++;//i++ 起到延时作用dat=ds; i=8;while(i>0)i--; return(dat);}uchar tempread(void) // 读一个字节数据函数{uchar i,j,dat; dat=0; for(i=1;i<=8;i++) {j=tempreadbit(); dat=(j<<7)|(dat>>1);} return(dat);void tempwritebyte(uchar dat) // 向DS18B20 写一个字节数据函数{ uint i;uchar j;bit testb; for(j=1;j<=8;j++){ testb=dat&0x01; dat=dat>>1; if(testb)// 写1 { ds=0; i++;i++; ds=1;i=8;while(i>0)i--;}else{ds=0; // 写0i=8;while(i>0)i--;ds=1; i++;i++;}}}void tempchange(void) //DS18B20 开始获取温度并转换{dsreset();delay(1);tempwritebyte(0xcc);tempwritebyte(0x44);}uint get_temp() // 获取温度{uchar a,b;dsreset();delay(1);tempwritebyte(0xcc);tempwritebyte(0xbe); a=tempread(); // 读高8 位b=tempread(); // 读低8 位temp=b;temp<<=8; // 两个字节组合成1 个字节temp=temp|a;f_temp=temp*0.0625;temp=f_temp*10+0.5;f_temp=f_temp+0.05; // 温度在寄存器中为12 位,分辨率为0.0625人return temp;}void display(uchar addr,uchar dat){ write_com(0x80+0x40+addr); write_data(0x30+dat);delay(5);}void dis_temp(uint t){uchar i;i=t/100; display(10,i); i=t%100/10;display(11,i);i=t%100%10; display(13,i);}void init()// 初始化程序{uchar num;flag=1;lcden=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);write_com(0x80); for(num=0;num<15;num++){ write_data(table[num]); delay(5);}write_com(0x80+0x40); for(num=0;num<8;num++){ write_data(table1[num]); delay(5);} write_com(0x80+0x40+10); for(num=0;num<6;num++){write_data(table2[num]); delay(10);}}void di()// 蜂鸣器响函数{beep=0;delay(100);beep=1;}void write_sfm(uchar add,uchar date){uchar shi,ge; shi=date/10;ge=date%10; write_com(0x80+0x40+add); write_data(0x30+shi);write_data(0x30+ge);}void write_nyrz(uchar add,uchar date)// 显示年,月,日,周{ uchar shi,ge;shi=date/10;ge=date%10; write_com(0x80+add); write_data(0x30+shi);write_data(0x30+ge);}void display_week(uchar we){write_com(0x80+12);switch(we){case 1: write_data('M');delay(5); write_data('O');delay(5);write_data('N'); break;case 2: write_data('T');delay(5); write_data('U');delay(5);write_data('E'); break;case 3: write_data('W');delay(5);write_data('E');delay(5);write_data('D');break;case 4: write_data('T');delay(5);write_data('H');delay(5);write_data('U');break;case 5: write_data('F');delay(5);write_data('R');delay(5);write_data('T');break;case 6: write_data('S');delay(5);write_data('A');delay(5);write_data('T');break;case 7: write_data('S');delay(5);write_data('U');delay(5);write_data('N');break;}}void keyscan()// 按键设置{if(key3==0)// 功能键按下{flag=0;delay(5);if(key3==0){s1num++;while(!key3);di();switch(s1num)// 光标闪烁定位{case 1:write_com(0x80+0x40+7);// 定位到秒的位置write_com(0x0f);break;case 2:write_com(0x80+0x40+4);// 定位到分的位置write_com(0x0f);break;case 3:write_com(0x80+0x40+1);// 定位到小时的位置write_com(0x0f);break;case 4:write_com(0x80+0x0e);// 定位到星期的位置if(s1num!=0)// 只有功能键按下后,增大, {if(key4==0)// 增大建{delay(5); if(key4==0){while(!key4); di();switch(s1num){case 1: miao++;if(miao==60) miao=0;write_sfm(6,miao); //write_1302(write_second ,miao);write_com(0x80+0x40+7); break;case 2: fen++;if(fen==60) fen=0;write_com(0x0f); break;case 5:write_com(0x80+0x9);// write_com(0x0f); break; case 6:write_com(0x80+0x6);// write_com(0x0f); break; case 7:write_com(0x80+0x3);// write_com(0x0f); break; case 8: s1num=0;// 复位,时钟走 write_com(0x0c); flag=1;write_1302 (0x8e,0x00); write_1302 (0x80,miao); write_1302 (0x82,fen); write_1302 (0x84,shi); write_1302 (0x86,day); write_1302 (0x88,month); write_1302 (0x8c,year); write_1302 (0x8a,week); write_1302 (0x8e,0x80); break;定位到日的位置定位到月的位置 定位到年的位置 // 允许写保护 // 秒位初始化 // 分钟初始化 // 小时初始化 // 日初始化// 月初始化 // 年初始化 // 日期始化 //禁止写Y增小建才有效write_sfm(3,fen);//write_1302(write_minute,fen);write_com(0x80+0x40+4);break;case 3: shi++;if(shi==24) shi=0;write_sfm(0,shi);write_com(0x80+0x40+1);break;case 4: week++;if(week==8)week=1;display_week(week);write_com(0x80+14);break;case 5: day++; if(day==31) day=1;write_nyrz(8,day);write_com(0x80+9); break;case 6: month++; if(month==13)month=1; write_nyrz(5,month);write_com(0x80+6); break;case 7: year++; if(year==99) year=0;write_nyrz(2,year);write_com(0x80+3); break;}}}if(key5==0)// 减小键{delay(5);if(key5==0){while(!key5);di();switch(s1num){case 1: miao--;if(miao==-1) miao=59;write_sfm(6,miao);write_com(0x80+0x40+7);break;case 2: fen--;if(fen==-1) fen=59;write_sfm(3,fen);write_com(0x80+0x40+4);break;case 3: shi--;if(shi==-1) shi=23;write_sfm(0,shi);write_com(0x80+0x40+1);break;case 4: week--;if(week==-1) week=7;display_week(week);write_com(0x80+14); break;case 5: day--;if(day==0) day=31;write_nyrz(8,day);write_com(0x80+9); break;case 6: month--;if(month==0) month=12;write_nyrz(5,month);write_com(0x80+6); break;case 7: year--;if(year==-1) year=99;write_nyrz(2,year);write_com(0x80+3); break;} }}}}void set_alarm(){if(key1==0)// 功能键按下{delay(5);if(key1==0){while(!key1);flag=0;s1num2++;write_sfm(6,amiao);write_com(0x80+0x40+7);write_sfm(3,afen);write_com(0x80+0x40+4);write_sfm(0,ashi);write_com(0x80+0x40+1);di();switch(s1num2)// 光标闪烁定位{case 1:write_com(0x80+0x40+7);// 定位到秒的位置write_com(0x0f);break;case 2:write_com(0x80+0x40+4);// 定位到分的位置write_com(0x0f); break;case 3:write_com(0x80+0x40+1);// 定位到小时的位置write_com(0x0f); break;case 4: s1num2=0;// 复位,时钟走write_com(0x0c);flag=1;write_1302(0x8e,0x00);// 允许写保护write_1302 //(0x8e,0x80);break;if(s1num2!=0)// 只有功能键按下后,增大,增小建才有效{ if(key2==0)// 增大建{delay(5);if(key2==0){while(!key2);di();switch(s1num2){case 1: amiao++;if(amiao==60) amiao=0;write_sfm(6,amiao);write_com(0x80+0x40+7);break;case 2: afen++;if(afen==60)afen=0; write_sfm(3,afen);write_com(0x80+0x40+4);break;case 3: ashi++;if(ashi==24)ashi=0; write_sfm(0,ashi);write_com(0x80+0x40+1);break;}}}WWWWWW-nma-()八-cdwsuainip-nfconfigurafiono 八CDmpchangeo 八fo r (ll'10v 0〒)宀dislCDmp(ge匚 empo)-w h =e 3宀keyscanoy 、^M ffl Bw h i -e ((k ey l QO QO k e y 2QO QO k e y 3QO QO k e y 4QO QO key 5)QO QO ((f e n u u a f e n )QO QO (s h ll'u a s h i )))beep"八if(f-agu") 宀miaouReach302(0X81)7/和引^wriCDlsfm(6ymiao)八fenuReach302(0X83)0和引Vwmelsfm(3fen=shll'Read」3o2(ox85)0 和引亠£4wriCDlsfm(Qshi)八dayuReach302(0X87)0和引mwriCDlnyrzGday)八monfhuReach302(0X89)7/和引出 w r i CD l n yrz(5 -monfh)八year"Reach302(0x8d)y/ 和引<wriCDlnyrz(2yyear)八weekuReacH302(0x8b)y/disp-aylweek(week)八e-sewrite_1302(0x80,0x80);// 时钟振荡器停止}set_alarm();WWW}}。
DS1302+DS18B20+lcd1602完整程序#include <REG51.H>#include <intrins.h>//#include "LCD1602.h"//#include "DS1302.h"#define uint unsigned int#define uchar unsigned charsbit DS1302_CLK = P1^7; //实时时钟时钟线引脚sbit DS1302_IO = P1^6; //实时时钟数据线引脚sbit DS1302_RST = P1^5; //实时时钟复位线引脚sbit wireless_1 = P3^0;sbit wireless_2 = P3^1;sbit wireless_3 = P3^2;sbit wireless_4 = P3^3;sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;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 0x00 // default#define LCD_MOVE 0x01 // 画面可平移#define LCD_NO_MOVE 0x00 //defaultvoid 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 0x84#define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8Cvoid DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数){unsigned char i;ACC = d;for(i=8; i>0; i--){DS1302_IO = ACC0; //相当于汇编中的RRCDS1302_CLK = 1;DS1302_CLK = 0;ACC = ACC >> 1;}}unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数) {unsigned char i;for(i=8; i>0; i--){ACC = ACC >>1; //相当于汇编中的RRCACC7 = DS1302_IO;DS1302_CLK = 1;DS1302_CLK = 0;}return(ACC);}void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据{DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr); // 地址,命令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) //获取时钟芯片的时钟数据到自定义的结构型数组{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);}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'; }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'; //星期的数据另外放到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); //写入允许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子程序*************************/ /***********ds18b20延迟子函数(晶振12MHz )*******/void delay_18B20(unsigned int i){while(i--);}/**********ds18b20初始化函数**********************/void Init_DS18B20(void){unsigned char x=0;DQ = 1; //DQ复位delay_18B20(8); //稍做延时DQ = 0; //单片机将DQ拉低delay_18B20(80); //精确延时大于480usDQ = 1; //拉高总线delay_18B20(14);x=DQ; //稍做延时后如果x=0则初始化成功x=1则初始化失败delay_18B20(20);}/***********ds18b20读一个字节**************/unsigned char ReadOneChar(void){uchar i=0;uchar dat = 0;for (i=8;i>0;i--){DQ = 0; // 给脉冲信号dat>>=1;DQ = 1; // 给脉冲信号if(DQ)dat|=0x80;delay_18B20(4);}return(dat);}/*************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 wery importantInit_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){unsigned int i,j;for(i=0;i<count;i++)for(j=0;j<120;j++);}/*延时子程序*/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); //写入允许Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入done=0;while(out==0);while(wireless_1==1);}}////////////////////////////////////////////////////////////////////////////////////////////////////// //////void Upkey()//升序按键{Up=1;if(Up==0||wireless_2==1){mdelay(8);switch(count){case 1:temp=Read1302(DS1302_SECOND); //读取秒数temp=temp+1; //秒数加1up_flag=1; //数据调整后更新标志if((temp&0x7f)>0x59) //超过59秒,清零temp=0;break;case 2:temp=Read1302(DS1302_MINUTE); //读取分数temp=temp+1; //分数加1up_flag=1;if(temp>0x59) //超过59分,清零temp=0;break;case 3:temp=Read1302(DS1302_HOUR); //读取小时数temp=temp+1; //小时数加1up_flag=1;if(temp>0x23) //超过23小时,清零temp=0;break;case 4:temp=Read1302(DS1302_WEEK); //读取星期数temp=temp+1; //星期数加1up_flag=1;if(temp>0x7)temp=1;break;case 5:temp=Read1302(DS1302_DAY); //读取日数temp=temp+1; //日数加1up_flag=1;if(temp>0x31)temp=1;break;case 6:temp=Read1302(DS1302_MONTH); //读取月数temp=temp+1; //月数加1up_flag=1;if(temp>0x12)temp=1;break;case 7:temp=Read1302(DS1302_YEAR); //读取年数temp=temp+1; //年数加1up_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); //读取秒数temp=temp-1; //秒数减1down_flag=1; //数据调整后更新标志if(temp==0x7f) //小于0秒,返回59秒temp=0x59;break;case 2:temp=Read1302(DS1302_MINUTE); //读取分数temp=temp-1; //分数减1down_flag=1;if(temp==-1)temp=0x59; //小于0秒,返回59秒break;case 3:temp=Read1302(DS1302_HOUR); //读取小时数temp=temp-1; //小时数减1down_flag=1;if(temp==-1)temp=0x23;break;case 4:temp=Read1302(DS1302_WEEK); //读取星期数temp=temp-1; //星期数减1down_flag=1;if(temp==0)temp=0x7;;break;case 5:temp=Read1302(DS1302_DAY); //读取日数temp=temp-1; //日数减1down_flag=1;if(temp==0)temp=31;break;case 6:temp=Read1302(DS1302_MONTH); //读取月数temp=temp-1; //月数减1down_flag=1;if(temp==0)temp=12;break;case 7:temp=Read1302(DS1302_YEAR); //读取年数temp=temp-1; //年数减1down_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就加1done=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();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();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();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();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();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();case 8: count=0;hide_year=0; //count8, 跳出调整模式,返回默认显示状态Second=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入允许Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入done=0;break; //count=7,开启中断,标志位置0并退出default:break;}}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); //显示星期GotoXY(11,0);Print("Week"); //在液晶上显示字母weekDelay1ms(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;while(1){while(done==1)keydone(); //进入调整模式while(done==0){show_time(); //液晶显示数据flag=0;Setkey(); //扫描各功能键}}}。
数字开发与实践课程设计题目:用DS1302与LCD1602设计可调式电子日历时钟班级:姓名:学号:学院:年月日用DS1302与LCD1602设计的可调式电子日历时钟一、总体设计1.1、设计目的为巩固所学的单片机知识,把所学理论运用到实践中,用LCD1602与DS1302 设计可调式电子日历时钟。
1.2、设计要求(1)显示:年、月、日、时、分、秒和星期;(2)设置年、月、日、时、分、秒和星期的初始状态;(3)能够用4个按键调整日历时钟的年、月、日、时、分、秒和星期;完成可调式电子日历时钟的硬件和软件的设计,包括单片机的相关内容;日历时钟模块的设计,液晶显示模块的设计,按键模块的设计。
控制程序的编写等。
备注:本程序另外添加了每到上午8:10和下午2:10的闹钟提醒功能。
1.3、系统基本方案选择和论证1.3.1、单片机芯片的选择方案方案一:采用89C51芯片作为硬件核心,采用Flash ROM,内部具有4KB ROM 存储空间,能于3V的超低压工作,而且与MCS-51系列单片机完全兼容。
方案二:采用STC12C5A60S2系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,是高速/低功耗/超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12倍。
内部集成MAX810专用复位电路,2路PWM,8路高速10位A/D转换(250K/S),针对电机控制,强干扰场合。
但造价较高。
1.3.2 、显示模块选择方案和论证:方案一:采用点阵式数码管显示,点阵式数码管是由八行八列的发光二极管组成,对于显示文字比较适合,如采用显示数字显得太浪费,且价格也相对较高。
所以不用此种作为显示。
方案二:采用LED数码管动态扫描,虽然LED数码管价格适中,但要显示多个数字所需要的个数偏多,功耗较大,显示出来的只是拼音,而不是汉字。
所以也不用此种作为显示。
方案三:采用LCD液晶显示屏,液晶显示屏的显示功能强大,可显示大量字符,且视觉效果较好,外形美观。
H_ADJ BIT P3.0 ;时/年调整M_ADJ BIT P3.1 ;分/月调整S_ADJ BIT P1.4 ;秒/日调整DT_SET BIT P1.5 ;时间/日期选择STR BIT P1.6 ;启动走时T_RST BIT P1.0 ;实时时钟复位线引脚T_CLK BIT P1.1 ;实时时钟时钟线引脚T_IO BIT P1.2 ;实时时钟数据线引脚DL_BIT EQU 20H ;日低位DH_BIT EQU 21H ;日高位MOL_BIT EQU 22H ;月低位MOH_BIT EQU 23H ;月高位YL_BIT EQU 24H ;年低位YH_BIT EQU 25H ;年高位SL_BIT EQU 26H ;秒低位SH_BIT EQU 27H ;秒高位ML_BIT EQU 28H ;分低位MH_BIT EQU 29H ;分高位HL_BIT EQU 2AH ;时低位HH_BIT EQU 2BH ;时高位SEC EQU 30HMIN EQU 31HHOUR EQU 32HDAY EQU 33HMONTH EQU 34HWEEK EQU 35HYEAR EQU 36HFLAG1 BIT 20h.0 ;DS18B20存在标志位DQ BIT P1.3TEMPER_L EQU 59HTEMPER_H EQU 58HA_BIT EQU 55HB_BIT EQU 56HDS1302_ADDR EQU 5EHDS1302_DATA EQU 5FHORG 00HLJMP STARTSTART:MOV SP,#60HMOV TMOD,#11HMOV TH0,#3CHMOV TL0,#0B0HMOV R0,#10SETB EASETB ET0SETB TR0MOV R1,37HMOV YEAR,#13H ;上电预置日期、时间MOV WEEK,#03H ;周1 MONMOV MONTH,#07H ;2011 04 25 12:00:00MOV DAY,#05HMOV HOUR,#23HMOV MIN,#00HMOV SEC,#00HMOV 50H,#0///////////////////////////////////////////////////////////////////////////MAIN: // LCALL DISPLCALL KEYJB F0,MAIN10 ;F0=1,开始走时。
片机万年历汇编闹钟时间可调程序(LCD1602,DS18B20,DS1302,MAX810L)说明:0该程序全部是用汇编语言编写1.该程序附带有温度显示,并且带有闹铃功能2.正常时间和闹钟时间都可以用键盘设置3.该程序是使用LCD1602显示年月日,格式为TIME XX-XX-XX XX,由于屏幕的关系,所以就不显示周的数据,其中闹铃调整的上界面是“BELLADJUST”4.该程序的时间是由时钟芯片DS1302提供的,据说很精准,目前看起来确实是这样的,刚开始我是使用定时器计时的,但是不怎么精准,可能是我的汇编技术有限才导致,所以本人就把这个版本呈上,希望诸位多多斧正5.该程序的温度是通过DS18B20提取的,这个模块是我从别人那里COPY过来的,O(∩_∩)O~,显示是肯定没问题的6.该程序也有用MAX810l的复位功能,但是好像这一点还没被体现出来7.烧程序我使用的是MAX232外加几个极性电容,还有一个RS232,不幸的是我的PCB板的RS232的封装画错啦!!~~~~(>_<)~~~~8.该万年历是由五个按键控制的,SW5复位,SW1调时间,调年月日时分秒,除秒可以加减调节之外其余的调节都是只能加不能减(自我觉得如果增加减的功能会觉得程序复杂,所以免!), SW4 是用来调节闹钟的时分秒的,和SW1按键不同的是时分秒都能加减,当闹钟设置的时间和正常显示时间的时分秒相同时,闹铃十秒钟,期间你可以按SW4键终止响铃,SW2 和SW3 分别是用来加减时间的!9.说了这么多,最后说说自我认为的缺陷,行家应该都一眼就看出一些破绽了,那就是按键消抖的问题,这个我觉得有点麻烦所以本人就把这个问题留给阅览资料的你吧!10.废话说了这么多,最后把我的程序,ORCAD电路原理图,PADS软件的PCB图,以及一张实物图献上,希望你能喜欢,页脚有我的Email(prettyboy2009@),欢迎随时交流!程序:;*************************************************************** ;***************************************************************RS BIT P2.7;P2.5RW BIT P2.6;P2.6E BIT P2.5;P2.7SU BIT P2.1;P1.6 ;1302串行口数据端RST BIT P3.7;P1.5CLK BIT P3.6;P1.7ALARM BIT P1.2;P2.3JIAN BIT P1.0;P2.2 ;减JIA BIT P1.3;P2.1 ;加MOSHI BIT P1.1;P2.0 ;模式DQ BIT P1.4;P1.0SOUND BIT P3.4;P1.3NIAN EQU 7FHYUE EQU 7DHDAY EQU 7CHHHH EQU 7EHSHI EQU 7BHFEN EQU 7AHMIAO EQU 79HASHI EQU 78HAFEN EQU 77HAMIAO EQU 76HA_BIT EQU 70H ;18B20B_BIT EQU 6FHFLAG EQU 6EHDS1302_ADDR EQU 6DHDS1302_DATA EQU 6CHORG 0000HLJMP STARTORG 0030H ;***************************************************************; 初始化开机时间 &&&&&&& 初始化闹铃时间;***************************************************************START:MOV DPTR,#TABMOV SHI,#16HMOV ASHI,#17MOV FEN,#58HMOV AFEN,#30MOV MIAO,#00HMOV AMIAO,#00MOV NIAN,#11HMOV YUE,#12HMOV DAY,#13HMOV HHH,#00H;***************************************************************; 初始化LCD1602 &&&&&&& 初始化DS1302 ;***************************************************************MOV P0,#01H ; 显示清屏数据指针清零所有显示清零LCALL WR_CODEMOV P0,#02H ; 显示回车数据指针清零LCALL WR_CODEMOV P0,#38H ;设置16*2显示 5*7 点阵 8位数据接口LCALL WR_CODEMOV P0,#06H ; 当写或写一个数据时地址指针自动加一光标自动加一LCALL WR_CODEMOV P0,#0cH ; 开显示不显光标 0fh开显示开光标光标闪烁LCALL XIANSHILCALL XIAN1;***************************************************************; 主函数(这个大家都懂的);*************************************************************** MAIN:lcall RD_DS1302LCALL XIANSHIlcall keyLCALL AKEYLCALL RE_TEMPLCALL CONVERLCALL DISPLAY_INTLJMP BELLRING;***************************************************************; 读1302子程序;***************************************************************RD_DS1302:MOV DS1302_ADDR,#8DH ;读DS1302中的年LCALL READ ;调用读DS1302子程序MOV NIAN, DS1302_DATA ;把读出的年数据存入年寄存器中MOV DS1302_ADDR,#89H ;读DS1302中的月LCALL READMOV YUE, DS1302_DATA ;把读出的月数据存入月寄存器中MOV DS1302_ADDR,#87H ;读DS1302中的天LCALL READMOV DAY, DS1302_DATA ;把读出的天数据存入天寄存器中MOV DS1302_ADDR,#85H ;读DS1302中的小时LCALL READMOV SHI, DS1302_DATA ;把读出的天数据存入小时寄存器中MOV DS1302_ADDR,#83H ;读DS1302中的分钟LCALL READMOV FEN, DS1302_DATA ;把读出的天数据存入分钟寄存器中MOV DS1302_ADDR,#81H ;读DS1302中的秒钟LCALL READMOV MIAO, DS1302_DATA ;把读出的天数据存入秒钟寄存器中RET ;***************************************************************; 写1302子程序;***************************************************************WR_DS1302:MOV DS1302_ADDR, #8EH ;写DS1302控制指令MOV DS1302_DATA, #00H ;写数据到DS1302的8E控制寄存器中,允许对其进行写操作LCALL WRITE ;调用写DS1302子程序MOV DS1302_ADDR,#8CH ;写DS1302中的年MOV DS1302_DATA , NIAN ;把写出的年数据存入年寄存器中LCALL WRITEMOV DS1302_ADDR,#88H ;写DS1302中的月MOV DS1302_DATA ,YUE ;把写出的月数据存入月寄存器中LCALL WRITEMOV DS1302_ADDR,#86H ;写DS1302中的天MOV DS1302_DATA ,DAY ;把写出的天数据存入天寄存器中LCALL WRITEMOV DS1302_ADDR,#84H ;写DS1302中的小时MOV DS1302_DATA , SHI ;把写出的天数据存入小时寄存器中LCALL WRITEMOV DS1302_ADDR,#82H ;写DS1302中的分钟MOV DS1302_DATA , FEN ;把写出的天数据存入分钟寄存器中LCALL WRITEMOV DS1302_ADDR,#80H ;写DS1302中的秒钟MOV DS1302_DATA , MIAO ;把写出的天数据存入秒钟寄存器中LCALL WRITEMOV DS1302_ADDR, #90H ;写DS1302控制指令MOV DS1302_DATA,#0A6H ;写数据到DS1302的90控制寄存器中,LCALL WRITE ;调用写DS1302子程序RET;***************************************************************; 写1302程序;***************************************************************WRITE:CLR CLKNOPSETB RSTNOPMOV A,DS1302_ADDRMOV R4,#8 WRITE1:RRC A ;送地址给1302NOPNOPCLR CLKNOPNOPNOPMOV SU,CSETB CLK ;送入地址在时钟上升沿有效NOPNOPNOPNOPDJNZ R4,WRITE1CLR CLKNOPMOV A,DS1302_DATAMOV R4,#8 WRITE2:RRC ANOP ;送数据给1302,时钟上升沿,数据输入CLR CLKNOPNOPMOV SU,CNOPNOPNOPNOPDJNZ R4,WRITE2CLR RSTCLR ARET ;***************************************************************; 读1302程序;***************************************************************READ:CLR CLKNOPNOPSETB RSTNOPMOV A,DS1302_ADDRMOV R4,#8 READ1:RRC ANOPMOV SU,CNOPNOPNOPSETB CLK ;送入地址在时钟上升沿有效NOPNOPNOPCLR CLKNOPNOPDJNZ R4,READ1 ;判断8位数据是否传送完?MOV R4,#8 READ2:CLR CLKNOPNOPNOPMOV C,SUNOPNOPNOPNOPNOP ;从ds1302中读取数据,时钟下NOPNOPNOPNOPSETB CLKNOPDJNZ R4,READ2 ;判断8位数据是否传送完?MOV DS1302_DATA,ACLR RSTRET;***************************************************************; 固定显示显示TIME ,'-',:;***************************************************************XIAN1:MOV P0,#84HLCALL WR_CODEMOV A,#'-' ;1602有字库可以直接调用不用查表LCALL WR_DATAMOV P0,#87HLCALL WR_CODEMOV A,#'-'LCALL WR_DATAMOV P0,#80HLCALL WR_CODEMOV A,#'2' ;计时100年所以20XX 20是固定的LCALL WR_DATAMOV P0,#81HLCALL WR_CODEMOV A,#'0'LCALL WR_DATAMOV P0,#0C1HLCALL WR_CODEMOV A,#'T'LCALL WR_DATAMOV P0,#0C2HLCALL WR_CODEMOV A,#'I'LCALL WR_DATAMOV P0,#0C3HLCALL WR_CODEMOV A,#'M'LCALL WR_DATALCALL WR_CODEMOV A,#'E'LCALL WR_DATAMOV P0,#0CCHLCALL WR_CODEMOV A,#':'LCALL WR_DATAMOV P0,#0C9HLCALL WR_CODEMOV A,#':'LCALL WR_DATAMOV P0,#08EHLCALL WR_CODEMOV A,#0DFHLCALL WR_DATAMOV P0,#08FHLCALL WR_CODEMOV A,#'C'LCALL WR_DATARET;*************************************************************** ; 显示数据时分秒年月日周地址数据都在变化没用循环体;***************************************************************XIANSHI:MOV HHH,MIAOLCALL HEXMOV P0,#0CDHLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV A,BMOV P0,#0CEHLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV HHH,FENLCALL HEXMOV P0,#0CAHLCALL WR_CODEMOVC A,@A+DPTRMOV A,BMOV P0,#0CBH LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATAMOV HHH,SHI LCALL HEXMOV P0,#0C7H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATA MOV A,BMOV P0,#0C8H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATAMOV HHH,DAY LCALL HEXMOV P0,#088H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATA MOV A,BMOV P0,#089H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATAMOV HHH,YUE LCALL HEXMOV P0,#085H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATA MOV A,BMOV P0,#086H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATAMOV HHH,NIAN LCALL HEXLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV A,BMOV P0,#083HLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATARET;***************************************************************; 判键子程按一次模式键后就一直判断下一次按键是P2.1还是P2.2;判断进入下一模式还是加1(按下模式键第一次加1需要按两次);MO1加分 MO2加时 MO3加月 MO4加日 MO5加年,除秒可以加减调节外,;时间只能通过加分时日月年调节;***************************************************************KEY:JNB MOSHI,MORET MO:JNB MOSHI,$MOV P0,#0DH ; 开显示不显光标 0fh开显示开光标光标闪烁LCALL WR_CODE MO1:MOV P0,#0CBHLCALL WR_CODEJNB JIA,JIAFFJNB JIAN,JIANFFJNB MOSHI,MO11LJMP MO1 MO11:JNB MOSHI,$;MO2:MOV P0,#0C8HLCALL WR_CODEJNB JIA,JIASSJNB MOSHI,MO21LJMP MO2 MO21:JNB MOSHI,$; ;MO4:MOV P0,#089HJNB JIA,JIADDJNB MOSHI,MO41LJMP MO4 MO41:JNB MOSHI,$MO3:MOV P0,#086HLCALL WR_CODEJNB JIA,JIAMMJNB MOSHI,MO31LJMP MO3 MO31:JNB moshi,$;MO5:MOV P0,#083HLCALL WR_CODEJNB JIA,JIAYYJNB MOSHI,MO51LJMP MO5 MO51:JNB MOSHI,$MOV P0,#0CH ; 开显示不显光标 0fh开显示开光标光标闪烁LCALL WR_CODElcall XIAN1RET;***************************************************************; 跳转出范围中转;***************************************************************JIAFF:LJMP JIAFJIANFF:LJMP JIANFJIADD:LJMP JIADJIAMM:LJMP JIAMJIAYY:LJMP JIAYJIASS:LJMP JIAS;***************************************************************;判断加1 以及跳转到另一模式(模式是指加分还是加时加月等);***************************************************************JIAF:MOV P0,#0CBHJIAF2:JNB MOSHI,JIAF1JNB JIAN,JIANFJB JIA,JIAF2JNB JIA,$mov A,FENADD A , #01HDA Amov FEN,ACJNE A , #60H ,JIAF3MOV FEN ,#00H JIAF3:LCALL WR_DS1302LCALL XIANSHILJMP JIAF JIAF1:JNB MOSHI,$LJMP MO11JIANF:MOV P0,#0CBHLCALL WR_CODEJNB MOSHI,JIANF1JNB JIA,JIAFJB JIAN,JIANFJNB JIAN,$MOV A,FENCJNE A,#00,JIANF2MOV FEN,#59HLJMP JIANF3 JIANF2:CLR CSUBB A,#01DA AMOV FEN,A JIANF3:LCALL WR_DS1302LCALL XIANSHILJMP JIANF JIANF1:JNB MOSHI,$LJMP MO11 JIAS:JIAS2:JNB MOSHI,JIAS1JB JIA,JIAS2JNB JIA,$MOV A,SHIADD A,#01HDA AMOV SHI,ACJNE A,#24H,JIAS3MOV SHI,#00 JIAS3:LCALL WR_DS1302LCALL XIANSHILJMP JIAS JIAS1:JNB MOSHI,$LJMP MO21JIAD:MOV P0,#089HLCALL WR_CODEJIAD2:JNB MOSHI,JIAD1JB JIA,JIAD2JNB JIA,$MOV A,DAYADD A,#01HDA AMOV DAY,AMOV A,YUECJNE A,#01H,SS1LJMP JIAD4 SS1:CJNE A,#03H,SS2 LJMP JIAD4 SS2:CJNE A,#05H,SS3LJMP JIAD4 SS3:CJNE A,#07H,SS4LJMP JIAD4LJMP JIAD4 SS5:CJNE A,#10H,SS6LJMP JIAD4 SS6:CJNE A,#12H,SSS JIAD4:MOV A,DAYCJNE A,#32H,JIAD3MOV DAY,#01H JIAD3:LCALL WR_DS1302LCALL XIANSHILJMP JIAD JIAD1:JNB MOSHI,$LJMP MO41 SSS:CJNE A,#02H,S30MOV A,NIANANL A,#0FHMOV GEW,AMOV A,NIANANL A,#0F0HSWAP AMOV B,#10MUL ABADD A,GEWMOV B,#04HDIV ABMOV A,BCJNE A,#00H,S29LJMP S28 S30:MOV A,DAYCJNE A,#31H,JIAD3MOV DAY,#01HLJMP JIAD3 S29:MOV A,DAYCJNE A,#29H,JIAD3MOV DAY,#01HLJMP JIAD3CJNE A,#30H,JIAD3MOV DAY,#01HLJMP JIAD3;***************************************************************;;判断月的天数判断闰年的方法先将年的数据有十六进制BCD码转换成正常的十六进制;再除以4 判断余数是否为0 为零则为闰年不为零不是;***************************************************************JIAM:MOV P0,#086HLCALL WR_CODE JIAM2:JNB MOSHI,JIAM1JB JIA,JIAM2JNB JIA,$MOV A,YUEADD A,#01HDA AMOV YUE,ACJNE A,#13H,JIAM3MOV YUE,#01 JIAM3:LCALL WR_DS1302LCALL XIANSHI JIAM1:JNB MOSHI,$LJMP MO31 JIAY:MOV P0,#083HLCALL WR_CODE JIAY2:JNB MOSHI,JIAY1JB JIA,JIAY2JNB JIA,$MOV A,NIANADD A,#01HDA AMOV NIAN,ACJNE A,#99H,JIAY3MOV NIAN,#00 JIAY3:LCALL WR_DS1302LCALL XIANSHI;***************************************************************;温度读取;************************************************************ ***RE_TEMP:SETB DQACALL INIT_18B20JB FLAG, STRET ST:MOV A, #0CCHACALL WRITE_18B20MOV A, #44HACALL WRITE_18B20ACALL INIT_18B20MOV A, #0CCHACALL WRITE_18B20MOV A, #0BEHACALL WRITE_18B20ACALL READ_18B20RET;***************************************************************;初始化DS18B20;***************************************************************INIT_18B20:SETB DQNOPCLR DQMOV R1, #3 DLY:MOV R0, #107DJNZ R0, $DJNZ R1, DLYSETB DQNOPNOPNOPMOV R0, #25H T2:JNB DQ, T3DJNZ R0, T2JMP T4 T3:SETB FLAGCLR FLAGJMP T7 T5:MOV R0, #117 T6:DJNZ R0, T6 T7:SETB DQRET ;***************************************************************;写DS18B20;***************************************************************WRITE_18B20:MOV R2, #8CLR C WR1:CLR DQMOV R3, #6DJNZ R3, $RRC AMOV DQ, CMOV R3, #23DJNZ R3, $SETB DQNOPDJNZ R2, WR1SETB DQRET;***************************************************************;读DS18B20;***************************************************************READ_18B20:MOV R4, #2MOV R1, #21H RE0:MOV R2, #8 RE1:CLR CSETB DQNOPNOPCLR DQNOPNOPSETB DQMOV R3, #9 RE2:DJNZ R3, RE2MOV C, DQMOV R3, #23 RE3:DJNZ R3, RE3RRC ADJNZ R2, RE1MOV @R1, ADEC R1DJNZ R4, RE0RET;***************************************************************;温度转换;***************************************************************CONVER:MOV A, 21HMOV C, 20H.0RRC AMOV C, 20H.1RRC AMOV C, 20H.2RRC AMOV C, 20H.3RRC AMOV 21H, ARET;***************************************************************;显示温度整数部分;***************************************************************DISPLAY_INT:MOV A, 21HMOV B, #10DIV ABMOV B_BIT, AMOV A_BIT, BMOV DPTR, #TABMOV P0,#08cHLCALL WR_CODEMOV A, B_BITMOVC A, @A+DPTRLCALL WR_DATAMOV P0,#08DHLCALL WR_CODEMOV A, A_BITMOVC A, @A+DPTRLCALL WR_DATARET;***************************************************************; 1602的写数据读指令判忙程序;***************************************************************WR_DATA:MOV P0,ASETB RS ;RS=1选择数据寄存器CLR RW ;RW=0 ;准备CLR E ;E=0 ;执行显示命令LCALL BUSY ;判断液晶模块是否忙?SETB E ;E=1 ;显示完成,程序停车RET WR_CODE:CLR RS ;写入控制命令的子程序CLR RWCLR ELCALL BUSYSETB ERET BUSY:MOV P0,#0FFH ;判断液晶显示器是否忙的子程序CLR RSSETB RWCLR ENOP ;nop一定要有SETB EJB P0.7,BUSY ;如果P0.7为高电平表示忙就循环等待RET ;***************************************************************; 判键子程按一次模式键后就一直判断下一次按键是P3.4还是P3.5 判断进入下一模式还是加1(按下模式键第一次加1需要按两次);***************************************************************AKEY:JNB ALARM, XIANGUANGRET XIANGUANG:JNB ALARM,$MOV P0,#01H ; 显示清屏数据指针清零所有显示清零LCALL WR_CODEMOV P0,#02H ; 显示回车数据指针清零LCALL WR_CODEMOV P0,#038H ;设置16*2显示 5*7 点阵 8位数据接口LCALL WR_CODEMOV P0,#04H ; 当读或写一个数据时地址指针自动加一光标自动加一LCALL WR_CODEMOV P0,#0DH ; 开显示不显光标 0fh开显示开光标光标闪烁LCALL WR_CODELCALL AXIANLCALL AXIANSHIMOMIAO: MOV P0,#0CBHLCALL WR_CODEJNB JIA,INCMJNB JIAN,DECMJNB ALARM ,BACKMIAOLJMP MOMIAO BACKMIAO:JNB ALARM,$LJMP MOFENINCM:MOV P0,#0CBHLCALL WR_CODE INCM2:JNB ALARM,INCM1JNB JIAN,DECMJB JIA,INCM2JNB JIA,$INC AMIAOMOV A,AMIAOCJNE A,#60,INCM3MOV AMIAO,#00 INCM3:LCALL AXIANSHILJMP INCM INCM1:JNB ALARM ,BACKMIAODECM:MOV P0,#0CBHLCALL WR_CODEJNB ALARM,DECM1JNB JIA,INCMJB JIAN,DECMJNB JIAN,$MOV A,AMIAOCJNE A,#00,DECM2MOV AMIAO,#59LJMP DECM3 DECM2:CLR CSUBB A,#01MOV AMIAO,A DECM3:LCALL AXIANSHILJMP DECM DECM1:JNB ALARM,BACKMIAOMOFEN:MOV P0,#0C8HLCALL WR_CODEJNB JIA,INCFJNB JIAN,DECFJNB ALARM ,BACKFENLJMP MOFEN BACKFEN:JNB ALARM,$LJMP AMOSHIINCF:MOV P0,#0C8HLCALL WR_CODEINCF2:JNB ALARM,INCF1JNB JIAN,DECFJB JIA,INCF2JNB JIA,$INC AFENMOV A,AFENCJNE A,#60,INCF3MOV AFEN,#00INCF3:LCALL AXIANSHILJMP INCFINCF1:JNB ALARM ,BACKFENDECF:MOV P0,#0C8HLCALL WR_CODEJNB ALARM,DECF1JNB JIA,INCFJB JIAN,DECFJNB JIAN,$MOV A,AFENCJNE A,#00,DECF2MOV AFEN,#59LJMP DECF3DECF2:CLR C;DEC ASUBB A,#01;DA AMOV AFEN,ADECF3:LCALL AXIANSHILJMP DECFDECF1:JNB ALARM,BACKFENAMOSHI:MOV P0,#0C5HLCALL WR_CODEJNB JIA,INCSJNB JIAN,DECSJNB ALARM ,BACKSHI LJMP AMOSHIINCS:MOV P0,#0C5HLCALL WR_CODEINCS2:JNB ALARM,INCS1JNB JIAN,DECSJB JIA,INCS2JNB JIA,$INC ASHIMOV A,ASHICJNE A,#24,INCS3MOV ASHI,#00INCS3:LCALL AXIANSHILJMP INCSINCS1:JNB ALARM ,BACKSHIBACKSHI:JNB ALARM,$MOV P0,#01HLCALL WR_CODEMOV P0,#0CHLCALL WR_CODELCALL XIAN1LJMP MAINDECS:MOV P0,#0C5HLCALL WR_CODEJNB ALARM,DECS1JNB JIA,INCSJB JIAN,DECSJNB JIAN,$MOV A,ASHICJNE A,#00,DECS2MOV ASHI,#23LJMP DECS3 DECS2:CLR CSUBB A,#01MOV ASHI,A DECS3:LCALL AXIANSHILJMP DECS DECS1:JNB ALARM,BACKSHI;***************************************************************; 闹钟部分固定显示显示TIME ADJUST;***************************************************************AXIAN:MOV P0,#82HLCALL WR_CODEMOV A,#'B'LCALL WR_DATAMOV P0,#83HLCALL WR_CODEMOV A,#'E'LCALL WR_DATAMOV P0,#84HLCALL WR_CODEMOV A,#'L' ;LCALL WR_DATAMOV P0,#85HLCALL WR_CODEMOV A,#'L'LCALL WR_DATAMOV P0,#088HLCALL WR_CODEMOV A,#'A'LCALL WR_DATAMOV P0,#089HLCALL WR_CODEMOV A,#'D'LCALL WR_DATAMOV P0,#08AHLCALL WR_CODEMOV A,#'J'LCALL WR_DATAMOV P0,#08BHLCALL WR_CODEMOV A,#'U'LCALL WR_DATAMOV P0,#08CHLCALL WR_CODEMOV A,#'S'LCALL WR_DATAMOV P0,#08DHLCALL WR_CODEMOV A,#'T'LCALL WR_DATAMOV P0,#0C6HLCALL WR_CODEMOV A,#':'LCALL WR_DATAMOV P0,#0C9HLCALL WR_CODEMOV A,#':'LCALL WR_DATARET;*************************************************************** ; 显示数据时分秒年月日周地址数据都在变化没用循环体;*************************************************************** AXIANSHI:MOV HHH,AMIAOLCALL AHEXMOV P0,#0CAHLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV A,BMOV P0,#0CBHLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV HHH,AFENLCALL AHEXMOV P0,#0C7HLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV A,BMOV P0,#0C8HLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV HHH,ASHILCALL AHEXMOV P0,#0C4HLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV A,BMOV P0,#0C5HLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATARET;***************************************************************; 分离十进制BCD码中的十位和个位;***************************************************************AHEX: MOV A,HHHMOV B,#10DIV ABRET;***************************************************************; 闹钟模块;***************************************************************;==========================条件符合响铃1分钟============================ BELLRING:MOV HHH,SHILCALL HEXMOV R2,BMOV B,#10MUL ABADD A,R2CJNE A ,ASHI, AAAMOV HHH,FENLCALL HEXMOV R2,BMOV B,#10MUL ABADD A,R2CJNE A ,AFEN,AAAMOV HHH,MIAOLCALL HEXMOV R2,BMOV B,#10MUL ABADD A,R2CJNE A ,AMIAO,AAALCALL BELLRAAA:LJMP MAIN;==========================闹钟响铃10秒钟============================BELLR:MOV COUNT,#10ZZZ:SETB SOUNDLCALL DELAY500MSCLR SOUNDLCALL DELAY500MSlcall RD_DS1302LCALL XIANSHIJNB ALARM ,BBBDJNZ COUNT ,ZZZBBB:JNB ALARM ,$SETB SOUNDRET;==========================设置闹铃延时500MS响一次=================== DELAY500MS:MOV R7,#17HDL1:MOV R6,#98HDL0:MOV R5,#46HDJNZ R5,$DJNZ R6,DL0DJNZ R7,DL1RET;*************************************************************** ; 转换成BCD码;*************************************************************** ZHUAN:MOV A,HHHADD A,#00HDA ARET;*************************************************************** ; 分离BCD码中的十位和个位;*************************************************************** HEX:MOV A,HHHMOV B,#16DIV ABRET;*************************************************************** ; 数据查表;*************************************************************** TAB: DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39HENDORCAD电路原理图PADS软件的PCB图实物图。