⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 text.c

📁 LCD DS1302,MEGA16
💻 C
字号:
//基于AT89S52的万年历程序
//所用主要芯片;万年历芯片DS1302,温度传感器DS18B20
//程序撰写:我很单片机(乐乐)
//2008年4月于天津理工大学
//注1 (可以依靠按键自行调整时间)
//注2  可自行判断闰年程序(2000-2099)
//注3  如果运行发现问题会继续更改
#include<reg52.h>
#include<intrins.h>

#define uchar unsigned char
#define uint unsigned int
#define LCDDATA P0
uchar code w[][3]={"MON","TUE","WED","TUR","FRI","SAT","SUN"};
uchar code t[]={"TEMP"};
sbit DQ=P3^2;    //18B20数据

sbit RS= P3^5;
sbit RW= P3^6;
sbit E= P3^4;
sbit BUSY=P0^7;

sbit DATA=P2^7;
sbit SCLK=P2^6;
sbit RST=P3^7;

uchar x_key,y_key,keytemp;
void delay(uint t)
{uchar j;
 while(t--)
 {for(j=0;j<125;j++);}
 }

void test_busy()
{
 do{LCDDATA=0XFF;
 RS=0;
 RW=1;
 E=0;
 E=1;}
 while(BUSY);
 }

void write_com(com)
{
 RS=0;
 RW=0;
 LCDDATA=com;
 E=0;
 _nop_();
 E=1;
 }
  
void write_data(da)
{
 RS=1;
 RW=0;
 LCDDATA=da;
 E=0;
 _nop_();
 E=1;
 }

void delay1820(uint x)
{ uint b=0;
  uchar i;
 while(b++<x)
 {for(i=0;i<1;i++);}	
 }

uchar reset_18b20()				//监测18b20
{//uchar ack=1;
 DQ=0;
 delay1820(18);	//480us以上
 DQ=1;
 delay1820(1);	 //15~60us
 if(DQ) 
 {delay1820(5);	   //60~240us
 return 1;	}
 else 
 {delay1820(5);	   //60~240us
 return 0;}
}

uchar read_18b20()
{uchar j,redat=0;
for(j=8;j>0;j--)
{ redat>>=1;
 DQ=0;
 DQ=1;
 if(DQ) redat|=0x80;
 delay1820(2);	//60~120us
 DQ=1;
 }
 DQ=1;		//养成习惯读完字节时序线置1
 return (redat);
}

void write_18b20(uchar wrdat)
{ uchar j;
  for(j=8;j>0;j--)
  {DQ=0;
  if(wrdat&0x01)DQ=1;
  else DQ=0;
  delay1820(1);	 //15~60us
  DQ=1;
  wrdat>>=1;
 }
  DQ=1;
}

void start_18b20()
{uchar temp_h,temp_l,zheng,reset=1;
 uint temp=0;
 uchar wendu_h,wendu_l;
 while(reset==1){reset=reset_18b20();}	  //监测到18b20否?
 write_18b20(0xCC);    //跳过读rom指令
 write_18b20(0x44);   //启动温度转换启动温度转换
 delay1820(40000);	      //延时750ms
 reset=reset_18b20();	  
 while(reset==1){reset=reset_18b20();}
 write_18b20(0xcc);	 //跳过读rom指令
 write_18b20(0xbe);  //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
 temp_l=read_18b20();
 temp_h=read_18b20();
 temp=(temp|temp_h)<<8;		   //处理数据
 temp=temp|temp_l;
 if(temp_h&0x08)		//如果为负数,转为原码
  {temp=~(temp-1);
  }
  zheng=temp/16;		 //转化为实际温度值
  if(temp_h&0x08) zheng++;	 //小数部分四舍五入
  wendu_h= zheng/10+48;
  wendu_l= zheng%10+48;
  test_busy();
  write_com(0x8e);			  
  test_busy();
  write_data(wendu_h);
  test_busy();
  write_data(wendu_l);
}

void lcd_init()
{delay(500);
 delay(15);
 write_com(0x38);
 delay(5);
 write_com(0x38);
 delay(5);
 write_com(0x38); 
 test_busy(); 
 write_com(0x38); 		//设置16*2显示 5*7点阵 8为数据接口
 test_busy();
 write_com(0x01);      //显示清屏
 test_busy();
 write_com(0x0c);     //开显示 关光标
 test_busy();
 write_com(0x06);   //指针加1  屏显示不移动
 }

//向DS1302写一字节数据,address为命令字节
void write1302byte(uchar command,uchar writedata){
uchar j;
RST=0;
SCLK=0;
RST=1;
for(j=0;j<=7;j++){
if(command&0x01) DATA=1;
else DATA=0;
SCLK=1;
command>>=1;
SCLK=0;
}
for(j=0;j<=7;j++){
if(writedata&0x01) DATA=1;
else DATA=0;
SCLK=1;
writedata>>=1;
SCLK=0;
}
RST=0;
}
//读取DS1302一字节数据,address为命令字节
uchar read1302byte(uchar command){
uchar i,k=0;
RST=0;
SCLK=0;
RST=1;
for(i=0;i<8;i++){
if(command&0x01) DATA=1;
else DATA=0;
SCLK=1;
command>>=1;
if(i!=7) SCLK=0;
}
k=0;
for(i=0;i<8;i++){
k>>=1;
SCLK=0;
if(DATA) k|=0x80;
SCLK=1;
}
RST=0;
return(k);
}

 dis_m(uchar x)		  //显示'pm'or'am'
 {test_busy();
 write_com(0xc0);			  
 test_busy();
 write_data(x);
 test_busy();
 write_data('M');
  }

void display_min()
{ uchar min,min_h,min_l;
 min=read1302byte(0x83);   //1302读出数据为BCD码
 min_h=min/16+48;		   //转成待1602液晶显示的ASCII码
 min_l=min%16+48;
 test_busy();
 write_com(0xc5);			  
 test_busy();
 write_data(min_h);
 test_busy();
 write_data(min_l);
}

display_hour()
  { 
 uchar hour,hour_h,hour_l,hourflag;	 //hourflag区分中午12点or凌晨12点标志位
  hour=read1302byte(0x85);
  hourflag=hour&0x20;
   if(hourflag) dis_m('P');		 //A/P=1  PM
   else dis_m('A');					 //A/P=0  AM
   hour=hour&0x1f;
   hour_h=hour/16+48;
   hour_l=hour%16+48;
   if((hour==0)&&(hourflag))		//中午12点显示12点,凌晨12点显示0点
   {hour_h=49;hour_l=50;}
   write_com(0xc2);			  
   test_busy();
   write_data(hour_h);
   test_busy();
   write_data(hour_l);
   }

display_day()
   { 
 uchar day,day_h,day_l;
 day=read1302byte(0x87);
   day_h=day/16+48;
   day_l=day%16+48;
   test_busy();
   write_com(0x86);			  
   test_busy();
   write_data(day_h);
   test_busy();
   write_data(day_l);
  }

display_mon()
   {
 uchar mon,mon_h,mon_l;
   mon=read1302byte(0x89);
   mon_h=mon/16+48;
   mon_l=mon%16+48;
   test_busy();
   write_com(0x83);			  
   test_busy();
   write_data(mon_h);
   test_busy();
   write_data(mon_l);
   }

display_week()
{  uchar j; 
 uchar week; 
   week=read1302byte(0x8b);
   test_busy();
   write_com(0xca);
   for(j=0;j<3;j++)
   { test_busy();
   write_data(w[week-1][j]);
   }
   }

display_year()
   {
   uchar year,year_h,year_l;
   year=read1302byte(0x8d);
   year_h=year/16+48;
   year_l=year%16+48;
   test_busy();
   write_com(0x80);			  
   test_busy();
   write_data(year_h);
   test_busy();
   write_data(year_l);
   }

void deal_min()	                 	 //按键调整时间(调分钟)
{uchar min1;
 min1=read1302byte(0x83);			//读出1302数据为BCD码   
  min1=(min1>>4)*10+(min1&0x0f);	//转为10进制数据
 min1++;
 if(min1==60) min1=0;				//是否超出时间范围
 min1=(min1/10)*16+min1%10;			//转成BCD码送回1302
 write1302byte(0x82,min1);
}

void deal_hour()
{uchar hour1,hour2;
 hour1=read1302byte(0x85);
 hour2=hour1;
 hour1=hour1&0X1F;
 hour1=(hour1>>4)*10+(hour1&0x0f);	
 hour1++;
 if(hour1==12)  
 {hour1=0;
  hour2=(~hour2)&0x20;
  }
 else hour2&=0x20;
 hour1=(hour1/10)*16+hour1%10;
 hour2=hour2|hour1;
 write1302byte(0x84,hour2|0x80);
}

void doweek(x)						 //调整星期  没有自己的按键控制,随年月日的按键,自动变化
{uchar week2;
 week2=read1302byte(0x8b);
 week2+=x;
 if(week2>7) week2%=7;
 write1302byte(0x8a,week2);
 }

void doweek_feb()
{uchar leap;
 leap=read1302byte(0x8d);
 leap=(leap>>4)*10+(leap&0x0f);
 if(leap%4==0) doweek(1);
 else doweek(0);
 }

void doweek_dec()
{uchar leap;
 leap=read1302byte(0x8d);
 leap=(leap>>4)*10+(leap&0x0f);
 if(leap%4==0) doweek(50);
 else doweek(44);
 }

void deal_month()
{uchar mon1;
 mon1=read1302byte(0x89);
 switch(mon1)
 {case 1: doweek(3); break;				//1月N日的星期与2月的N日差3天
  case 2: doweek_feb(); break;
  case 3: doweek(3); break;
  case 4: doweek(2); break;
  case 5: doweek(3); break;
  case 6: doweek(2); break;
  case 7: doweek(3); break;
  case 8: doweek(3); break;
  case 9: doweek(2); break;
  case 0x10: doweek(3); break;
  case 0x11: doweek(2); break;			
  case 0x12: doweek_dec(); break;			//12月N日与当年的1月N日的星期差50天
  default:break;
  }
 mon1=(mon1>>4)*10+(mon1&0x0f);
 mon1++;
 if(mon1>12) mon1=1;
 mon1=(mon1/10)*16+mon1%10;
 write1302byte(0x88,mon1);
}

void deal_year()							//跨过闰年星期加2,平年星期加1
{uchar year1,month2;
 year1=read1302byte(0x8d);
 year1=(year1>>4)*10+(year1&0x0f);
 month2=read1302byte(0x89);
 if((month2<=2&&year1%4==0)||(month2>2&&year1%4==3))
 doweek(2);
 else doweek(1);
 year1++;
 if(year1>99) year1=0;
 year1=(year1/10)*16+year1%10;
 write1302byte(0x8c,year1);
}

void natural(uchar x)							//除2月其他月份处理方法相同
{uchar day1;
 day1=read1302byte(0x87);
 day1=(day1>>4)*10+(day1&0x0f);
 day1++;
 if(day1>x) {day1=1;write1302byte(0x8a,x-29);}
 day1=(day1/10)*16+day1%10;
 write1302byte(0x86,day1);
}

void especial()							   //2月特殊,闰年2月29,平年28	 (限于2000~2099年)
{uchar leap;
 leap=read1302byte(0x8d);
 leap=(leap>>4)*10+(leap&0x0f);
 if(leap%4==0) natural(29);
 else natural(28);
 }

void deal_day()
{uchar week1;
 week1=read1302byte(0x8b);
 week1++;
 if(week1>7) week1=1;
 write1302byte(0x8a,week1);
 switch(read1302byte(0x89))
 {case 1: natural(31); break;
  case 2: especial(); break;
  case 3: natural(31);  break;
  case 4: natural(30);  break;
  case 5: natural(31);  break;
  case 6: natural(30);  break;
  case 7: natural(31);  break;
  case 8: natural(31);  break;
  case 9: natural(30);  break;
  case 0x10: natural(31); break;
  case 0x11: natural(30); break;
  case 0x12: natural(31); break;
  default:break;
  }
}   


uchar key_value(uchar kk)
{switch(kk)
 {case 0xee: kk=0;break;
  case 0xde: kk=1;break;
  case 0xbe: kk=2;break;
  case 0x7e: kk=3;break;
  case 0xed: kk=4;break;
  case 0xdd: kk=5;break;
  case 0xbd: kk=6;break;
  case 0x7d: kk=7;break;
  case 0xeb: kk=8;break;
  case 0xdb: kk=9;break;
  case 0xbb: kk=10;break;
  case 0x7b: kk=11;break;
  case 0xe7: kk=12;break;
  case 0xd7: kk=13;break;
  case 0xb7: kk=14;break;
  case 0x77: kk=15;break;
  default: break;
  }
  return (kk);
 }

void scankey()
{uchar x_key,y_key,keytemp;  
 P1=0X0f;
   x_key=P1&0x0f;
 if(x_key!=0x0f)
  {delay(30);
   P1=0X0f;
   x_key=P1&0x0f;
   if(x_key!=0x0f)
   {P1=0XF0;
    y_key=P1&0XF0;
    keytemp=x_key|y_key;
    switch(key_value(keytemp))
    {case 0:  deal_min();break;		  //0键处理分钟
     case 1: deal_hour();break;		  //1键处理小时
     case 5: deal_day();break;		 //2键处理天
     case 3: deal_month();break;	 //3键处理月
     case 4: deal_year();break;		//4键处理年
     default:break;
    }
   }
  }
}

main()
{ uchar j;
 lcd_init();
 test_busy();
 write_com(0xc4);			  
 test_busy();
 write_data(':');
 test_busy();
// write_com(0xc7);			   //不显示2000年的前两位
 //test_busy();
// write_data(':');
 //test_busy();
// write_com(0x80);			  
 //test_busy();
// write_data('2');
// test_busy();
// write_data('0');
// test_busy();
 write_com(0x82);			  
 test_busy();
 write_data('-');
 test_busy();
 write_com(0x85);			  
 test_busy();
 write_data('-');
 test_busy();
 write_com(0x8a);
 for(j=0;j<4;j++)
 { test_busy();
 write_data(t[j]);
 }
 write1302byte(0x80,0x30);				 //30秒
 write1302byte(0x82,0x59);				 //59分
 write1302byte(0x84,0xa0);				 //中午12点
 write1302byte(0x86,0x1);				 //1号
 write1302byte(0x88,0x05);				 //5月
 write1302byte(0x8a,0x04);				 //周三
 write1302byte(0x8c,0x08);				 //08年
 while(1)
 { //sec=read1302byte(0x81);   //不显示秒
  // sec_h=sec/16+48;;
  // sec_l=sec%16+48;
  // test_busy();
  // write_com(0xc8);			  
  // test_busy();
   //write_data(sec_h);
  // test_busy();
  // write_data(sec_l);
   start_18b20();			   //启动18B20温度传感器
   display_min();			   //显示分
   display_hour();			   //显示小时
   display_day();			   //显示天
   display_mon();			  //显示月
   display_week();			  //显示星期
   display_year();			  //显示年
   scankey();				  //扫键盘,调整时间
   }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -