89C52单片机 DS1302 DS18B20 17位数码管万年历

合集下载

DS1302 DS18B20 LCD1602经典万年历 高低温报警

DS1302    DS18B20   LCD1602经典万年历  高低温报警

/*********************************************//* 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');}}。

数码管万年历ds1302

数码管万年历ds1302

/ZPF(新)//2012//4/29#include <REGX55.H>#include<intrins.h>#define uint unsigned int#define uchar unsigned charuchar k,s,aa,Nshi,Nfen;//,miao,nian,yue,ri,zhou;uchar number[8];uchar dif_flag;//测温度定义uint temp;float f_temp; //温度值variable of temperature bit flag;sbit w1=P1^2;sbit w2=P1^3;sbit w3=P1^4;sbit w4=P1^5;sbit DQ=P1^7;sbit dula=P1^0;sbit wela=P1^1;sbit DS1302_CLK = P3^7; //实时时钟时钟线引脚sbit DS1302_IO = P3^6; //实时时钟数据线引脚sbit DS1302_RST = P3^5; //实时时钟复位线引脚sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;sbit key=P1^6;sbit key1=P3^0;sbit key2=P3^1;sbit key3=P3^2;sbit key4=P3^3;sbit key5=P3^4;uchar read[7];uchar table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0x00};//共阴数码管0-9uchar week_value[2];//void dis_delay(void);void delay(uint x);void display(unsigned char a,unsigned char b,unsigned char c);void show_time(); //显示程序void Write1302(unsigned char ucAddr, unsigned char ucDa);void keyscan();void Display_18b20(uint temp);/***********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;}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) //实时时钟写入一字节(内部函数)(4) {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) //实时时钟读取一字节(内部函数)(5) {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;//只有在clk为低时,才能将rst置高DS1302InputByte(ucAddr); // 地址,命令DS1302InputByte(ucDa); // 写1Byte数据DS1302_CLK = 1;//上升沿将数据写入DS1302内部移位寄存器DS1302_RST = 0;}unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据(3){unsigned char ucData;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;//启动数据传送DS1302InputByte(ucAddr|0x01); // 地址,命令,读操作(4)ucData = DS1302OutputByte(); // 读1Byte数据,应在上升沿前读取(5)DS1302_CLK = 1;DS1302_RST = 0;return(ucData);}void naozhong(uchar x){uchar c = 0;c = 4 * x;Nfen = 0xc1 + c;Nshi = 0xc3 + c;}/***********DS1302按键部分子程序******************/void jia(uchar p, uchar max, uchar com)//p读取时间单位的值,max进制,com地址{p = ((p & 0x70) >>4 ) * 10 + (p & 0x0f);p ++;if(p / max)p =0 ;p = (p / 10) * 16 + p % 10;Write1302(com, p);}void jian(uchar p, uchar max, uchar com)//p读取秒的值,max进制,com地址{p = ((p & 0x70) >>4 ) * 10 + (p & 0x0f);p --;if(p == 255)p = max ;p = (p / 10) * 16 + p % 10;Write1302(com,p);}void keyscan(){if(!key1){delay(5);if(!key1 ){k++;Write1302(0x8e,0x00);if(k==4)k=0, Write1302(0x8e,0x80);while(!key1);}}if(!key2){delay(5);if(!key2){if(dif_flag == 0){switch(k){case 1:jia(Read1302(DS1302_SECOND), 60, 0x80); break;case 2:jia(Read1302(DS1302_MINUTE), 60, 0x82); break;case 3:jia(Read1302(DS1302_HOUR), 24, 0x84); break;}}if(dif_flag == 1){switch(k){case 1:jia(Read1302(DS1302_DAY), 32, 0x86); break;case 2:jia(Read1302(DS1302_MONTH), 13, 0x88); break;case 3:jia(Read1302(DS1302_YEAR), 100, 0x8c); break;}}if(dif_flag == 2){if(k == 1)jia(Read1302(DS1302_WEEK), 8, 0x8a);}while(!key2);}}if(!key3){delay(5);if(!key3){if(dif_flag == 0){switch(k){case 1:jian(Read1302(DS1302_SECOND), 60, 0x80); break;case 2:jian(Read1302(DS1302_MINUTE), 60, 0x82); break;case 3:jian(Read1302(DS1302_HOUR), 24, 0x84); break;}}if(dif_flag == 1){switch(k){case 1:jian(Read1302(DS1302_DAY), 32, 0x86); break;case 2:jian(Read1302(DS1302_MONTH), 13, 0x88); break;case 3:jian(Read1302(DS1302_YEAR), 100, 0x8c); break;}}if(dif_flag == 2){if(k == 1)jian(Read1302(DS1302_WEEK), 8, 0x8a);}while(!key3);}if(key5 ==0);//key5 = 1;}void DS1302_GetTime(SYSTEMTIME *Time) //获取时钟芯片的时钟数据到自定义的结构型数组(2){unsigned char ReadV alue;ReadValue = Read1302(DS1302_SECOND);//(3)Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//16进制转为10进制ReadValue = Read1302(DS1302_MINUTE);Time->Minute = ((ReadV alue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_HOUR);Time->Hour = ((ReadV alue&0x70)>>4)*10 + (ReadV alue&0x0F);ReadValue = Read1302(DS1302_DAY);Time->Day = ((ReadV alue&0x70)>>4)*10 + (ReadV alue&0x0F);ReadValue = Read1302(DS1302_WEEK);Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadV alue&0x0F);ReadValue = Read1302(DS1302_MONTH);Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_YEAR);Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadV alue&0x0F);}void show_time() //液晶显示程序(1){uchar f=2;DS1302_GetTime(&CurrentTime); //获取时钟芯片的时间数据(2)read[0]=CurrentTime.Second;read[1]=CurrentTime.Minute;read[2]=CurrentTime.Hour;read[3]=CurrentTime.Week;read[4]=CurrentTime.Day;read[5]=CurrentTime.Month;read[6]=CurrentTime.Year;read[7]=0x00;if(!key){delay(5);if(!key)dif_flag++;while(!key)if(!key5){Write1302(0x8e,0x00);//写写保护寄存器禁止写保护Write1302(0x80,0x00);//写秒Write1302(0x90,0xab);//写充电寄存器Write1302(0x82,0x00);//分Write1302(0x84,0x12);//时Write1302(0x86,0x01);//日Write1302(0x88,0x05);//月Write1302(0x8a,0x02);//周Write1302(0x8c,0x12);//年Write1302(0x8e,0x80);//写保护}}}if(dif_flag==3)dif_flag=0;for(f=2;f>0;f--){if(dif_flag==0)display(read[0],read[1],read[2]);else if(dif_flag==1)display(read[4],read[5],read[6]);else if(dif_flag==2)display(read[3],read[7],read[7]);}}//显示延时函数void dis_delay(uchar x){uchar i;for(i=0;i<x;i++);}void delay(uint x){uint i,j;for(i=x;i>0;i--)for(j=110;j>0;j--);}/*****************DS18B20******************/void Init_Ds18b20(void) //DS18B20初始化send reset and initialization command {uint i;DQ = 0; //单片机拉低总线i=70;while(i>0)i--;DQ = 1; //释放总线,即拉高了总线i=4;while(i>0)i--;}bit Read_One_bit() //读取一个字节的数据read a byte date//读数据时,数据以字节的最低有效位先从总线移出{uint i;bit dat;DQ=0;i++;DQ=1;i++;i++;dat=DQ;i=5;while(i>0)i--;return (dat);}uchar Read_One_Byte(void){uchar i,j,dat;dat=0;for(i=1;i<=8;i++){j=Read_One_bit();dat=(j<<7)|(dat>>1);}return (dat);}void Write_One_Byte(uchar dat){uint i;uchar j;bit testb;show_time();for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb){DQ=0;i++;i++;DQ=1;i=5;while(i>0)i--;}else{DQ=0;i=5;while(i>0)i--;DQ=1;i++;i++;}}}void tmpchange(void){uchar f;Init_Ds18b20();f=70;while(f>0)f--;Write_One_Byte(0xcc); //忽略ROM指令Write_One_Byte(0x44); //温度转换指令}uint Get_Tmp() //获取温度get the temperature{uchar a,b,f;Init_Ds18b20(); //初始化f=70;while(f>0)f--;show_time();Write_One_Byte(0xcc); //忽略ROM指令Write_One_Byte(0xbe); //温度转换指令a = Read_One_Byte(); //读取到的第一个字节为温度LSBb = Read_One_Byte(); //读取到的第一个字节为温度MSBshow_time();if(b>127){flag=1;a=~a;b=~b;a+=0x01;}else{flag=0;}temp = b; //先把高八位有效数据赋于temptemp <<= 8; //把以上8位数据从temp低八位移到高八位temp = temp|a; //两字节合成一个整型变量f_temp = temp*0.0625; ////temp = (f_temp*10+0.5)*0.9; //放大十倍//0.9调试加上理论不需要temp = f_temp*10+0.5;//f_temp=f_temp+0.5; // //同时进行一个四舍五入操作。

ds1302_万年历

ds1302_万年历

/***************************************************************系统名称:电子万年历日期:2008,7,18功能描述:LCD12864串行模式显示,DS1302读取时间年月份,18B20 读取温度****************************************************************/#include <reg51.h>#include <intrins.h>#include <stdio.h>#define uchar unsigned char#define uint unsigned int/*------------LCD12864相关声明-----------------------------*/#define com 0#define dat 1sbit cs =P1^6;sbit sid=P1^4;sbit sck=P1^2;uchar code TAB1[]={"电字钟w418781840"};//第一行初始化.uchar code TAB2[]={"20 年月日"}; //第二行uchar code TAB3[]={"星期: : "}; //第三行uchar code TAB4[]={"室温: ℃"}; //第四行/*----------------------DS1302相关声明-------------------------*/char TAB_1302[]={ 0x00,0x29,0x02, //秒:分:时.0x18,0x06,0x06,0x08}; //日:月:星期:年.uchar code TAB_XQ[]={"一二三四五六日"};//把DS1302数字日期转换为中文字符. sbit T_CLK=P2^4; /* 实时时钟的时钟线引脚*/sbit T_IO=P2^5; /* 实时时钟的数据线*/sbit T_RST=P2^6; /* 实时时钟的复位线引脚*/uchar bdata datbyte;sbit datbyte0=datbyte^0;sbit datbyte7=datbyte^7;/*--------------18B20相关声明-------------------------------*/uchar dis1[16];sbit DQ=P1^0; /*DS18B20温度检测*//*----------键盘相关声明-------------------------------------*/sbit key=P3^2; //功能键sbit key1=P3^3; //只有加1键uchar sum,keyflag=0; //调用时,分,秒,标志,调用键盘处理标志./*--------------以下为LCD12864相关函数--------------------------*//**************************************************************函数名称:void delay1ms(uint x)函数功能: 延时1MS***************************************************************/void delay1ms(uint x){uint i,j;for(i=0;i<x;i++)for(j=0;j<120;j++);}/************************************************************** 函数名称:void w_12864byte(uchar byte)函数功能: 写字节**************************************************************/ void w_12864byte(uchar byte){uchar i;for(i=0;i<8;i++){sck=0;byte<<=1;sid=CY;sck=1;}}/************************************************************** 函数名称:uchar r_12864byte(void)函数功能: 读字节***************************************************************/ uchar r_12864byte(void){uchar i,temp1,temp2;temp1 = 0;temp2 = 0;for(i=0;i<8;i++){temp1=temp1<<1;sck = 0;sck = 1;sck = 0;if(sid) temp1++;}for(i=0;i<8;i++){temp2=temp2<<1;sck = 0;sck = 1;sck = 0;if(sid) temp2++;}return ((0xf0&temp1)+(0x0f&temp2));}/************************************************************** 函数名称:void c_12864busy( void )函数功能: 检测忙函数**************************************************************/ void c_12864busy( void ){dow_12864byte(0xfc); //11111,RW(1),RS(0),0while(0x80&r_12864byte());}/************************************************************** 函数名称:void w_12864(bit dat_com,uchar byt)函数功能: 写入函数***************************************************************/ void w_12864(bit dat_com,uchar byt){uchar temp;if(dat_com==0) //为零,写入指令temp=0xf8; //11111,RS(0),RW(0),0else //否则,写入数据temp=0xfa; //11111,RS(1),RW(0),0cs=1;c_12864busy();w_12864byte(temp);w_12864byte(byt&0xf0); //写入高四位w_12864byte(byt<<4); //写入低四位cs=0;}/************************************************************** 函数名称:void init_12864(void)函数功能:初始化12864***************************************************************/ void init_12864(void){w_12864(com,0x30); //基本指令功能.w_12864(com,0x0c); //显示打开,关光标,反白关.w_12864(com,0x01); //清屏指令.w_12864(com,0x06); //AC自动加一}/*----------------以下为DS1302相关函数-------------------------*//************************************************************** 函数名称:void w_1302byte(uchar date)函数功能:写一个字节(上升沿)***************************************************************/ void w_1302byte(uchar date){ uchar i;datbyte=date;for(i=0;i<8;i++){ T_IO=datbyte0; //写最低位T_CLK=0;T_CLK=1;datbyte>>=1;}}/************************************************************** 函数名称:uchar r_1302byte(void)函数功能:读一个字节(下降沿)***************************************************************/ uchar r_1302byte(void){ uchar i;datbyte=0;for(i=0;i<8;i++){ datbyte7=T_IO; //读最低位T_CLK=1;T_CLK=0;datbyte>>=1;}return(datbyte);}/*************************************************************** 函数名称:void write_1302(uchar addr,uchar date)函数功能: 指定位置写数据****************************************************************/ void write_1302(uchar addr,uchar date){ T_RST=0;T_CLK=0;T_RST=1;w_1302byte(addr);w_1302byte(date);T_CLK=0;T_RST=0;}/************************************************************** 函数名称:uchar read_1302(uchar addr)函数功能: 指定位置读数据****************************************************************/ uchar read_1302(uchar addr){ uchar dat1,dat2,temp;T_RST=0;T_CLK=0;T_RST=1;w_1302byte(addr);temp=r_1302byte();T_RST=0;T_CLK=0;dat1=temp/16;dat2=temp%16;temp=dat1*10+dat2;return(temp);}/***************************************************************函数名称:void init_1302(void)函数功能: 初始化*****************************************************************/ void init_1302(void){ uchar i;uchar addr=0x80;write_1302(0x8e,0x00);for(i=0;i<7;i++){write_1302(addr,TAB_1302[i]);addr+=2;}write_1302(0x8e,0x80);}/**************************************************************** 函数名称:void get_1302(void)功能说明:读取DS1302时钟信息.*****************************************************************/ void get_1302(void){ uchar i,addr=0x81;for(i=0;i<7;i++){ TAB_1302[i]=read_1302(addr);addr+=2;}}/*---------------以下为18B20相关函数-----------------------------*//******************************************************************函数名称:void delay (uint x)功能说明:若机器周期为1us,则本延时程序为延时4*x(us)******************************************************************/ void delay (uint x) //本板延时8us{while (--x);}/***************************************************************** 函数名称:uchar bus_rest(void)功能说明:产生单总线系统信号的总线复位信号,并返回总线上是否存在单总线器件信息******************************************************************/ uchar bus_rest(void){uchar presence;DQ=0; //将DQ信号线拉低delay(29); //持续48USDQ=1; //释放总线delay(3); //等待从设备将总线拉低presence=DQ; //保存当前总线状态delay(25); //等待总线初始化过程结束return presence;//返回是否有从设备将总线拉低}/**************************************************************** 函数名称:uchar r_1820BYTE(void)功能说明:向单总线读取一个数据字节*****************************************************************/ uchar r_1820BYTE(void){uchar i=0;uchar date = 0;for (i=8;i>0;i--){DQ = 0; // 将DQ信号线拉低启动读时隙DQ=1;// 释放总线,等待从机动车辆返回数据位delay(1); //越接近15us越好; 准备采样总线上的信号date>>=1 ;if (DQ)date=date|0x80;delay(6);}return(date);}/***************************************************************** 函数名称:void w_1280Byte(uchar bytevalue)功能说明:向单总线写一个数据字节******************************************************************/ void w_1280Byte(uchar bytevalue){uchar i;for(i=0;i<8;i++){DQ=0; // 将DQ信号线拉低启动读时隙DQ=bytevalue&0x01; //delay(5);//等待写时隙结束DQ=1; //释放bytevalue>>=1;}delay(5); ////等待写时隙结束}/***************************************************************** 函数名称:uint read_T(void)功能说明:读取1820温度*******************************************************************/ uint read_T(void){uchar a=0;uchar b=0;uint t=0;bus_rest();w_1280Byte(0xCC); // 跳过读序号列号的操作;w_1280Byte(0x44); // 启动温度转换,模数转化;bus_rest();w_1280Byte(0xCC); //跳过读序号列号的操作;a=r_1820BYTE();// 低8位b=r_1820BYTE();// 高8位t=(b*256)+a;return(t);}/**************************************************************函数名称:void show_T(uint temp)函数功能:显示温度**************************************************************/void show_T(uint temp){int i;float ftemp;ftemp = temp* 0.0625;w_12864(com,0x98+3);for(i=0;i<5;i++)w_12864(dat,dis1[i]); //写入温度}/*---------------以下为显示相关函数--------------------------*//******************************函数名称: void fenli(uchar x,uchar y,uchar val)功能描述: 指定位置写入数据********************************/void fenli(uchar x,uchar y,uchar val){ uchar ge,shi,addr,i=0;if(val==5)//星期数字显示的转换为中文{w_12864(com,0x88+2);for(i=0;i<2;i++){if(TAB_1302[5]==0)w_12864(dat,TAB_XQ[i]);if(TAB_1302[5]==1)w_12864(dat,TAB_XQ[2+i]);if(TAB_1302[5]==2)w_12864(dat,TAB_XQ[3+i]);if(TAB_1302[5]==3)w_12864(dat,TAB_XQ[5+i]);if(TAB_1302[5]==4)w_12864(dat,TAB_XQ[7+i]);if(TAB_1302[5]==5)w_12864(dat,TAB_XQ[9+i]);if(TAB_1302[5]==6)w_12864(dat,TAB_XQ[11+i]);}}else{shi=TAB_1302[val]/10;//分离十位ge=TAB_1302[val]%10;if(x==1)x=0x80;if(x==2)x=0x90;if(x==3)x=0x88;if(x==4)x=0x98;addr=x+y;w_12864(com,addr);//指定位置w_12864(dat,0x30+shi);//写入w_12864(dat,0x30+ge);}}/*************************************************************函数名称:void display(void)功能描述: 显示函数**************************************************************/ void display(void){ get_1302(); //读1302fenli(3,7,0); //读秒fenli(3,5,1); //读分fenli(3,3,2); //读时fenli(2,5,3); //读日fenli(2,3,4); //读月fenli(3,2,5); //读星期fenli(2,1,6); //读年}/*---------------按键处理相关函数--------------------------*//************************************************************ 函数名称:void scanner()功能描述: 按键函数*************************************************************/ void scanner(){ uchar i,j;if(!key) //功能键按下{ delay1ms(500); //延时500MSif(!key) //还按下,退出时间调整{ keyflag=0; //标志位为0sum=0; //清0w_12864(com,0x0c);//清闪烁for(i=0;i<7;i++)//十进制转十六进制{ j=TAB_1302[i]/10;TAB_1302[i]=TAB_1302[i]%10;TAB_1302[i]=TAB_1302[i]+16*j;}init_1302(); //写入1302while(!key); //等待释放delay1ms(10); //延时消抖}else //500MS内放开{ keyflag=1; //标志为1,进行时间调整sum++; //功能键加1if(sum==8)sum=0;switch(sum){ case 1: //{ w_12864(com,0x98+7);w_12864(com,0x0f);break;}case 2: //为2,年闪烁w_12864(com,0x90+1);break;case 3: //月闪烁w_12864(com,0x90+3);break;case 4: //日闪烁w_12864(com,0x90+5);break;case 5: //星期闪烁w_12864(com,0x88+2);break;case 6: //分闪烁w_12864(com,0x88+5);break;case 7: //时闪烁w_12864(com,0x88+3);break;}}}if(sum) //功能键按下{if(!key1){ delay1ms(10);if(!key1){ while(!key1);//等待加1键释放delay1ms(10);if(sum==1){ //备用}if(sum==2){ TAB_1302[6]++;if(TAB_1302[6]==100)TAB_1302[6]=0;fenli(2,1,6);w_12864(com,0x90+1);//闪烁归位}if(sum==3){ TAB_1302[4]++;if(TAB_1302[4]==13)TAB_1302[4]=1;fenli(2,3,4);w_12864(com,0x90+3);}if(sum==4){ TAB_1302[3]++;if(TAB_1302[3]==32)TAB_1302[3]=1;fenli(2,5,3);w_12864(com,0x90+5);}if(sum==5){ TAB_1302[5]++;if(TAB_1302[5]==7)TAB_1302[5]=0;fenli(3,2,5);w_12864(com,0x88+2);}if(sum==6){ TAB_1302[1]++;if(TAB_1302[1]==60)TAB_1302[1]=0;fenli(3,5,1);w_12864(com,0x88+5);}if(sum==7){ TAB_1302[2]++;if(TAB_1302[2]==24)TAB_1302[2]=0;fenli(3,3,2);w_12864(com,0x88+3);}}}}}//============================================================= void init(void){uchar i;init_12864();init_1302();while(TAB1[i]!='\0'){w_12864(dat,TAB1[i]);i++;}i=0;w_12864(com,0x90);while(TAB2[i]!='\0'){w_12864(dat,TAB2[i]);i++;}i=0;w_12864(com,0x88);while(TAB3[i]!='\0'){w_12864(dat,TAB3[i]);i++;}i=0;w_12864(com,0x98);while(TAB4[i]!='\0'){w_12864(dat,TAB4[i]);i++;}}/************************************************************* 函数名称:主函数函数功能:**************************************************************/ main(){init();while(1){scanner(); //检测键盘if(!keyflag) //标志为0{ display(); //调用显示show_T(read_T()); //显示温度delay1ms(500);}}}。

基于89C52单片机和DS1302的万年历设计

基于89C52单片机和DS1302的万年历设计

基于89C52单片机和DS1302的万年历设计摘要古人依靠日冕、漏刻记录时间,而随着现代科技的发展,电子万年历已经成为日渐流行的日常计时工具。

本文研究的万年历系统拟用STC89C52单片机控制,以DS1302时钟芯片计时、1602液晶屏显示。

系统主要由单片机控制电路,显示电路以及校正电路三个模块组成。

本文阐述了系统的硬件工作原理,所应用的各个接口模块的功能以及其工作过程,论证了设计方案理论的可行性。

系统程序采用C语言编写,经Keil软件进行调试后在Proteus软件中进行仿真测试,可以显示年、月、日、星期、时、分、秒,并具有校准功能和与即时时间同步的功能。

实验结果表明此万年历实现后具有读取方便、显示直观、功能多样、电路简洁等诸多优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。

关键词:万年历单片机DS1302 lcd1602目录第一章前言............................................................................................. 错误!未定义书签。

1.1引言(课题研究的意义) (1)1.2本课题主要的研究工作 (1)1.2.1研究内容 (1)1.2.2论文章节安排 (2)1.3本章小结 (2)第二章单片机的概述 (3)2.1单片机的定义和特点 (3)2.1.1单片机的定义 (3)2.1.2单片机的特点 (3)2.2单片机的发展现状和趋势 (3)2.3编程语言的选择 (4)2.4本章小结 (4)第三章设计要求和方案论证 (5)3.1设计要求 (5)3.2单片机芯片的选择方案和论证 (5)3.3显示模块选择方案和论证 (5)3.4时钟芯片的选择方案和论证 (6)3.5电路设计最终方案决定 (6)3.6本章小结 (6)第四章系统的硬件设计与实现 (7)4.1电路设计框图 (7)4.2系统硬件概述 (7)4.3主要单元电路的设计 (7)4.3.1 STC89C52单片机简介 (7)4.3.2单片机主控制模块的设计 (10)4.3.3时钟电路模块的设计 (11)4.3.4独立式键盘设计 (13)4.3.5显示模块的设计 (13)4.4本章小结 (15)第五章系统的软件设计 (16)5.1程序流程图 (16)5.1.1系统总流程图 (16)5.1.2时钟程序流程图 (16)5.1.3液晶显示程序流程图 (17)5.2程序的设计 (18)5.2.1读写DS1302程序 (18)5.2.2液晶显示程序 (19)5.3本章小结 (19)第六章结束语 (20)致谢词 (21)参考文献 (22)附录一:系统电路图 (23)附录二:系统程序 (24)第一章前言1.1引言(课题研究的意义)万年历是我国古代传说中最古老的一部太阳历。

基于单片机带温度显示的液晶万年历

基于单片机带温度显示的液晶万年历

摘要在寒假期间我用一周时间完成了这个液晶万年历,它可以显示年月日、时分秒、以及温度(可上下限报警),可以对时间进行加一或减一调整,并加入了闰、平年时间调整,方便可行,已经调试成功。

考虑到成本和方便,本作品采用了STC89c52和DS18B20,计时用的是51单片机自带的十六位定时器/计数器T0,尽管对时间进行了误差调整但是还是有一定的误差,考虑到学校后改用DS1302时钟芯片,进一步减小误差。

温度显示精度达到0.1摄氏度。

关键词:单片机 DS18B20 万年历温度1.硬件工作介绍(1)上电自动复位及手动复位电路STC89c52单片机的RST端外部复位有两种操作方式:上电自动复位和按键手动复位。

本设计用上电自动复位以及手动复位下结合的方式外接电路(见附图)。

(2)时钟振荡电路作品中采用12M晶振,其连接方法如图所示,其中电容的值都为22pF。

(3)1602液晶显示接口1602采用标准的16脚接口(见附图),其中:第1脚:GND为地电源第2脚:VCC接5V正电源第3脚:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。

第5脚:RW为读写信号线,高电平时进行读操作,低电平时进行写操作。

当RS 和RW共同为低电平时可以写入指令或者显示地址,当RS为低电平RW为高电平时可以读忙信号,当RS为高电平RW为低电平时可以写入数据。

第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。

第7~14脚:D0~D7为8位双向数据线。

第15脚:VCC第16:GND(4)键盘键盘是通过S3(P3.2),S4(p3.3),S5(p3.4)对时钟进行调整,其S3选择要调整的对象如时,分,日,月等等,并在液晶屏上显示所选的对象。

S4对所选中的对象进行加一调整,而S5对所选对象进行减一调整。

基于单片机DS1302的时钟万年历

基于单片机DS1302的时钟万年历

#include<>#define uchar unsigned char#define uint unsigned intsbit lcdws=P2^1; //1602管脚定义sbit lcden=P2^0;sbit lcdrs=P2^2;sbit key1=P2^3; //闹钟设置键sbit key2=P2^4;sbit key3=P1^5;//功能键定义sbit key4=P1^6;//增大键定义sbit key5=P1^7;//减小键定义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=P1^0;//ds18b20信号线sbit beep=P1^4; //蜂鸣器管脚定义sbit ACC_7 = ACC^7; //位寻址寄存器定义sbit SCLK = P1^2; // DS1302时钟信号sbit DIO= P1^1; // DS1302数据信号sbit CE = P1^3;//地址、数据发送子程序//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; //CE 引脚为低,数据传送中止 SCLK=0; //清零时钟总线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-- ) //循环8次移位 {SCLK = 0;temp = addr;DIO = (bit)(temp&0x01); //每次传输低字节 addr >>= 1; //右移一位 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 2010年09月30日23点58分56秒星期一{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--;}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*;temp=f_temp*10+;f_temp=f_temp+; //温度在寄存器中为12位,分辨率为^ 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);//定位到星期的位置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;}}}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_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;}}}}}void main()//主函数{Initial();lcdws=0;init();// IntConfiguration();tempchange();for(i=10;i>0;i--){dis_temp(get_temp());}while(1){keyscan();//按键扫描// while((key1&&key2&&key3&&key4&&key5)&&((fen==afen)&&(shi==ashi))) // {// beep=0;// delay(500);// beep=1;// }if(flag==1){miao=Read1302(0x81);//显示秒write_sfm(6,miao);fen=Read1302(0x83);//显示分write_sfm(3,fen);shi=Read1302(0x85);//显示小时write_sfm(0,shi);day=Read1302(0x87);//显示日write_nyrz(8,day);month=Read1302(0x89);//显示月write_nyrz(5,month);year=Read1302(0x8d);//显示年write_nyrz(2,year);week=Read1302(0x8b);//显示日期display_week(week);}else{write_1302(0x80,0x80);//时钟振荡器停止}set_alarm();}}。

DS1302设计的可调万年历(实测正常,附有程序)

DS1302设计的可调万年历(实测正常,附有程序)

DS1302设计的可调万年历(实测正常,附有程序)ds1302设计的可调万年历(本制作所用数码管全为共阳数码管)我刚开始想要搞万年历的时候就是玩游戏打听别人的程序,可是辨认出打听了很多都不理想,必须不就没有日历和时间一起表明,必须不就无法阳入时间的,后来我研究了两天,自己终于把程序编成了出。

不好了,废话我就不多说道,本制作我已经把实物搞了出,确保没问题!下面附有仿真图和实物图。

拍摄的效果不够好,但实物是不错的,本人实物中用三级管代替了仿真图的74hc04非门,用哪个都是可以的……请注意:本程序分后两个c文件的,如果不能编成,可以q我:1107588997我轻易播发程序过去给你……软件源程序:(初始化程序只在已经开始时用一次,之后必须把它屏蔽掉)#include#include#includeuchartime_data[7]={0,0,0,0,0,0,0};ucharwrite_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};ucharread_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};voidwrite_ds1302_byte(uchardat){uchari;for(i=0;i<8;i++){sck=0;io=dat&0x01;dat=dat>>1;sck=1;}}voidwrite_ds1302(ucharadd,uchardat){rst=0;_nop_();sck=0;_nop_();rst=1;_nop_();write_ds1302_byte(add);write_ds1302_byte(dat);rst=0;_nop_();io=1;sck=1;}ucharread_ds1302(ucharadd){uchari,value;rst=0;_nop_();sck=0;_nop_();rst=1;_nop_();write_ds1302_byte(add);for(i=0;i<8;i++){value=value>>1;sck=0;if(io)value=value|0x80;sck=1;}rst=0;_nop_();sck=0;_nop_();sck=1;io=1;returnvalue;}voidread_rtc(void){uchari;for(i=0;i<7;i++){time_data[i]=read_ds1302(read_add[i]);}}voidtime_pros(void){nian=time_data[0]/16*10+time_data[0];yue=time_data[2]/16*10+time_data[2];ri=ti me_data[3]/16*10+time_data[3];xi=time_data[1]/16*10+time_data[1];shi=time_data [4]/16*10+time_data[4];fen=time_data[5]/16*10+time_data[5];miao=time_data[6]/1 6*10+time_data[6];}voidmain(){//init_ds1302();//初始化while(1){read_rtc();time_pros();display();button();}}//----------------------------zichengxu.c----------------------------------------------#defineduan1p2#defineduan2p3#defineweip0#defineuintunsignedint#defineucharunsignedcharsbitsck=p1^1;sbitio=p1^0;sbitrst =p1^2;sbitk1=p1^4;sbitk2=p1^5;sbitk3=p1^6;sbitk4=p1^7;ucharshi,fen,miao,nian,yue,ri,xi,menu,y;unsignedcharcodequan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; voidwrite_ds1302_byte(uchardat);voidwrite_ds1302(ucharadd,uchardat);ucharread_ds1302(ucharadd);//voidinit_ds1302(void);//初始化voidread_rtc(void);voidtime_pros(void);voiddisplay(void);voidbutton(void);voiddelay(uintz){ucharx,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}/*(voidinit_ds1302(void)//初始化{write_ds1302(0x8e,0x00);write_ds1302(0x80,0x00);write_ds1302(0x82,0x20);write_ ds1302(0x84,0x09);write_ds1302(0x86,0x25);write_ds1302(0x88,0x12);write_ds1302 (0x8a,0x06);write_ds1302(0x8c,0x10);write_ds1302(0x90,0x01);write_ds1302(0xc0, 0xf0);write_ds1302(0x8e,0x80);}*/voiddisplay(void){wei=0;duan1=quan[2];if(menu==3&&y<80&&k1!=0&&k2!=0&&k3!=0&&k4!=0){duan2=0xff;}elseduan2=quan[shi/10];delay(2);duan1=0xff;duan2=0xff;wei=1;duan1=quan[0];if(menu==3&&y<80&&k1!=0&&k2!=0&&k3!=0&&k4!=0){duan2=0xff;}elseduan2=quan[shi];delay(2);duan1=0xff;duan2=0xff;。

单片机的18B20、1302和LCM1602液晶显示温度与万年历显控制

单片机的18B20、1302和LCM1602液晶显示温度与万年历显控制

摘要本设计以数字集成电路技术为基础,单片机技术为核心。

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

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

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

目录摘要 (2)前沿 (4)1.1设计目标 (5)1.2设计要求 (5)2 设计方案 (5)2.1 控制器选用 (5)2.2 显示部分设计 (6)2.3 数字温度采集设计 (6)2.4 系统设计 (6)2.4.1 晶体振荡器电路 (7)2.4.3 时间计数器电路 (7)2.4.4 时钟电路 (7)2.4.5 复位电路 (8)2.4.6复位电路的可靠性设计 (8)2.4.7 按键部分 (8)3各硬件介绍 (9)3.1 AT89S51的引脚说明 (9)3.2 LCD1602简介 (9)3.3 DS1302 简介 (10)3.4 DS18B20 简介 (12)4 系统硬件设计所需的器材 (15)5系统软件总体设计........................................................................... 1错误!未定义书签。

6电路原理仿真图7 主程序流程图 (17)8 完整程序编写 (19)前言电子时钟是实现对年,月,日,时,分,秒数字显示的计时装置,广泛用于个人家庭,车站,码头,办公室,银行大厅等场所,成为人们日常生活中的必需品。

数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度远远超过老式钟表。

钟表的数字化给人们生产生活带来了极大的方便,在此基础上完成的电子时钟精度高,功能易于扩展。

可扩展成为诸如定时自动报警、按时自动打铃、时间程序自动控制、定时广播、自动起闭路灯、定时开关烘箱、通断动力设备、甚至各种定时电气的自动启用等电路。

所有这些,都是以钟表数字化为基础的。

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

89C52单片机+DS1302时钟芯片+DS18B20+74HC138译码器 17位数码管万年历制作关键字:51单片机、数码管、万年历、DS1302本文介绍使用STC89C52单片机,DS1302时钟芯片提供时钟信号,DS18B20提供温度信号,74HC138译码器+S8550三极管驱动17位共阳极数码管,才用3个按键对万年历进行调整。

实物图如下:Proteus仿真如下:图中采用4个红色LED模拟时间分隔符,当功能键按下一次后秒开始闪烁,此时可以按下第二键和第三键进行加和减的操作,再按一次功能键进入分钟的调节,依次类推,最后跳出调整状态。

STC89C52介绍:STC89C52是STC公司生产的一种低功耗、高性能CMOS8位微控制器,具有8K 在系统可编程Flash存储器。

STC89C52使用经典的MCS-51内核,但做了很多的改进使得芯片具有传统51单片机不具备的功能。

在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。

具有以下标准功能: 8k 字节Flash ,512字节RAM , 32 位I/O 口线,看门狗定时器,内置4KB EEPROM ,MAX810复位电路,3个16 位定时器/计数器,4个外部中断,一个7向量4级中断结构(兼容传统51的5向量2级中断结构),全双工串行口。

另外 STC89C52 可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。

空闲模式下,CPU 停止工作,允许RAM 、定时器/计数器、串口、中断继续工作。

掉电保护方式下,RAM 内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。

最高运作频率35MHz ,6T/12T 可选。

器件参数:1. 增强型8051单片机,6 时钟/机器周期和12 时钟/机器周期可以任意 选择,指令代码完全兼容传统8051.[2]2. 工作电压:5.5V ~3.3V (5V 单片机)/3.8V ~2.0V (3V 单片机)3.工作频率范围:0~40MHz ,相当于普通8051 的0~80MHz ,实际工作 频率可达48MHz4. 用户应用程序空间为8K 字节5. 片上集成512 字节RAM6. 通用I/O 口(32 个),复位后为:P0/P1/P2/P3 是准双向口/弱上拉, P0 口是漏极开路输出,作为总线扩展用时,不用加上拉电阻,作为 I/O 口用时,需加上拉电阻。

7. ISP (在系统可编程)/IAP (在应用可编程),无需专用编程器,无 需专用仿真器,可通过串口(RxD/P3.0,TxD/P3.1)直接下载用户程 序,数秒即可完成一片8. 具有EEPROM 功能9. 共3 个16 位定时器/计数器。

即定时器T0、T1、T2 10.外部中断4 路,下降沿中断或低电平触发电路,Power Down 模式可 由外部中断低电平触发中断方式唤醒11. 通用异步串行口(UART ),还可用定时器软件实现多个UART12. 工作温度范围:-40~+85℃(工业级)/0~75℃(商业级)13. PDIP 封装DS1302介绍:DS1302 是美国DALLAS 公司推出的一种高性能、低功耗、带RAM 的实时时钟电路,它可以对年、月、日、周、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V ~5.5V 。

采用三线接口与CPU 进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM 数据。

DS1302内部有一个31×8的用于临时性存放数据的RAM 寄存器。

DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后备电源双电源引脚,同时提供了对后备电源进行涓细电流充电的能力。

DS1302的引脚排列,其中Vcc2为主电源,VCC1为后备电源。

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

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

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

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

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

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

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

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

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

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

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

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

SCLK 为时钟输入端。

DS18B20介绍:DS18B20数字温度传感器接线方便,封装成后可应用于多种场合,如管道式,螺纹式,磁铁吸附式,不锈钢封装式,型号多种多样,有LTM8877,LTM8874等等。

主要根据应用场合的不同而改变其外观。

封装后的DS18B20可用于电缆沟测温,高炉水循环测温,锅炉测温,机房测温,农业大棚测温,洁净室测温,弹药库测温等各种非极限温度场合。

耐磨耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和控制领域。

1: 技术性能描述①、 独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯。

② 、测温范围 -55℃~+125℃,固有测温误差(注意,不是分辨率,这里之前是错误的)1℃。

③、支持多点组网功能,多个DS18B20可以并联在唯一的三线上,最多只能并联8个,实现多点测温,如果数量过多,会使供电电源电压过低,从而造成信号传输的不稳定。

④、工作电源: 3.0~5.5V/DC (可以数据线寄生电源)⑤ 、在使用中不需要任何外围元件⑥、 测量结果以9~12位数字量方式串行传送⑦ 、不锈钢保护管直径 Φ6⑧ 、适用于DN15~25, DN40~DN250各种介质工业管道和狭小空间设备测温⑨、 标准安装螺纹 M10X1, M12X1.5, G1/2”任选⑩ 、PVC 电缆直接出线或德式球型接线盒出线,便于与其它电器设备连接。

74HC138介绍:74HC138是一款高速CMOS器件,74HC138引脚兼容低功耗肖特基TTL (LSTTL)系列。

74HC138译码器可接受3位二进制加权地址输入(A0, A1和A2),并当使能时,提供8个互斥的低有效输出(Y0至Y7)。

74HC138特有3个使能输入端:两个低有效(E1和E2)和一个高有效(E3)。

除非E1和E2置低且E3置高,否则74HC138将保持所有输出为高。

利用这种复合使能特性,仅需4片74HC138芯片和1个反相器,即可轻松实现并行扩展,组合成为一个1-32(5线到32线)译码器。

任选一个低有效使能输入端作为数据输入,而把其余的使能输入端作为选通端,则74HC138亦可充当一个8输出多路分配器,未使用的使能输入端必须保持绑定在各自合适的高有效或低有效状态。

74HC138与74HC238逻辑功能一致,只不过74HC138为反相输出。

CD74HC138 ,CD74HC238和CD74HCT138 ,CD74HCT238是高速硅栅CMOS 解码器,适合内存地址解码或数据路由应用。

74HC138 作用原理于高性能的存贮译码或要求传输延迟时间短的数据传输系统,在高性能存贮器系统中,用这种译码器可以提高译码系统的效率。

将快速赋能电路用于高速存贮器时,译码器的延迟时间和存贮器的赋能时间通常小于存贮器的典型存取时间,这就是说由肖特基钳位的系统译码器所引起的有效系统延迟可以忽略不计。

HC138 按照三位二进制输入码和赋能输入条件,从8 个输出端中译出一个低电平输出。

两个低电平有效的赋能输入端和一个高电平有效的赋能输入端减少了扩展所需要的外接门或倒相器,扩展成24 线译码器不需外接门;扩展成32 线译码器,只需要接一个外接倒相器。

在解调器应用中,赋能输入端可用作数据输入端。

复合使能输入,轻松实现扩展兼容JEDEC标准no.7A 存储器芯片译码选择的理想选择低有效互斥输出ESD保护HBM EIA/JESD22-A114-C超过2000 V MM EIA/JESD22-A115-A超过200 V 温度范围-40~+85 ℃-40~+125 ℃多路分配功能。

三极管8550介绍:三极管8550是一种常用的普通三极管。

它是一种低电压,大电流,小信号的PNP型硅三极管。

各模块如下:程序源代码如下:(如果本文对您有用请下载此文档贡献一下您宝贵的财富值,本文不贵,予人玫瑰手有余香,愿单片机爱好者都能学好学会)主函数:(main.h)#include<temp.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit wela=P3^3;sbit A=P2^7;sbit b=P2^6;sbit C=P2^5;sbit SCLK=P3^5; //DS1302通讯线定义sbit DIO=P3^6;sbit RST=P3^7;sbit k1=P1^0;sbit k2=P1^1;sbit k3=P1^4;sbit w1=P2^4;sbit w2=P2^3;uchar code smgw[]={0,1,2,3,4,5,6,7};uchar code smgd[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88};uchar tab1[9];uchar tab2[9];float tp;int temp;uchar nian,yue,ri,zhou,shi,fen,miao,a,shan,tt,shan;uchar knum;void delay(uint z){u int x,y;f or(x=z;x>0;x--)for(y=110;y>0;y--);}void write(uchar date) //写入DS1302一个字节{u char temp,i;R ST=1;S CLK=0;t emp=date;f or(i=0;i<8;i++){SCLK=0;if(temp&0x01)DIO=1;elseDIO=0;SCLK=1;temp>>=1;}}uchar read() //读出DS1302一个字节{u char a,temp;R ST=1;f or(a=8;a>0;a--){temp>>=1;SCLK=1;_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();SCLK=0;if(DIO){temp=temp|0x80;}else{temp=temp|0x00;}}r eturn (temp);}void write_1302(uchar add,uchar dat) //写DS1302数据{R ST=0;S CLK=0;R ST=1;w rite(add);w rite(dat);S CLK=1;R ST=0;}uchar read_1302(uchar add) //读DS1302数据{u char dat1,dat2;R ST=0;S CLK=0;R ST=1;w rite(add);d at1=read();S CLK=1;R ST=0;d at1=ACC; ///?????dat2=dat1/16; //数据进制转换 dat1=dat1%16; //十六进制转十进制 dat1=dat1+dat2*10;r eturn(dat1);}void ds1302_init() //1302初始化{R ST=0;S CLK=0;w rite_1302(0x8e,0x00); //允许写入/* write_1302(0x84,0x00); //24小时制w rite_1302(0x80,0x00);//设置初始值SECw rite_1302(0x82,0x59);//设置初始值MINw rite_1302(0x84,0x23);//设置初始值HRw rite_1302(0x86,0x26);//设置初始值DATEw rite_1302(0x88,0x04);//设置初始值MONTHw rite_1302(0x8A,0x03);//设置初始值DAYw rite_1302(0x8C,0x09);//设置初始值YEAR*/w rite_1302(0x90,0xa5);//启动充电功能w rite_1302(0x8e,0x80);}void display(){miao=read_1302(0x81); //读秒fen=read_1302(0x83); //读分shi=read_1302(0x85);//&0x3f; //读时ri=read_1302(0x87); //读日yue=read_1302(0x89); //读月nian=read_1302(0x8d); //读年zhou=read_1302(0x8B); //读星期 */i f(temp< 0) //当温度值为负数{temp=temp-1;temp=~temp;tp=temp;temp=tp*0.0625*100+0.5;}else{tp=temp;temp=tp*0.0625*100+0.5;}w ela=0;i f(knum==7){wela=0;A=0;b=0;C=0; //年P0=0xa4|shan;delay(1);P0=0xff;A=1;b=0;C=0;P0=0xc0|shan;delay(1);P0=0xff;A=0;b=1;C=0;P0=smgd[nian/10]|shan;delay(1);P0=0xff;A=1;b=1;C=0;P0=smgd[nian%10]|shan;delay(1);P0=0xff;}e lse{wela=0;A=0;b=0;C=0; //年P0=0xa4;delay(1);P0=0xff;A=1;b=0;C=0;P0=0xc0;delay(1);P0=0xff;A=0;b=1;C=0;P0=smgd[nian/10];delay(1);P0=0xff;A=1;b=1;C=0;P0=smgd[nian%10];delay(1);P0=0xff;}i f(knum==6){A=0;b=0;C=1; // 月P0=smgd[yue/10]|shan;delay(1);P0=0xff;A=1;b=0;C=1;P0=smgd[yue%10]|shan;delay(1);P0=0xff;}e lse{A=0;b=0;C=1; // 月P0=smgd[yue/10];delay(1);P0=0xff;A=1;b=0;C=1;P0=smgd[yue%10];delay(1);P0=0xff;}i f(knum==5){A=0;b=1;C=1; // 星期P0=smgd[zhou%10]|shan;delay(1);P0=0xff;}e lse{A=0;b=1;C=1; // 星期P0=smgd[zhou%10];delay(1);P0=0xff;}w ela=1;i f(knum==4){wela=1;A=0;b=0;C=0; // 日P0=smgd[ri/10]|shan;delay(1);P0=0xff;A=1;b=0;C=0;P0=smgd[ri%10]|shan;delay(1);P0=0xff;}e lse{wela=1;A=0;b=0;C=0; // 日P0=smgd[ri/10];delay(1);P0=0xff;A=1;b=0;C=0;P0=smgd[ri%10];delay(1);P0=0xff;}i f(knum==3){A=1;b=1;C=0; // 时P0=smgd[shi/10]|shan;delay(1);P0=0xff;A=0;b=1;C=0;P0=smgd[shi%10]|shan;delay(1);P0=0xff;}e lse{A=1;b=1;C=0; // 时P0=smgd[shi/10];delay(1);P0=0xff;A=0;b=1;C=0;P0=smgd[shi%10];delay(1);P0=0xff;}i f(knum==2){A=0;b=0;C=1; // 分P0=smgd[fen/10]|shan;delay(1);P0=0xff;A=1;b=0;C=1;P0=smgd[fen%10]|shan;delay(1);P0=0xff;}e lse{A=0;b=0;C=1; // 分P0=smgd[fen/10];delay(1);P0=0xff;A=1;b=0;C=1;P0=smgd[fen%10];delay(1);P0=0xff;}i f(knum==1){A=0;b=1;C=1; // 秒P0=smgd[miao/10]|shan;delay(1);P0=0xff;A=1;b=1;C=1;P0=smgd[miao%10]|shan;delay(1);P0=0xff;}e lse{A=0;b=1;C=1; //秒P0=smgd[miao/10];delay(1);P0=0xff;A=1;b=1;C=1;P0=smgd[miao%10];delay(1);P0=0xff;}/* w1=0;P0 = smgd[temp / 10000];d elay(1);P0=0xff;w1=1;w2=0;P0 = smgd[temp % 10000 / 1000];d elay(1);P0=0xff;w2=1; */}void key(){ //u char temp;// display();i f(k1==0){delay(20);if(k1==0){while(!k1);knum++;if(knum==1){temp=(miao)/10*16+(miao)%10;//十进制转换成DS1302要求的DCB码write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x80,0x80|temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码write_1302(0x8e,0x80); //打开写保护}if(knum==8){knum=0;write_1302 (0x8e,0X00); //禁止写保护write_1302 (0x80,0x7f&temp); //时钟恢复write_1302 (0x8e,0x80); //允许写保护write_1302(0x8e,0x00);write_1302(0x80,0x00|temp);//miao数据写入DS1302write_1302(0x8e,0x80);}}}if(knum!=0){if(k2==0){delay(20);if(k2==0){while(!k2);switch(knum){case 1:miao++;if(miao==60)miao=0;temp=(miao)/10*16+(miao)%10;//十进制转换成DS1302要求的DCB码write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x80,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码write_1302(0x8e,0x80); //打开写保护break;case 2:fen++;if(fen==60)fen=0;temp=(fen)/10*16+(fen)%10;//十进制转换成DS1302要求的DCB码write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x82,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码write_1302(0x8e,0x80); //打开写保护}break;case 3:shi++;if(shi==24)shi=0;temp=(shi)/10*16+(shi)%10;//十进制转换成DS1302要求的DCB码write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x84,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码write_1302(0x8e,0x80); //打开写保护break;case 4:ri++;switch(yue){case 1:case 3:case 5:case 7:case 8:case 10:case 12:if(ri==32)ri=1;break;case 4:case 6:case 9:case 11:if(ri==31)ri=1;break;case 2:if(nian%4==0||nian%400==0){if(ri==30)ri=1;}else{if(ri==29)ri=1;}break;}temp=(ri)/10*16+(ri)%10;//十进制转换成DS1302要求的DCB 码write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x86,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码write_1302(0x8e,0x80); //打开写保护break;case 5:zhou++;if(zhou==8)zhou=1;temp=(zhou)/10*16+(zhou)%10;//十进制转换成DS1302要求的DCB码write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x8a,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码write_1302(0x8e,0x80); //打开写保护break;case 6:yue++;if(yue==13)yue=1;temp=(yue)/10*16+(yue)%10;//十进制转换成DS1302要求的DCB码write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x88,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码write_1302(0x8e,0x80); //打开写保护break;case 7:nian++;if(nian==99)nian=0;temp=(nian)/10*16+(nian)%10;//十进制转换成DS1302要求的DCB码write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x8c,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码write_1302(0x8e,0x80); //打开写保护break;}}}if(k3==0){delay(20);if(k3==0){while(!k3);switch(knum){case 1:miao--;if(miao==-1)miao=59;temp=(miao)/10*16+(miao)%10;//十进制转换成DS1302要求的DCB码write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x80,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码write_1302(0x8e,0x80); //打开写保护break;case 2:fen--;if(fen==-1)fen=59;temp=(fen)/10*16+(fen)%10;//十进制转换成DS1302要求的DCB码write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x82,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码write_1302(0x8e,0x80); //打开写保护}break;case 3:shi--;if(shi==-1)shi=23;temp=(shi)/10*16+(shi)%10;//十进制转换成DS1302要求的DCB码write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x84,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码write_1302(0x8e,0x80); //打开写保护break;case 4:ri--;switch(yue){case 1:case 3:case 5:case 7:case 8:case 10:case 12:if(ri==0)ri=31;break;case 4:case 6:case 9:case 11:if(ri==0)ri=30;break;case 2:if(nian%4==0||nian%400==0){if(ri==0)ri=29;}else{if(ri==0)ri=28;}break;}temp=(ri)/10*16+(ri)%10;//十进制转换成DS1302要求的DCB 码write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x86,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码write_1302(0x8e,0x80); //打开写保护break;case 5:zhou--;if(zhou==0)zhou=7;temp=(zhou)/10*16+(zhou)%10;//十进制转换成DS1302要求的DCB码write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x8a,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码write_1302(0x8e,0x80); //打开写保护break;case 6:yue--;if(yue==0)yue=12;temp=(yue)/10*16+(yue)%10;//十进制转换成DS1302要求的DCB码write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x88,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码write_1302(0x8e,0x80); //打开写保护break;case 7:nian--;if(nian==-1)nian=99;temp=(nian)/10*16+(nian)%10;//十进制转换成DS1302要求的DCB码write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x8c,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据BCD码write_1302(0x8e,0x80); //打开写保护break;}}}}}void main(){d s1302_init();T MOD=1;T H0=(65536-50000)/256;T L0=(65536-50000)%256;E A=1;E T0=1;T R0=1;s han=0x00;w hile(1){key();//Ds18b20ReadTemp();display();}}void time0() interrupt 1{T H0=(65536-50000)/256;T L0=(65536-50000)%256;t t++;i f(tt==9){tt=0;shan=~shan;}}温度函数:(temp.h)#include"temp.h"/****************************************************************************** * 函数名 : Delay1ms* 函数功能 : 延时函数* 输入 : 无* 输出 : 无*****************************************************************************/void Delay1ms(uint y){u int x;f or( ; y>0; y--){for(x=110; x>0; x--);}}/****************************************************************************** * 函数名 : Ds18b20Init* 函数功能 : 初始化* 输入 : 无* 输出 : 初始化成功返回1,失败返回0******************************************************************************/uchar Ds18b20Init(){u char i;D SPORT = 0; //将总线拉低480us~960usi = 70;w hile(i--);//延时642usD SPORT = 1; //然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低i = 0;w hile(DSPORT) //等待DS18B20拉低总线{Delay1ms(1);i++;if(i>5)//等待>5MS{return 0;//初始化失败}}r eturn 1;//初始化成功}/****************************************************************************** * 函数名 : Ds18b20WriteByte* 函数功能 : 向18B20写入一个字节* 输入 : com* 输出 : 无******************************************************************************/void Ds18b20WriteByte(uchar dat){u int i, j;f or(j=0; j<8; j++){DSPORT = 0; //每写入一位数据之前先把总线拉低1usi++;DSPORT = dat & 0x01; //然后写入一个数据,从最低位开始i=6;while(i--); //延时68us,持续时间最少60usDSPORT = 1; //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值dat >>= 1;}}/****************************************************************************** * 函数名 : Ds18b20ReadByte* 函数功能 : 读取一个字节* 输入 : com* 输出 : 无******************************************************************************/uchar Ds18b20ReadByte(){u char byte, bi;u int i, j;f or(j=8; j>0; j--){DSPORT = 0;//先将总线拉低1usi++;DSPORT = 1;//然后释放总线i++;i++;//延时6us等待数据稳定bi = DSPORT; //读取数据,从最低位开始读取/*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。

相关文档
最新文档