×
单片机 > 单片机程序设计 > 详情

LCD1602-DS1302时钟程序

发布时间:2020-06-08 发布时间:
|
//DS1302时钟程序      
#include
#include
#define uchar unsigned char
#define uint unsigned int

/********************************************************************/
//少占鱼制作  河北正定欢迎您   长沙航空职业技术学院 
//2010 年QQ:411656434
//版权所有:www.51hei.com
#define LCD1602_RS  P2_5 //定义引脚   
#define LCD1602_RW  P2_6
#define LCD1602_E   P2_7
#define LCD1602_IO  P0

#define Busy    0x80 //用于检测LCD1602状态字中的Busy标识

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};// 初始化时间年月日星期时分秒    
uchar  Display_Buffer[12]={"12:25:00"};//时、分、秒 的格式    
uchar riqi[12]={"11-03-28"};//年、月、日 的格式  
uchar xingqi[5]="week";//星期
unsigned char second,minute,hour,week,day,month,year;
/******************1602函数********************************/

/********************************************************************/
void delays(uint m)
{
uint i,j;
for(i=0;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--);
}

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

/**************************************************************
函数功能:读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了。     
    _nop_();
   DS1302_CLK=1;//读完一位数据,再置高时钟,准备读下一个。  
   _nop_();//延时一下。   

}
  //读完数据还是把时钟清0,下次好直接用。    
  DS1302_CLK=0;//读完数据还是把时钟清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);

}

/*****************************************************
函数功能:向DS1302某地址写一字节数据子程序
入口参数:addr,TDat
出口参数:
************************************************/
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);//再写数据   
DS1302_IO=1;//单片机端置高防止破坏1302传来的数据,开始接收1302端的高低数据对数据线的改变。  
DS1302_RST=0;
      delayus(10);
DS1302_CLK=0;
     delayus(10);
}

/*****************************************************
函数功能:读DS1302地址子程序
入口参数:add
出口参数: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();//再读出数据   
DS1302_IO=1;//单片机端置高防止破坏1302传来的数据,开始接收1302端的高低数据对数据线的改变。  
DS1302_RST=0;
      delayus(10);
DS1302_CLK=0;
     delayus(10);
return(timedata);
}

/***************************************
函数功能:初始化DS1302子程序
入口参数:time[](全局变量)
出口参数:
*************************************************************/
void initial_ds1302()
{
DS1302_IO=1;//单片机端置高防止破坏1302传来的数据,开始接收1302端的高低数据对数据线的改变。  
DS1302_RST=0;
      delayms(100);
DS1302_CLK=0;
     delayms(100);
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);   //秒寄存器 
_nop_();
minute=read_ds1302(0x83);   //读分
_nop_();
hour=read_ds1302(0x85);    //读时
_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(); //启动等待,等LCM讲入工作状态
delays(1);
LCD1602_Init(); //LCM初始化  
Delay5Ms(); //延时片刻(可不要)
  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();//读取时间
    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';
    Displaystring(3,0,riqi);
     delayms(1);
    DisplayOneChar(14,1,week+'0');
    Displaystring(3,1,Display_Buffer);

}
}


//写数据 
void WriteData(uchar DAT)
{
Readbusy();
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_IO = DAT;
LCD1602_E = 0; //若晶振速度太高可以在这后加小的延时   
LCD1602_E = 0; //延时
LCD1602_E = 1;
LCD1602_E=1;
LCD1602_E=0;
}

//写指令  
void WriteCommand(uchar command,BuysC) //BuysC为0时忽略忙检测
{
LCD1602_IO=0x00;
if (BuysC)
Readbusy(); //根据需要检测忙    

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

//读数据 
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); //检测忙信号 
  LCD1602_E = 0;
}
//初始化
void LCD1602_Init(void) //LCM初始化
{
Delay400Ms();
LCD1602_E = 0;
LCD1602_IO=0x00;
WriteCommand(0x38,0); //三次显示模式设置,不检测忙信号
Delay5Ms();
WriteCommand(0x38,0);
Delay5Ms();
WriteCommand(0x38,0);
Delay5Ms();

WriteCommand(0x38,1); //显示模式设置,开始要求每次检测忙信号
Delay5Ms();
WriteCommand(0x08,1); //关闭显示   ]
Delay5Ms();
WriteCommand(0x01,1); //显示清屏  
Delay5Ms();
WriteCommand(0x06,1); // 显示光标移动设置   
Delay5Ms();
WriteCommand(0x0f,1); // 显示开及光标设置   
Delay5Ms();
}

//按指定位置显示一个字符
void DisplayOneChar(uchar X, uchar Y, uchar DData)
{
Y &= 0x01;
X &= 0x0f; //限制X不能大于15,Y不能大于1 
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
X |= 0x80; // 算出指令码   
WriteCommand(X, 0); //这里不检测忙信号,发送地址码 
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) //若到达字串尾则退出
  {
   if (X <= 0x0f) //X坐标应小于0x0f 
    {
     DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
     ListLength++;
     X++;
    }
  }
}

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

//400ms延时
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  {
    for(j=0;j<121;j++)
     {;}
   }
}
void delayus(uchar x)     
{
    while(--x);
}



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32中断向量表的位置.重定向