《电子技术应用》

ST7920液晶---DS1302时钟程序

2015/11/4 14:19:00

//DS1302时钟程序
//液晶用的ST7920控制芯片的12864       
#include <reg52.h>
#include <intrins.h>
/********************************************************************/
#define  LCD12864_IO  P0
#define  CLERADISPLAY LCD12864_command(0x01);
#define uchar unsigned char
#define uint unsigned int
/********************************************************************/
sbit LCD12864_EN=P2^7;   //E
sbit LCD12864_DIN=P2^5;  // RS
sbit LCD12864_CLK=P2^6;  //RW
sbit DS1302_CLK =P2^0;// P1^0;
sbit DS1302_IO =P2^1;// P1^1;
sbit DS1302_RST =P2^2;// P1^2;
unsigned char time[]={0x10,0x01,0x27,0x03,0x14,0x00,0x00};// 初始化时间年月日星期时分秒     
uchar Display_Buffer[]="12-22-00";//时、分、秒 的格式
uchar riqi[]="11-03-28";//年、月、日 的格式     
uchar xingqi[]="week-3";//星期  
unsigned char second,minute,hour,week,day,month,year;
/********************************************************************/
void LCD12864_busy(void);
void LCD12864_command(unsigned char command);
void LCD12864_data(unsigned char dat);
void LCD12864_address(unsigned char row,unsigned char line);
void LCD12864_string(unsigned char row,unsigned char line,unsigned char *s);
void LCD12864_picture(unsigned char *gImage);
void LCD12864_init(void);
 void LCD12864_char (unsigned char row,unsigned char line,unsigned char a);
/********************************************************************/
 
//
 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);
 }

void Mcu_init(void)
{
 
 LCD12864_init();
 
 
 CLERADISPLAY 
 CLERADISPLAY 
 LCD12864_init();
}


 


void Delay(void)
{
 unsigned char i;
     unsigned int j;
 for(i=0;i<200;i++)
  for(j=1000;j>0;j--);
}
 
/*****************************************************************************
函数功能:向DS1302送一字节数据子程序
入口参数:
出口参数:
*****************************************************************************/
void InputByte(unsigned char BYTE)
{
char i;
for(i=8;i>0;i--)
{  //前面在read_ds1302()函数里已经把CLK清0了    
   DS1302_CLK=0;//这里再清0一次,看着清楚。呵呵   
   DS1302_IO=(bit)(BYTE&0x01);//取出低位数据给数据引脚    
    DS1302_CLK=1;//置1,时钟上升沿,引脚上的数据传入1302寄存器中   
   BYTE>>=1;//因为这里移位的BYTE不是最后要的结果,虽然最后循环完会多移一位,但没影响。
 //循环最后一次后,时钟状态是高电平。  
}
}


/*****************************************************************************
函数功能:读DS1302一个字节子程序,读数据是下降沿读
入口参数:
出口参数:
*****************************************************************************/
unsigned char OutputByte(void)
{
unsigned char i;
unsigned char ucdat=0;
for(i=8;i>0;i--)
{  //前面时钟状态是高电平。  
    ucdat>>=1; //移位注意,移位不能放在循环语句末,否则最后循环完会多移一位。得到结果就错了。
   DS1302_IO=1;//单片机端置高防止破坏1302传来的数据,开始接收1302端的高低数据对数据线的改变。    
   DS1302_CLK=0;//紧接着时钟变低,下降沿数据输出。 
   if(DS1302_IO)//数据已经输出,判断是1还是0.  
   ucdat|=0x80;//如果引脚是高则此位保存1。低不保存,右移的时候自然补0了。  
   DS1302_CLK=1;//读完一位数据,再置高时钟,准备读下一个。   
   _nop_();//延时一下。    
 
}
  //读完数据还是把时钟清0,下次好直接用。     
  DS1302_CLK=0;//读完数据还是把时钟清0,下次好直接用。   
DS1302_RST=0;
_nop_();
DS1302_CLK=0;
 DS1302_RST=0;
 return(ucdat);


}


/*****************************************************************************
函数功能:向DS1302某地址写一字节数据子程序
入口参数:addr,TDat
出口参数:
*****************************************************************************/
void write_ds1302(unsigned char addr,unsigned char TDat)
{
   DS1302_RST=0;
   _nop_();
   DS1302_CLK=0;
    _nop_();
   DS1302_RST=1;
    _nop_();
   InputByte(addr);//先写地址 
   InputByte(TDat);//再写数据    
 DS1302_IO=1;//单片机端置高防止破坏1302传来的数据,开始接收1302端的高低数据对数据线的改变。   
 DS1302_RST=0;
   _nop_();
 DS1302_CLK=0;
}


/*****************************************************************************
函数功能:读DS1302地址子程序   
入口参数:add
出口参数:timedata
*****************************************************************************/
unsigned char read_ds1302(unsigned char addr)
{
unsigned char timedata;
DS1302_RST=0;
DS1302_CLK=0;
DS1302_RST=1;
InputByte(addr);//先写入读命令   
timedata=OutputByte();//再读出数据    
 DS1302_IO=1;//单片机端置高防止破坏1302传来的数据,开始接收1302端的高低数据对数据线的改变。   
 DS1302_RST=0;
  _nop_();
 DS1302_CLK=0;
return(timedata);
}


/*****************************************************************************
函数功能:初始化DS1302子程序
入口参数:time[](全局变量)
出口参数:
*****************************************************************************/
void initial_ds1302()
{
 DS1302_IO=1;//单片机端置高防止破坏1302传来的数据,开始接收1302端的高低数据对数据线的改变。   
 DS1302_RST=0;
 DS1302_CLK=0;
write_ds1302(0x8e,0x00);   //写保护寄存器,在对时钟或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]);   //时  
write_ds1302(0x82,time[5]);   //分 
write_ds1302(0x80,time[6]);   //秒  
write_ds1302(0x8e,0x80);   //写保护寄存器 
}



/*****************************************************************************
函数功能:读DS1302时间子程序
入口参数:
出口参数:全局变量(second,minute,hour,week,day,month,year)
*****************************************************************************/
void read_time()
{
second=read_ds1302(0x81);   //秒寄存器  
minute=read_ds1302(0x83);   //读分 
hour=read_ds1302(0x85);    //读时 
//week=read_ds1302(0x8B);    //读星期  
//day=read_ds1302(0x87);    //日  
//month=read_ds1302(0x89);   //月  
//year=read_ds1302(0x8d);    //年  
}


void main(void)
{
Mcu_init();
 DS1302_RST=0;
 DS1302_IO=1;
      delayms(1000);
    DS1302_CLK=0;
     delayms(1000);
initial_ds1302();     //初始化DS1302


 Delay();Delay();
 CLERADISPLAY 
  LCD12864_string(1,1,"日期");
 LCD12864_string(2,1,"星期");
 LCD12864_string(3,1,"时间");
 while(1)
 {


    read_time();//读取时间 
    Display_Buffer[0]=hour/16+'0';//存储下时的高位进数组
    Display_Buffer[1]=hour%16+'0';//存储下时的低位进数组
    Display_Buffer[3]=minute/16+'0';//注意+'0'后存储的是ASCII。用于下面液晶显示。
    Display_Buffer[4]=minute%16+'0';//注意+'0'后存储的是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';
  //  xingqi[1]=week%16+'0';


// LCD12864_string(1,3,riqi);//液晶的第1行从第3位开始显示日期
// LCD12864_string(2,3,xingqi);//液晶的第2行从第3位开始显示星期
 LCD12864_string(3,3,Display_Buffer);//液晶的第3行从第3列开始显示时间
 }
}


/*******************************************************************/
void LCD12864_busy(void)
{
    bit BF = 0;
    LCD12864_EN=0;
    LCD12864_DIN=0;
    LCD12864_CLK=1;
    LCD12864_IO=0xff;  //单片机读数据之前必须先置高位
    do
    {
     LCD12864_EN=1;
        BF=LCD12864_IO&0x80;
        LCD12864_EN=0;
    } while(BF);
   
}
/*******************************************************************/
//          写入命令 
/*******************************************************************/
void LCD12864_command(unsigned char command)
{
    LCD12864_busy();
    LCD12864_EN=0;
    LCD12864_DIN=0;
    LCD12864_CLK=0; 
   LCD12864_IO=0xff;
    LCD12864_EN=1;
    LCD12864_IO=command;
    LCD12864_EN=0;
}
/*******************************************************************/
//          写入一字节数据
/*******************************************************************/
void LCD12864_data(unsigned char dat)
{
  
    LCD12864_busy();
    LCD12864_EN=0;
    LCD12864_DIN=1;
    LCD12864_CLK=0;
    LCD12864_IO=0xff;
    LCD12864_EN=1;
    LCD12864_IO=dat;
    LCD12864_EN=0;
}



/*******************************************************************/
//          设置显示位置    X(1~8),Y(1~4)
/*******************************************************************/
void LCD12864_address(unsigned char row,unsigned char line)
{
    switch(row)
    {
        case 1:LCD12864_command(0x7f + line);
        break;
        case 2:LCD12864_command(0x8f + line);
        break;
        case 3:LCD12864_command(0x87 + line);
        break;
        case 4:LCD12864_command(0x97 + line);
        default:
        break;
    }
}


 /*****************显示 一个 字符  **************/


  void LCD12864_char (unsigned char row,unsigned char line,unsigned char a)
{
 
    LCD12864_address(row,line);
    LCD12864_data(a);
}


/*******************************************************************/
//          在指定位置显示字符串
/*******************************************************************/
void LCD12864_string(unsigned char row,unsigned char line,unsigned char *s)
{
    unsigned char LCD12864_temp;
    LCD12864_address(row,line);
    LCD12864_temp=*s;
    while(LCD12864_temp != 0x00)
    {
        LCD12864_data(LCD12864_temp);
        LCD12864_temp=*(++s);
    } 
}


/*******************************************************************/
//          绘制一幅图片  
/*******************************************************************/
void LCD12864_picture(unsigned char *gImage)
{
    unsigned char X = 0x80,Y = 0x80;
    unsigned char i,j;
    for(i=0;i<64;i++)
    {
        for(j=0;j<16;j++)
        {
            LCD12864_command(0x34);
            LCD12864_command(Y);
            LCD12864_command(X);
            LCD12864_data(*(gImage+i*16+j));      //  low 8 bits
            LCD12864_data(*(gImage+i*16+j+1));    //  high 8 bits
            LCD12864_command(0x36);
            X++;
            j++;
        }
        Y++;
        if(Y>0x9f)
            Y=0x80;
        X=0x80+((i+1)/32)*8;
    }
    LCD12864_command(0x30);
  
}
/*******************************************************************/
//          初始化设置
/*******************************************************************/
void LCD12864_init(void)
{
    CLERADISPLAY      //  clear DDRAM
    LCD12864_command(0x30);     //  8 bits unsigned interface,basic instrument
    LCD12864_command(0x02);     //  cursor return
    LCD12864_command(0x0c);     //  display,cursor on
    LCD12864_command(0x03);  
    LCD12864_command(0x06);
    CLERADISPLAY       //  clear DDRAM
}

继续阅读>>