專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

LCD1602-DS1302時(shí)鐘程序

作者:佚名   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2011年03月30日   【字體:
  //DS1302時(shí)鐘程序       
#include <stc89c52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int

/********************************************************************/
//少占魚制作  河北正定歡迎您   長(zhǎng)沙航空職業(yè)技術(shù)學(xué)院  
//2010 年QQ:411656434
//版權(quán)所有:www.torrancerestoration.com
#define LCD1602_RS  P2_5 //定義引腳    
#define LCD1602_RW  P2_6
#define LCD1602_E   P2_7
#define LCD1602_IO  P0

#define Busy    0x80 //用于檢測(cè)LCD1602狀態(tài)字中的Busy標(biāo)識(shí)

const uchar num[]="  3456789+";
uchar code a[] = {"  E N v"};
void WriteData(uchar DAT);
void WriteCommand(uchar command,BuysC);
uchar ReadData(void);
void Readbusy(void);
void LCD1602_Init(void);
void DisplayOneChar(uchar X, uchar Y, uchar DData);
void Displaystring(uchar X, uchar Y, uchar *DData);
void Delay5Ms(void);
void Delay400Ms(void);
void delayms(uint);
void delays(uint m) ;
void delayus(uchar x) ;
sbit DS1302_CLK =P2^0;// P1^0;
sbit DS1302_IO =P2^1;// P1^1;
sbit DS1302_RST =P2^2;// P1^2;

uchar shuju;
unsigned char time[]={0x11,0x03,0x28,0x01,0x12,0x39,0x00};// 初始化時(shí)間年月日星期時(shí)分秒     
uchar  Display_Buffer[12]={"12:25:00"};//時(shí)、分、秒 的格式     
uchar riqi[12]={"11-03-28"};//年、月、日 的格式   
uchar xingqi[5]="week";//星期
unsigned char second,minute,hour,week,day,month,year;
/******************1602函數(shù)********************************/

/********************************************************************/
 void delays(uint m)
{
uint i,j;
for(i=0;i<m;i++)
  {
    for(j=0;j<1000;j++)
     {;}
   }
}


void Delay(void)
{
 unsigned char i;
     unsigned int j;
 for(i=0;i<200;i++)
  for(j=300;j>0;j--);
}
 
/*****************************************************************************
函數(shù)功能:向DS1302送一字節(jié)數(shù)據(jù)子程序
入口參數(shù):
出口參數(shù):
*****************************************************************************/
void InputByte(unsigned char BYTE)
{
char i;
for(i=8;i>0;i--)
{  //前面在read_ds1302()函數(shù)里已經(jīng)把CLK清0了    
   DS1302_CLK=0;//這里再清0一次,看著清楚。呵呵   
   _nop_();
   DS1302_IO=(bit)(BYTE&0x01);//取出低位數(shù)據(jù)給數(shù)據(jù)引腳    
    _nop_();
    _nop_();
    DS1302_CLK=1;//置1,時(shí)鐘上升沿,引腳上的數(shù)據(jù)傳入1302寄存器中   
   _nop_();
    _nop_();
   BYTE>>=1;//因?yàn)檫@里移位的BYTE不是最后要的結(jié)果,雖然最后循環(huán)完會(huì)多移一位,但沒影響。
    _nop_();
 //循環(huán)最后一次后,時(shí)鐘狀態(tài)是高電平。  
}
  _nop_();
   _nop_();
}

/*****************************************************************************
函數(shù)功能:讀DS1302一個(gè)字節(jié)子程序,讀數(shù)據(jù)是下降沿讀
入口參數(shù):
出口參數(shù):
*****************************************************************************/
unsigned char OutputByte(void)
{
unsigned char i;
unsigned char ucdat=0;
for(i=8;i>0;i--)
{  //前面時(shí)鐘狀態(tài)是高電平。  
    ucdat>>=1; //移位注意,移位不能放在循環(huán)語句末,否則最后循環(huán)完會(huì)多移一位。得到結(jié)果就錯(cuò)了。
   DS1302_IO=1;//單片機(jī)端置高防止破壞1302傳來的數(shù)據(jù),開始接收1302端的高低數(shù)據(jù)對(duì)數(shù)據(jù)線的改變。    
   DS1302_CLK=0;//緊接著時(shí)鐘變低,下降沿?cái)?shù)據(jù)輸出。 
   if(DS1302_IO)//數(shù)據(jù)已經(jīng)輸出,判斷是1還是0.  
   ucdat|=0x80;//如果引腳是高則此位保存1。低不保存,右移的時(shí)候自然補(bǔ)0了。      
    _nop_();
   DS1302_CLK=1;//讀完一位數(shù)據(jù),再置高時(shí)鐘,準(zhǔn)備讀下一個(gè)。   
   _nop_();//延時(shí)一下。    
 
}
  //讀完數(shù)據(jù)還是把時(shí)鐘清0,下次好直接用。     
  DS1302_CLK=0;//讀完數(shù)據(jù)還是把時(shí)鐘清0,下次好直接用。   
     _nop_();
 _nop_();
DS1302_RST=0;
_nop_();
 _nop_();
 _nop_();
 _nop_();
 _nop_();
 _nop_();
DS1302_CLK=0;
_nop_();
 _nop_();
 _nop_();
 _nop_();
 DS1302_RST=0;
 _nop_();
 _nop_();
 _nop_();
 _nop_();
   _nop_();
    return(ucdat);

}

/*****************************************************************************
函數(shù)功能:向DS1302某地址寫一字節(jié)數(shù)據(jù)子程序
入口參數(shù):addr,TDat
出口參數(shù):
*****************************************************************************/
void write_ds1302(unsigned char addr,unsigned char TDat)
{
   DS1302_RST=0;
   _nop_();
    _nop_();
   DS1302_CLK=0;
   _nop_();
    _nop_();
   DS1302_RST=1;
    _nop_();
    _nop_();
     _nop_();
    _nop_();
   InputByte(addr);//先寫地址    
    _nop_();
     _nop_();
   InputByte(TDat);//再寫數(shù)據(jù)    
 DS1302_IO=1;//單片機(jī)端置高防止破壞1302傳來的數(shù)據(jù),開始接收1302端的高低數(shù)據(jù)對(duì)數(shù)據(jù)線的改變。   
 DS1302_RST=0;
      delayus(10);
 DS1302_CLK=0;
     delayus(10);
}

/*****************************************************************************
函數(shù)功能:讀DS1302地址子程序
入口參數(shù):add
出口參數(shù):timedata
*****************************************************************************/
unsigned char read_ds1302(unsigned char addr)
{
unsigned char timedata;
DS1302_RST=0;
_nop_();
DS1302_CLK=0;
_nop_();
DS1302_RST=1;
InputByte(addr);//先寫入讀命令   
timedata=OutputByte();//再讀出數(shù)據(jù)    
 DS1302_IO=1;//單片機(jī)端置高防止破壞1302傳來的數(shù)據(jù),開始接收1302端的高低數(shù)據(jù)對(duì)數(shù)據(jù)線的改變。   
 DS1302_RST=0;
      delayus(10);
 DS1302_CLK=0;
     delayus(10);
return(timedata);
}

/*****************************************************************************
函數(shù)功能:初始化DS1302子程序
入口參數(shù):time[](全局變量)
出口參數(shù):
*****************************************************************************/
void initial_ds1302()
{
 DS1302_IO=1;//單片機(jī)端置高防止破壞1302傳來的數(shù)據(jù),開始接收1302端的高低數(shù)據(jù)對(duì)數(shù)據(jù)線的改變。   
 DS1302_RST=0;
      delayms(100);
 DS1302_CLK=0;
     delayms(100);
write_ds1302(0x8e,0x00);   //寫保護(hù)寄存器,在對(duì)時(shí)鐘或RAM寫前WP一定要為0
write_ds1302(0x8c,time[0]);   //年 
write_ds1302(0x88,time[1]);   //月 
write_ds1302(0x86,time[2]);   //日 
write_ds1302(0x8A,time[3]);   //星期 
write_ds1302(0x84,time[4]);   //時(shí)  
write_ds1302(0x82,time[5]);   //分 
write_ds1302(0x80,time[6]);   //秒  
write_ds1302(0x8e,0x80);   //寫保護(hù)寄存器 
}

/*****************************************************************************
函數(shù)功能:讀DS1302時(shí)間子程序
入口參數(shù):
出口參數(shù):全局變量(second,minute,hour,week,day,month,year)
*****************************************************************************/
void read_time()
{
second=read_ds1302(0x81);   //秒寄存器  
 _nop_();
minute=read_ds1302(0x83);   //讀分 
 _nop_();
hour=read_ds1302(0x85);    //讀時(shí) 
 _nop_();
week=read_ds1302(0x8B);    //讀星期  
 _nop_();
day=read_ds1302(0x87);    //日  
 _nop_();
month=read_ds1302(0x89);   //月 
 _nop_();
year=read_ds1302(0x8d);    //年 
 _nop_(); 
}

void main(void)
{uchar shuju;
 delayms(2);
 Delay400Ms(); //啟動(dòng)等待,等LCM講入工作狀態(tài)
 delays(1);
 LCD1602_Init(); //LCM初始化   
 Delay5Ms(); //延時(shí)片刻(可不要) 
  DS1302_RST=0;
      delayms(1000);
    DS1302_CLK=0;
     delayms(1000);
 shuju=ReadData();
 Displaystring(2, 0, a);
 Delay();Delay();
 delayms(2000);
 Displaystring(3,0,riqi);
  Displaystring(12,0,xingqi);
 delayms(4000);
 // initial_ds1302();     //初始化DS1302
     delayms(1200);
 while(1)
 {
        read_time();//讀取時(shí)間 
    Display_Buffer[0]=hour/16+'0';//存儲(chǔ)下時(shí)的高位進(jìn)數(shù)組
    Display_Buffer[1]=hour%16+'0';//存儲(chǔ)下時(shí)的低位進(jìn)數(shù)組
    Display_Buffer[3]=minute/16+'0';//注意+'0'后存儲(chǔ)的是ASCII。用于下面液晶顯示。
    Display_Buffer[4]=minute%16+'0';//注意+'0'后存儲(chǔ)的是ASCII。用于下面液晶顯示。
    Display_Buffer[6]=second/16+'0';
    Display_Buffer[7]=second%16+'0';
    riqi[0]=year/16+'0';
    riqi[1]=year%16+'0';
    riqi[3]=month/16+'0';
    riqi[4]=month%16+'0';
    riqi[6]=day/16+'0';
    riqi[7]=day%16+'0';
    Displaystring(3,0,riqi);
     delayms(1);
    DisplayOneChar(14,1,week+'0');
    Displaystring(3,1,Display_Buffer);

 }
}


//寫數(shù)據(jù)  
void WriteData(uchar DAT)
{
 Readbusy();
 LCD1602_RS = 1;
 LCD1602_RW = 0;
 LCD1602_IO = DAT;
 LCD1602_E = 0; //若晶振速度太高可以在這后加小的延時(shí)    
 LCD1602_E = 0; //延時(shí) 
 LCD1602_E = 1;
 LCD1602_E=1;
 LCD1602_E=0;
}

//寫指令   
void WriteCommand(uchar command,BuysC) //BuysC為0時(shí)忽略忙檢測(cè)
{
 LCD1602_IO=0x00;
 if (BuysC)
 Readbusy(); //根據(jù)需要檢測(cè)忙     

 LCD1602_RS = 0;
 LCD1602_RW = 0;
 LCD1602_IO = command;
 LCD1602_E = 0;
 LCD1602_E = 0;
 LCD1602_E = 1;
 LCD1602_E = 1;
 LCD1602_E=0;
}

//讀數(shù)據(jù)  
uchar ReadData(void)
{
Readbusy();
 LCD1602_RS = 1;
 LCD1602_RW = 1;
 LCD1602_E = 0;
 LCD1602_E = 0;
 LCD1602_E = 1;
 delayms(1);
 LCD1602_E = 0;
 return(LCD1602_IO);

}

//讀忙
void Readbusy(void)
{
 LCD1602_IO = 0xff;
 LCD1602_RS = 0;
 LCD1602_RW = 1;
 LCD1602_E = 0;
 LCD1602_E = 0;
 LCD1602_E = 1;
 delayms(2);

 while (LCD1602_IO&0x80); //檢測(cè)忙信號(hào)  
  LCD1602_E = 0;
}
 //初始化
void LCD1602_Init(void) //LCM初始化
{
 Delay400Ms();
 LCD1602_E = 0;
 LCD1602_IO=0x00;
 WriteCommand(0x38,0); //三次顯示模式設(shè)置,不檢測(cè)忙信號(hào)
 Delay5Ms();
 WriteCommand(0x38,0);
 Delay5Ms();
 WriteCommand(0x38,0);
 Delay5Ms();

 WriteCommand(0x38,1); //顯示模式設(shè)置,開始要求每次檢測(cè)忙信號(hào)
 Delay5Ms();
 WriteCommand(0x08,1); //關(guān)閉顯示   ] 
 Delay5Ms();
 WriteCommand(0x01,1); //顯示清屏   
 Delay5Ms();
 WriteCommand(0x06,1); // 顯示光標(biāo)移動(dòng)設(shè)置    
 Delay5Ms();
 WriteCommand(0x0f,1); // 顯示開及光標(biāo)設(shè)置    
 Delay5Ms();
}

//按指定位置顯示一個(gè)字符 
void DisplayOneChar(uchar X, uchar Y, uchar DData)
{
 Y &= 0x01;
 X &= 0x0f; //限制X不能大于15,Y不能大于1  
 if (Y) X |= 0x40; //當(dāng)要顯示第二行時(shí)地址碼+0x40;
 X |= 0x80; // 算出指令碼    
 WriteCommand(X, 0); //這里不檢測(cè)忙信號(hào),發(fā)送地址碼  
 WriteData(DData);
}

//按指定位置顯示一串字符 
void Displaystring(uchar X, uchar Y, uchar  *DData)
{
 uchar ListLength;

  ListLength = 0;
 Y &= 0x01;
 X &= 0x0f; //限制X不能大于15,Y不能大于1
 while (DData[ListLength]>0x20) //若到達(dá)字串尾則退出 
  {
   if (X <= 0x0f) //X坐標(biāo)應(yīng)小于0x0f  
    {
     DisplayOneChar(X, Y, DData[ListLength]); //顯示單個(gè)字符
     ListLength++;
     X++;
    }
  }
}

//5ms延時(shí)
void Delay5Ms(void)
{
 unsigned int t = 5552;
 while(t--);
}

//400ms延時(shí)
void Delay400Ms(void)
{
  uchar i = 5;
  uint j;
  while(i--)
   {
  j=7269;
  while(j--);
   }
 }
 //
 void delayms(uint k)
 {
uint data i,j;
for(i=0;i<k;i++)
  {
    for(j=0;j<121;j++)
     {;}
   }
 }
void delayus(uchar x)      
 {
    while(--x);
 }
關(guān)閉窗口

相關(guān)文章