专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

51单片机+ds1302+ds18b20+1602液晶万年历

作者:佚名   来源:本站原创   点击数:  更新时间:2012年11月22日   【字体:

  这是我写的单片机小程序,将单片机开发板上的ds1302,ds18b20和1602综合起来,在1602上显示年月日周时分秒和温度;望各位好友指点,此程序仅适用于我的开发板,用在其他开发板上应该改下端口就可以。


 

 #include <reg52.h>
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef long int uint32;
//****************************************************************************************************
sbit DQ=P2^2;//********************供18b20使用的变量
float T;
//****************************************************************************************************
uint8 counter_0,counter_1;//*******供1302使用的变量
uint8 second=0,minute=0,hour=0,year=0,month=0,day=0,week;
uint32 sh;
uint8 D[]="wek";
uint16 i=0;
//****************************************************************************************************
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<ds18b20>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//****************************************************************************************************
void delay_10us(uint8 x)//*********10微秒级别延时
{
 while(x>0)x--;
}
//****************************************************************************************************
void ds18b20_init()//**************ds18b20的初始化
{
 uint16 i;
 DQ=0;
 i=103;
 while(i>0)i--;
 DQ=1;
 i=4;
 while(i>0)i--;;
}
//****************************************************************************************************
bit readbit()//********************读取一位数据
{
 uint16 i;
 bit dat;
 DQ=0;i++;
 DQ=1;i++;i++;
 dat=DQ;
 i=8;while(i>0)i--;
 return(dat);
}
//****************************************************************************************************
uint8 r_ds18b20()//****************从ds18b20读取一字节数据
{
 uint8 dat=0,i,j;
 for(i=1;i<=8;i++)
 {
  j=readbit();
  dat=(j<<7)|(dat>>1);
 }
 return(dat);
}
//****************************************************************************************************
void w_ds18b20(uint8 dat)//********向ds18b20写入一字节数据
{
 uint8 j;
 uint8 i;
 bit testb;
 for(i=1;i<=8;i++)
 {
  testb=dat&0x01;
  dat>>=1;
  if(testb)
   { 
    DQ=0;
    j++;j++;j++;
    DQ=1;
    j=14;while(j>0)j--;
   }

  else
   { 
    DQ=0;
    j=14;while(j>0)j--;
    DQ=1;
    j++;j++;j++;
   }
 }
}
//****************************************************************************************************
void beginchange()//***************开始转换温度
{
 ds18b20_init();
 delay_10us(200);
 w_ds18b20(0xcc);
 w_ds18b20(0x44);
}
//****************************************************************************************************
void get_temp()//*****************从ds18b20读取数据并转换成十进制
{
 uint8 H,L;
 uint16 temp;
 ds18b20_init();
 delay_10us(200);
 w_ds18b20(0xcc);
 w_ds18b20(0xbe);
 L=r_ds18b20();
 H=r_ds18b20();
 temp=H;
 temp<<=8;
 temp|=L;
 T=temp*(0.0625);
}
//****************************************************************************************************
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<ds1302>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//****************************************************************************************************
#define WRITE_SECOND 0x80//*****写**秒寄存器地址
#define WRITE_MINUTE 0x82//*****写**分寄存器地址
#define WRITE_HOUR 0x84//*******写**时寄存器地址
#define WRITE_DAY 0x86//********写**天寄存器地址
#define WRITE_MONTH 0x88//******写**月寄存器地址
#define WRITE_YEAR 0x8c//*******写**年寄存器地址
#define WRITE_WEEK 0x8A//*******写**周寄存器地址
#define READ_SECOND 0x81//******读**秒寄存器地址
#define READ_MINUTE 0x83//******读**分寄存器地址
#define READ_HOUR 0x85//********读**时寄存器地址
#define READ_DAY 0x87//*********读**天寄存器地址
#define READ_MONTH 0x89//*******读**月寄存器地址
#define READ_YEAR 0x8d//********读**年寄存器地址
#define READ_WEEK 0x8b//********读**周寄存器地址
#define WRITE_PROTECT 0x8E//****写保护寄存器
sbit ACC_7=ACC^7;
sbit CLCK=P2^1;
sbit RST=P2^4;
sbit IO=P2^0;
//****************************************************************************************************
void write_1302(uint8 addr,uint8 dat)//向1302写入地址和数据
{
 uint8 i=0;
 RST=0;
 CLCK=0;
 RST=1;
 for(i=8;i>0;i--)
 {
 CLCK=0;
 if((addr&0x01)==1)IO=1;
 else IO=0;
 addr>>=1;
 CLCK=1;
 }
 for(i=8;i>0;i--)
 {
 CLCK=0;
 if((dat&0x01)==1)IO=1;
 else IO=0;
 dat>>=1;
 CLCK=1;
 }
 RST=0;
}
//****************************************************************************************************
uint8 read_1302(uint8 addr)//先向1302写地址,再读数据
{ 
 uint8 i=0,dat;
 RST=0;
 CLCK=0;
 RST=1;
 for(i=8;i>0;i--)
 {
 CLCK=0;
 if((addr&0x01)==1)IO=1;
 else IO=0;
 addr>>=1;
 CLCK=1;
 }
 for(i=8;i>0;i--)
 {
 ACC_7=IO;
 CLCK=1;
 ACC>>=1;
 CLCK=0;
 }
 dat=ACC;
 dat=(dat>>4)*10+(dat&0x0f);//有BCD码转换成十进制数
 return(dat);
 RST=0;
}
//*****************************************************************************************************
void ds1302_init()//1302初始化
{
 write_1302(WRITE_PROTECT,0x00);//*******取消写保护
 write_1302(WRITE_SECOND,0x00);//********00秒//NUM_BCD(0)
 write_1302(WRITE_MINUTE,0x00);//********00分钟//NUM_BCD(0) 
 write_1302(WRITE_HOUR,0x16);//**********16小时//NUM_BCD(0)
 write_1302(WRITE_DAY,0x21);//***********21天
 write_1302(WRITE_MONTH,0x11);//*********11月
 write_1302(WRITE_YEAR,0x12);//**********2012年
 write_1302(WRITE_WEEK,0x03);//**********星期三 
 write_1302(WRITE_PROTECT,0x80);//*******打开写保护
}
//****************************************************************************************************
void timer0_init()//几十毫秒的延时
{
 TMOD|=0x01;
 TMOD&=0xfd;
 TH0=0x3c;
 TL0=0xaf;
 TR0=1;
}
//****************************************************************************************************
void dushu()//从1302读取数据并将其转换成显示函数直接用到的数字
{
 second=read_1302(READ_SECOND);
 minute=read_1302(READ_MINUTE);
 hour=read_1302(READ_HOUR);
 day=read_1302(READ_DAY);
 month=read_1302(READ_MONTH);
 year=read_1302(READ_YEAR);
 week=read_1302(READ_WEEK);
}
//****************************************************************************************************** 
void jishi0()//每一段时间会进行一次读取数字
{
 if(TF0==1)
 {
 TF0=0;
 TH0=0x3c;
 TL0=0xaf;
 counter_1++;
 }
 dushu();
 if(counter_1==2)
 {
 counter_1=0;
 get_temp();
 beginchange();
 } 
}
//****************************************************************************************************
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<1602>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//****************************************************************************************************
sbit RS=P1^0;//**************数据命令选择端
sbit RW=P1^1;//**************读写选择端
sbit ENLCD=P2^5;//***********使能端
sbit shang=P2^6;//***********数码管数据输入控制端
sbit xia=P2^7;//*************数码管共阴极控制端
sbit busy=P0^7;//************判断忙标志
//****************************************************************************************************
void delay(uint32 x)
{
 while(x--); 
}
//****************************************************************************************************
bit check_1602()//***********判断1602是否处于忙状态
{
 P0=0xff;
 RS=0;
 RW=1;
 ENLCD=0;
 delay(50);
 ENLCD=1;
 return((bit)(P0&0x80)); 
}
//****************************************************************************************************
void write_com(uint8 com)//向1602写入一命令
{
 while(check_1602());//***首先判断1602是否在忙  忙则等待
 RS=0;
 RW=0;
 ENLCD=1;
 P0=com;
 delay(50);
 ENLCD=0;
 
}
//****************************************************************************************************
void write_dat(uint8 dat)//**向1602写入一字节数据
{
 while(check_1602());//**首先判断1602是否在忙  忙则等待
 RS=1;
 RW=0;
 ENLCD=1;
 P0=dat;
 delay(50);
 ENLCD=0;
}
//****************************************************************************************************
void init_1602()//**********1602初始化
{
 write_com(0x38);
 delay(1000);
 write_com(0x38);
 delay(1000);
 write_com(0x38);
 write_com(0x08);
 write_com(0x01);
 write_com(0x06);
 write_com(0x0c);
}
//****************************************************************************************************
void w_string(uint8 string[],uint8 x,uint8 y)//写入字符型数组  x代表从第一行的第几个方格开始显示
{ 
 uint8 i=0;          //y 代表在第几行
 if(y==1)
 {
  while(string[i]!=0)
  {
  write_com(0x80+i+x);
  write_dat(string[i]);
  i++;
  };
  i=0;
 }
 if(y==2)
 {
  while(string[i]!=0)
  {
  write_com(0xc0+i+x);
  write_dat(string[i]);
  i++;
  };
  i=0; 
 } 
}
//****************************************************************************************************
void w_char(uint8 c,x,y)//*********向1602写入一个字符
{
 if(y==1)
 {
  write_com(0x80+x);
  write_dat(c);
  
 }
 if(y==2)
 {
  write_com(0xc0+x);
  write_dat(c);
   
 } 
}
//****************************************************************************************************
void H_1602()//********************1602要显示的内容
{ 
 w_char(2+48,0,1);
 w_char(48,1,1);
 w_char(year/10%10+48,2,1);
 w_char(year%10+48,3,1);
 w_char(':',4,1);
 w_char(month/10+48,5,1);
 w_char(month%10+48,6,1);
 w_char(':',7,1);
 w_char(day/10+48,8,1);
 w_char(day%10+48,9,1);
 w_string(D,11,1);
 w_char(':',14,1);
 w_char(week%10+48,15,1);
 w_char(hour/10+48,0,2);
 w_char(hour%10+48,1,2);
 w_char(':',2,2);
 w_char(minute/10+48,3,2);
 w_char(minute%10+48,4,2);
 w_char(':',5,2);
 w_char(second/10+48,6,2);
 w_char(second%10+48,7,2);
 w_char((uint8)T/10%10+48,9,2);
 w_char((uint8)T%10+48,10,2);
 w_char('.',11,2);
 w_char((uint16)(T*10)%10+48,12,2);
 w_char(0xdf,13,2);//显示圆点
 w_char(67,14,2);//显示大写字母C
}
void closeLED()//******************关闭数码管函数
{
 shang=0x00;
 xia=0x00;
}
//****************************************************************************************************
void init()
{
 timer0_init();
 ds1302_init();
 init_1602();
 closeLED();
}
//****************************************************************************************************
main()
{
 init();
 beginchange();
 while(1)
 {
 jishi0();
 H_1602();
 }
}
关闭窗口

相关文章