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)前言电子时钟是实现对年,月,日,时,分,秒数字显示的计时装置,广泛用于个人家庭,车站,码头,办公室,银行大厅等场所,成为人们日常生活中的必需品。

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

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

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

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

ds1302+ds18b20+闹钟按键可调万年历c语言程序

ds1302+ds18b20+闹钟按键可调万年历c语言程序

#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只须写入一次,所以将此处屏蔽。

单片机课程设计之万年历、闹钟与温度显示设计

单片机课程设计之万年历、闹钟与温度显示设计
根据方案的选择,数码管时钟温度系统由51单片机、时钟芯片DS1302、测温芯片DS1802、数码管显示电路、键盘电路组成,如图3-1所示。
本系统采用C语言编写,控制器采用单片机STC89C52,温度检测部分采用DS18B20温度传感器,时钟系统用时钟芯片DS1302,用八位数码管作为显示器。单片机通过时钟芯片DS1302获取时间数据;通过温度传感器DS18B20采集温度信号送给单片机处理,并在数码管中显示出来,键盘可以切换界面,调时和温度查询与设置闹钟的功能。
由于DS18B20是在一根I/O线上读写数据,因此,对读写的数据位有着严格的时序要求。DS18B20有严格的通信协议来保证各位数据传输的正确性和完整性。该协议定义了几种信号的时序:初始化时序、读时序、写时序。所有时序都是将主机作为主设备,单总线器件作为从设备。而每一次命令和数据的传输都是从主机主动启动写时序开始,如果要求单总线器件回送数据,在进行写命令后,主机需启动读时序完成数据接收。数据和命令的传输都是低位在先。电路图如图3-4所示。
6、数码管显示电路设计
数码管内部是由7个条形发光二极管与一个小圆点发光二极管组成,根据这八个二极管的亮暗组成不同的字符。本系统采用八位数码管作为显示模块,数码管相对其他LCD类的显示器来说,成本比较低廉,省电。两个四位共阴0.56英寸的数码管作为显示屏。如图3-6所示。
7、按键控制电路设计
本系统采用四个按键作为键盘控制实现界面切换的功能,如图3-7所示。能够实现界面切换、时间校正、闹钟设置等功能。机械式按键再按下或释放时,由于机械弹性作用的影响,通常伴随有一定时间的触点机械抖动,然后其触点才稳定下来。其抖动过程如图3-8所示。抖动时间的长短与开关的机械特性有关,一般为5-10 ms。故软件编程时需要注意消除抖动。

基于单片机DS1302的时钟万年历(带闹钟)

基于单片机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温度检测应用实例

基于ds1302万年历应用实例、基于ds18b20温度检测应用实例

基于D S1302万年历以及基于D S18B20的温度检测电路/***************主程序***************/#include<reg51.h>#include "LCD1602.h"#include "1302.h"#include"wendu.h"#define uchar unsigned char#define uint unsigned intsbit speaker=P2^4;bit key_flag1=0,key_flag2=0;/*uchar shijian[6]={0};*///sec_add=0,min_add=0,hou_add=0,day_add=0,mon_add=0,yea_add=0;uchar data_alarm[7]={0};/*********************************键盘控制****************************************************/int key_scan() //扫描是否有键按下{ int i=0;uint temp;P1=0xf0;temp=P1;if(temp!=0xf0)i=1;elsei=0;return i;}uchar key_value() //确定按键的值{uint m=0,n=0,temp;uchar value;uchar code v[4][3]={'2','1','0','5','4','3','8','7','6','b','a','9'} ;//用二维数组进行按键查询P1=0xfe;temp=P1; if(temp!=0xfe)m=0;P1=0xfd;temp=P1 ;if(temp!=0xfd)m=1;P1=0xfb;temp=P1 ;if(temp!=0xfb)m=2;P1=0xf7;temp=P1 ;if(temp!=0xf7)m=3;P1=0xef;temp=P1 ;if(temp!=0xef)n=0;P1=0xdf;temp=P1 ;if(temp!=0xdf)n=1;P1=0xbf;temp=P1 ;if(temp!=0xbf)n=2;value=v[m][n];return value;}/************************************************设置闹铃函数*********************************/ void naoling(void){uchar i=0,l=0,j;init1602();while(key_flag2&&i<12)if(key_scan()){j=key_value();write_data(j);if(i%2==0)data_alarm[l]=((j-'0')<<4);else{data_alarm[l]+=(j-'0');l++;}i++;delay(600);}write_com(0x01);}uchar according(void){ uchar k;if(data_alarm[0]==x[1]&&data_alarm[1]==x[2]&&data_alarm[2]==x[3]&&data_alarm[3]==x[4]&&dat a_alarm[4]==x[5]&&data_alarm[5]==x[6])k=1;else k=0;return k;}void speak(void){uint i=50;while(i){speaker=0;delay(2);speaker=1;delay(1);i--;}}void alarm(void){uint i=10; //i=10while(i){speak();delay(10);i--;}}/************************************修改时间操作****************************************/void xiugai(void) //修改时间函数{if(key_scan()&&key_flag1)switch(key_value()){case '0': {data1[1]++;if(data1[1]>'9'){data1[1]='0';data1[0]++;}if(data1[0]>'9'){data1[0]='0';data1[1]='0'; }x[1]=(data1[0]-'0')<<4|(data1[1]-'0');dswrite(0x8c,x[1]);} break;case '1': {data1[4]++;if(data1[4]>'9'){data1[4]='0';data1[3]++;}if(data1[3]=='1'&&data1[4]=='3'){data1[3]='0';data1[4]='1'; }x[2]=(data1[3]-'0')<<4|(data1[4]-'0');dsw rite(0x88,x[2]);} break;case '2': {data1[7]++;if(data1[7]>'9'){data1[7]='0';data1[6]++;}if(data1[6]=='3'&&data1[7]=='2'){data1[6]='0';data1[7]='1'; }x[3]=(data1[6]-'0')<<4|(data1[7]-'0');dsw rite(0x86,x[3]);} break;case '3': {time[1]++;if(time[1]>'9'){time[1]='0';time[0]++;}if(time[0]=='2'&&time[1]=='4') {time[0]='0';time[1]='0';}x[4]=(time[0]-'0')<<4|(time[1]-'0');dswrite(0x84,x[4]);} break;case '4': {time[4]++;if(time[4]>'9'){time[4]='0';time[3]++;}if(time[3]=='6'&&time[4]=='1') {time[3]='0';time[4]='1';}x[5]=(time[3]-'0')<<4|(time[4]-'0');dswrite(0x82,x[5]);} break;case '5': { time[7]++;if(time[7]>'9'){time[7]='0';time[6]++;}if(time[6]=='6'&&time[7]=='1') {time[6]='0';time[7]='1';}x[6]=(time[6]-'0')<<4|(time[7]-'0');dswrite(0x80,x[6]);} break;//case 'b': reset() ;break;default: break;}}/************************************************中断处理函数*********************************/ void changing(void) interrupt 0 using 0 //需要修改时间和日期,或者停止修改{if(key_flag1)key_flag1=0;else key_flag1=1;}void alarming(void) interrupt 3 using 0 //需要设置闹铃或者停止设置{if(key_flag2)key_flag2=0;else key_flag2=1;}/*********************************主函数*************************************************/main(){uint i;//uchar *l;uchar p1[]="D:",p2[]="TM",p3[]="Wd";EA=1;EX0=1;IT0=1;EA=1;EX1=1;IT1=1;init1602(); //LCD初始化Initial_DS1302() ; //1302初始化ds18b20();baojing=1; //报警灯while(1){ //write_com(0x80); //显示区域不够去除// write_string(p1,2);write_com(0x88) ;write_string(p3,2) ;write_com(0xc0);write_string(p2,2);gettime();//从1302中读取时间datalcd( ); //日期显示转换timelcd( ); //时间显示转换xiugai( ); //调用修改时间函数if (key_flag2) naoling();if (according()) alarm();write_com(0x80);write_string(data1,8);write_com(0xc2);write_string(time,8);ds18b20(); //12位转换时间最大为750msget_temperature();display( );delay(10);}}/*****1302子程序:*************/#ifndef _REAL_TIMER_DS1302_2009_5_20_#define _REAL_TIMER_DS1302_2003_5_20_#include <intrins.h>#define uchar unsigned char#define uint unsigned intvoid timelcd( );void datalcd( );sbit DS1302_CLK = P2^6; //实时时钟时钟线引脚sbit DS1302_IO = P2^7; //实时时钟数据线引脚sbit DS1302_RST = P2^5; //实时时钟复位线引脚sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;uchar x[7]={0x20,0x10,0x04,0x18,0x10,0x0,0x00};//分别存放年月日,时分秒//uchar x[6]={0};uchar time[7]={0};// 存放时间uchar data1[7]={0};//存放日期void dswrite(unsigned char add,unsigned char dat){unsigned char i ;DS1302_CLK=0;DS1302_RST=0;DS1302_RST=1;for(i=0;i<8;i++){DS1302_IO=0;if(add&0x01)DS1302_IO=1;DS1302_CLK=1;add>>=1;DS1302_CLK=0;_nop_();;}ACC=dat;for(i=0;i<8;i++){DS1302_IO=0;if(dat&0x01)DS1302_IO=1; _nop_();DS1302_CLK=1;DS1302_CLK=0;dat>>=1;}DS1302_CLK=0;DS1302_RST=0;}unsigned char dsread(unsigned char add) {unsigned char i,dat;DS1302_CLK=0;DS1302_RST=0;DS1302_RST=1;ACC=add;for(i=0;i<8;i++){DS1302_IO=0;if(add&0x01)DS1302_IO=1;_nop_();DS1302_CLK=1;add>>=1;DS1302_CLK=0;_nop_();}DS1302_IO=1;//送1呈输入状态dat=0;for(i=0;i<7;i++){if(DS1302_IO)dat|=0x80;DS1302_CLK=1;dat >>= 1;_nop_();DS1302_CLK=0;_nop_();}DS1302_CLK=0;DS1302_RST=0;return dat;}void gettime()//从1302中读取时间{DS1302_RST=0;x[1]=dsread(0x8d);//年x[2]=dsread(0x89);//月x[3]=dsread(0x87);//日x[4]=dsread(0x85);//时x[5]=dsread(0x83);//分x[6]=dsread(0x81);//秒}void datalcd( ){data1[0]=(x[1]>>4)+'0';data1[1]=((x[1]&0x0f)+'0'); data1[2]='-';data1[3]=((x[2]>>4)&0x0f)+'0'; data1[4]=(x[2]&0x0f)+'0'; data1[5]='-';data1[6]=((x[3]>>4)&0x0f)+'0'; data1[7]=(x[3]&0x0f)+'0';}void timelcd( ){time[0]=((x[4]>>4)&0x0f)+'0'; time[1]=(x[4]&0x0f)+'0';time[2]=':';time[3]=((x[5]>>4)&0x0f)+'0'; time[4]=(x[5]&0x0f)+'0';time[5]=':';time[6]=((x[6]>>4)&0x0f)+'0';time[7]=(x[6]&0x0f)+'0';}void DS1302_SetProtect(bit flag) //是否写保护{if(flag)dswrite(0x8E,0x10);elsedswrite(0x8E,0x00);}void DS1302_SetTime(unsigned char Address, unsigned char Value) // 设置时间函数{DS1302_SetProtect(0);dswrite(Address, ((Value/10)<<4 | (Value%10))); //将十进制数转换为BCD码} //在DS1302中的与日历、时钟相关的寄存器存放的数据必须为BCD码形式void Initial_DS1302(void) //初始化1302{unsigned char Second;Second=dsread(0x80);if(Second&0x80) //初始化时间DS1302_SetTime(0x80,0);}/**************ds18b20子程序************/#include <reg51.h>#include <intrins.h>//#include "cd1602.h"#define uchar unsigned char#define uint unsigned intvoid display( );void delay(uint z);sbit ds=P3^7;sbit baojing=P3^6;uchar flag ;uint temp; //参数temp一定要声明为int 型uchar wendustring[6]={0}; //显示温度用void TempDelay (uchar us) //延时函数{while(us--);}void ds_reset(void) //18b20复位{ds=1;_nop_(); //延时1usds=0;TempDelay(80); //最少480us_nop_();ds=1;TempDelay(5); //存在检测高电平时间:15~60us,此处大约延时44us_nop_();_nop_();_nop_();if(ds==0)flag=1; //detect 18b20 successelseflag=0; //detect 18b20 failTempDelay(20); //存在检测低电平时间:60~240us,此处延时约140us _nop_();_nop_();ds=1; //拉高总线,让总线处于空闲状态}bit ds_read_bit(void) //读一位{bit dat;ds=0;_nop_(); //读时隙起始总线拉低至少1usds=1;_nop_();_nop_();dat=ds;TempDelay(10); //所有读"时间隙"必须60~120us,此处延时约77us return(dat);}uchar ds_read_byte(void ) //读一字节{uchar value,i,j;value=0;for(i=0;i<8;i++){j=ds_read_bit();value=(j<<7)|(value>>1);}return(value); //返回一个字节的数据}void ds_write_byte(uchar dat) //写一个字节{uchar i;bit onebit;for(i=1;i<=8;i++){onebit=dat&0x01; //判断位为0还是1 dat=dat>>1;if(onebit) //写1{ds=0;_nop_();_nop_();ds=1;TempDelay(5);}else //写0{ds=0;TempDelay(8); //写0 时间隙,低电平至少60μs,此处大约64us ds=1;_nop_();_nop_();}}}void ds18b20() //初始化{ds_reset();delay(1); //约2msds_write_byte(0xcc);ds_write_byte(0x44);}uint get_temperature() //读取温度函数{float wendu;uchar a,b;ds_reset();delay(1); //约2msds_write_byte(0xcc);ds_write_byte(0xbe);a=ds_read_byte();b=ds_read_byte();temp=b;temp<<=8;temp=temp|a;wendu=temp*0.0625;temp=wendu*10+0.5;return temp;}/*void main(){ uchar p3[]="W";init1602();baojing=1; //报警灯while(1){write_com(0x88);write_string(p3,1);ds18b20(); //12位转换时间最大为750ms get_temperature();display( );}} */void display(){if(temp&0x8000){temp=~temp;temp=temp-575; // 负值温度调试用wendustring[0]='-';wendustring[1]='0';wendustring[2]=temp%1000/100+'0'; //显示温度用wendustring[3]=temp%100/10+'0';if(wendustring[2]>='2'&&wendustring[3]>'5') baojing=0; else if (wendustring[2]>='3')baojing=0;else baojing=1;wendustring[4]='.';wendustring[5]=temp%10+'0';}else{wendustring[0]='+';wendustring[1]=temp/1000+'0';if(temp>750) baojing=0;else baojing=1;wendustring[2]=temp%1000/100+'0'; //显示温度用wendustring[3]=temp%100/10+'0';wendustring[4]='.';wendustring[5]=temp%10+'0';}write_com(0x8a);write_string(wendustring,6);delay(5);}/******************1602液晶显示子程序*****************/ #ifndef LCD_CHAR_1602_2005_4_9#define LCD_CHAR_1602_2005_4_9#define uchar unsigned char#define uint unsigned intsbit lcdrs = P2^0;sbit lcdrw = P2^1;sbit lcden = P2^2;void delay(uint z) // 延时{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void write_com(uchar com) // 写入指令数据到lcd {lcdrw=0;lcdrs=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;}void write_data(uchar date) // 写入字符显示数据到lcd {lcdrw=0;lcdrs=1;P0=date;delay(5);lcden=1;delay(5);lcden=0;}void init1602() // 初始化设定{lcdrw=0;lcden=0;write_com(0x3C);write_com(0x0c);write_com(0x06);write_com(0x01);write_com(0x80);}void write_string(uchar *pp,uint n) //写入字符串{int i;for(i=0;i<n;i++)write_data(pp[i]);}#endif。

万年历时钟(ds1302)+温度显示(ds18b20)原理图

万年历时钟(ds1302)+温度显示(ds18b20)原理图
A X1 19 18
P3.0 (RXD) P3.1 (TXD) P3.2 (INT0) P3.3 (INT1) P3.4 (T0) P3.5 (T1) X1 X2 IC2 89C51 P27 P26 P25 P24 P23 P22 P21 P20
Байду номын сангаас
28 27 26 25 24 23 22 21
LED2
DIG0_C
DIG4_B
DIG0_B
SD3
DP3
SG3
SD2
DP2
SG2
SD2
DP2
SG2
SD1
DP1
SG1
SD1
DP1
SC3
SC2
SC2
SC1
SC1
SE3
SE2
SE2
SE1
SE1
6
A4
d
h
g
d
h
g
d
h
g
d
h
g
d
h
g
e
c
e
c
e
c
e
c
e
c
R12 1.5k
S7 DP3 S6 SA3 S16 S5:减键,代码05 C S8 S6:加键,代码06 S7:调节时间,代码 07
R12 1.5k C7 104 C7 15P
5V 5V 1 2 3 4 5 CS1 6 CLK1 7 DATA1 8 9 KEY1 10 11 12 13 14 驱动第一排 VDD VDD NC VSS NC CS CLK DATA KEY SG SF SE SD SC HD7279A RESET RC CLKO DIG7 DIG6 DIG5 DIG4 DIG3 DIG2 DIG1 DIG0 DP SA SB 28 27 26 25 24 23 22 21 20 19 18 17 16 15

ds1302+ds18b20可调万年历汇编程序

ds1302+ds18b20可调万年历汇编程序

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,开始走时。

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

基于单片机DS1302的时钟万年历
向DS18B20写一个字节数据函数
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
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;
{
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);
{
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;}
SCLK= 0;}CE=0;
dat1=ACC;
dat2=dat1/16;//

单片机代码-DS1302万年历

单片机代码-DS1302万年历

#include<reg52.h>#include<intrins.h> //为了使用这个头文件中的_nop_()延时函数sbitsda=P2^0; //定义1302的数据线sbitscl=P2^1; //定义1302的时钟线sbitrst=P2^4; //定义1302的复位控制端,高电平时启动1302,低电平时关闭1302 sbit hc573_sg_le=P2^6; //对用于锁存段数据的573锁存LE端进行定义sbit hc573_bit_le=P2^7; //对用于锁存位选通数据的573锁存LE端进行定义sbitlcd_rs=P1^0; //1602数据/命令选择端,高电平执行数据操作,低电平执行命令操作sbitlcd_rw=P1^1; //1602读/写控制端高电平读,低电平写sbitlcd_en=P2^5; //1602读写控制使能信号,它为高脉冲信号才可执行读写操作sbit sta7=P0^7; //1602忙信号检测位,为1则忙,需等待,为0表示空闲unsigned char write_dat[8]={0x12,0x36,0x17,0x23,0x8,0x5,0x13,0x80}; //秒分时日月星期年和保护寄存器的初值unsigned char read_dat[8]; //用于接收从1302读到的寄存器当前值unsigned char code lcd_line1[]={" 20 - -"}; //定义第一行液晶显示的格式字符数组unsigned char code lcd_line2[]={"Week: : :"}; //定义第二行液晶显示的格式字符数组void lcd_busy_check(void) //1602忙信号检测,忙则等待{P0=0xff;do{lcd_rs=0; //读状态操作,为0lcd_rw=1; //读操作为1lcd_en=0;lcd_en=1; //读状态,需为高电平}while (sta7==1); //如果为1则忙,等待...直到为0lcd_en=0;}void lcd_write_cmd(unsigned char cmd) //液晶写命令函数{lcd_busy_check(); //每次操作之前都要进行忙信号检测lcd_rs=0; //执行命令操作,为0lcd_rw=0; //写操作,为0P0=cmd; //送指令到液晶数据端口P0,准备执行命令_nop_(); //这是一个延时函数,可延时一个机器周期,它在“intrins.h”中lcd_en=1; //高电平,指令送入液晶控制器_nop_(); //保持一会儿,使指令可靠地送入液晶控制器lcd_en=0; //低电平,执行命令}void lcd_write_data(unsigned char dat) //液晶写数据函数{lcd_busy_check(); //每次操作之前都要进行忙信号检测lcd_rs=1; //执行数据操作,为1lcd_rw=0; //写操作,为0P0=dat; //送数据到液晶数据端口P0,准备执行数据操作_nop_();lcd_en=1; //高电平,数据送入液晶液晶数据RAM_nop_(); //保持一会儿,使显示数据可靠地送入液晶数据RAM lcd_en=0; //低电平,显示数据}void lcd1602_init() //液晶显示初始化操作{P0=0x00;hc573_bit_le=0;hc573_sg_le=0; //关闭HC573使数码管不显示lcd_en=0; //为0,为实现高脉冲作准备lcd_write_cmd(0x38); //设置为5x7显示lcd_write_cmd(0x0c); // 打开显示-显示光标-光标闪烁lcd_write_cmd(0x6); //地址加一,光标右移,整屏显示不移动lcd_write_cmd(0x01); //清屏}/*--对1302进行写一个字节的函数--*/voidwrite_byte(unsigned char dat){unsigned char i;for(i=8;i>0;i--){sda=(bit)(dat&0x01);scl=0;scl=1;dat=dat>>1;}}/*--对1302进行读一个字节的函数--*/unsigned char read_byte(){unsigned char dat,i;for(i=8;i>0;i--){dat=dat>>1;scl=1;scl=0;if(sda==1)dat=(dat|0x80);}returndat;}/*--1302的初始化函数。

万年历功能介绍及操作说明

万年历功能介绍及操作说明

万年历功能介绍及操作说明
基于51单片机的液晶万年历设计
1、本设计基于STC89C52(与AT89S5
2、AT89C52通用,可任选)单片机以及DS1302时钟芯片、DS18B20温度传感器构成的万年历系统。

2、有闹钟和阴历功能,有闰年补偿,可以准确及正确的显示时间等信息。

3、可以显示年、月、日、时、分、秒、星期、温度、农历和闹钟设定。

4、掉电走时,不用重新调时,当按键按下时背光亮,更节能。

使用方法:
一共4个按键:设置、加、减、切换
按下设置的时候秒会闪,这时可以加减调节,然后再按设置是设置分钟,依次设置,最后按一下设置就是推出并保存,主界面按切换的时候是显示阴历(ping是平年,run是闰年),再按下切换是显示闹钟界面,此时可以按设置调整闹钟。

万年历ds1302

万年历ds1302

1 引言随着微电子技术和超大规模集成电路技术的不断发展,家用电子产品不但种类日益丰富,而且变得更加经济实用,单片微型计算机体积小、性价比高、功能强、可靠性高等独有的特点,在各个领域得到了广泛的应用。

电子万年历是一种应用非常广泛的日常计时工具,数字显示的日历钟已经越来越流行,特别是适合在家庭居室、办公室、大厅、会议室、车站和广场等使用。

LED数字显示的日历钟显示清晰直观、走时准确、可以进行夜视,并且还可以扩展出多种功能。

功能也越来越齐全,除了公历年月日、时分秒、星期显示及闹铃。

但通过我们对各种电子钟表、历的不断观察总结发现目前市场的钟、历都存在一些不足之处,比如:时钟不精确、产品成本太高、无环境温度显示等,这都给人们的使用带来了某些不便。

为此设计了一种功能全面、计时准确、成本低廉的基于51单片机的万年历。

2 功能要求1. 万年历能用数码管显示阳历年、月、日、星期、[小]时、分、秒并设置指定时间的闹铃。

2. 数字式温度计要求测温范围-50~100°C,LED数码管直读显示。

3 方案论证与设计3.1 控制部分的方案选择1. 用可编程逻辑器件设计。

可采用ALTERA公司的FLEX10K系列PLD器件。

设计起来结构清晰,各个模块,从硬件上设计起来相对简单,控制与显示的模块间的连接也会比较方便。

但是考虑到本设计的特点,EDA在功能扩展上比较受局限,而且EDA占用的资源也相对多一些。

从成本上来讲,用可编程逻辑器件来设计也没有什么优势。

2. 用凌阳16位单片机设计。

凌阳16位单片机有丰富的中断源和时基,方便本实验的设计。

它的准确度相当高,并且C语言和汇编兼容的编程环境也很方便来实现一些递归调用。

I/O口功能也比较强大,方便使用。

用凌阳16位单片机做控制器最有特色的就是它的可编程音频处理,可完成语音的录制播放和识别。

这些都方便对设计进行扩展,使设计更加完善。

成本也相对低一些。

但是,在控制与显示的结合上有些复杂,显示模组资源相对有限,而且单片机的稳定性不是很高。

万年历,STC,DS1302

万年历,STC,DS1302

}
}

{ } break; P0=0x00;
LS138++; if(LS138>0x07) { } SetTimer0(); LS138=0x00;
//定时器 1,初始化,用于控制按设置键后数码管闪烁的频率 voidTimer1Init(void) { } AUXR&=0xBF; TMOD&=0x0F; TL1=0xB0; TH1=0x3C; TF1=0; TR1=1; //定时器时钟 12T 模式 //设置定时器模式 //50 毫秒@12.000MHz
}
{ do { while(--k);
}while(--j);
}while(--i);
//设置时间、日期、星期 voidSetDateTime() { } voidSetTimer0()//用于控制 138 扫描数码管的时间 { } voidtm1_isr()interrupt3using1 { flashTime++; if(flashTime>50) TL0=0x78; TH0=0xCC; TF0=0; //设置定时初值 //设置定时初值 Set_RTC(write_rtc_address,l_tmpdate);
table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x00};
codeunsignedcharwrite_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};// 秒分时日月周年 最低位读写位 codeunsignedcharread_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; unsignedcharl_tmpdate[7]={30,43,21,15,12,2,14};//初始化 ds1302 的值 unsigned char Result[7]={0x00,0x00,0x00,0x00,0x00,0x00,0x00};//读取 ds1302 的结 果 unsigned char SetValue[7]={0x00,0x00,0x00,0x00,0x00,0x00,0x00};//存储已经设置好 的值,该值最后要写入 ds1302 unsignedcharLS138; unsigned char SetKey;//0x00 表示没有按设置键,0x01 设置年,0x02 设置月,0x03 设置 日,0x04 设置小时,0x05 设置分,0x06 设置秒 unsignedcharFlash,flashTime; unsignedcharHexYear; voidDelay250ms() { _nop_(); i=2; j=231; k=91; do unsignedchari,j,k; //@12.000MHz
  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。

相关文档
最新文档