專注電子技術學習與研究
當前位置:單片機教程網(wǎng) >> MCU設計實例 >> 瀏覽文章

51單片機+ds1302+ds18b20+1602液晶萬年歷

作者:佚名   來源:本站原創(chuàng)   點擊數(shù):  更新時間:2012年11月22日   【字體:

  這是我寫的單片機小程序,將單片機開發(fā)板上的ds1302,ds18b20和1602綜合起來,在1602上顯示年月日周時分秒和溫度;望各位好友指點,此程序僅適用于我的開發(fā)板,用在其他開發(fā)板上應該改下端口就可以。


 

 #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()//********************讀取一位數(shù)據(jù)
{
 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讀取一字節(jié)數(shù)據(jù)
{
 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寫入一字節(jié)數(shù)據(jù)
{
 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讀取數(shù)據(jù)并轉換成十進制
{
 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寫入地址和數(shù)據(jù)
{
 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寫地址,再讀數(shù)據(jù)
{ 
 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碼轉換成十進制數(shù)
 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讀取數(shù)據(jù)并將其轉換成顯示函數(shù)直接用到的數(shù)字
{
 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()//每一段時間會進行一次讀取數(shù)字
{
 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;//**************數(shù)據(jù)命令選擇端
sbit RW=P1^1;//**************讀寫選擇端
sbit ENLCD=P2^5;//***********使能端
sbit shang=P2^6;//***********數(shù)碼管數(shù)據(jù)輸入控制端
sbit xia=P2^7;//*************數(shù)碼管共陰極控制端
sbit busy=P0^7;//************判斷忙標志
//****************************************************************************************************
void delay(uint32 x)
{
 while(x--); 
}
//****************************************************************************************************
bit check_1602()//***********判斷1602是否處于忙狀態(tài)
{
 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寫入一字節(jié)數(shù)據(jù)
{
 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)//寫入字符型數(shù)組  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()//******************關閉數(shù)碼管函數(shù)
{
 shang=0x00;
 xia=0x00;
}
//****************************************************************************************************
void init()
{
 timer0_init();
 ds1302_init();
 init_1602();
 closeLED();
}
//****************************************************************************************************
main()
{
 init();
 beginchange();
 while(1)
 {
 jishi0();
 H_1602();
 }
}
關閉窗口

相關文章