时钟——掉电可存

来源:互联网 发布:脸歪 知乎 编辑:程序博客网 时间:2024/05/16 17:06
#include <reg52.h>#include <intrins.h>#include "i2c.h"sbit RS = P2^4;sbit RW = P2^5;sbit EN = P2^6;#define RS_CLR RS=0 #define RS_SET RS=1#define RW_CLR RW=0 #define RW_SET RW=1 #define EN_CLR EN=0#define EN_SET EN=1#define DataPort P0unsigned int sec,min,h;unsigned char dat[3] = 0;//unsigned int i;/******************函数声明********************/void LCD_Init(void);void DelayUs2x(unsigned char t);void DelayMs(unsigned char t);void LCD_Write_Com(unsigned char com);bit LCD_Check_Busy(void);void LCD_Write_Data(unsigned char Data);void LCD_Clear(void);void LCD_Write_String(unsigned char x,unsigned char y, unsigned char *s);void LCD_Write_Char(unsigned char x,unsigned char y, unsigned char Data);/******************中断************************/void ISR_T0(void) interrupt 1{unsigned char j;TH0 = 0X3C;TL0 = 0XB0;j++;if(j == 20){sec++;j = 0;}}  /*****************初始化函数*****************/void LCD_Init(void){LCD_Write_Com(0x38);DelayMs(5);LCD_Write_Com(0x38);     DelayMs(5);     LCD_Write_Com(0x38);     DelayMs(5);     LCD_Write_Com(0x38);      LCD_Write_Com(0x08);    //显示关闭    LCD_Write_Com(0x01);    //显示清屏    LCD_Write_Com(0x06);    //显示光标移动设置     DelayMs(5);     LCD_Write_Com(0x0C);    //显示开及光标设置}/***************us延时函数*******************/void DelayUs2x(unsigned char t)  //延时 = 2 * t + 5 us{while(--t);}/**************ms延时函数 ******************/void DelayMs(unsigned char t) //大致延时1ms{while(t--){DelayUs2x(245);DelayUs2x(245);}}/*****************写入命令函数***************/void LCD_Write_Com(unsigned char com){DelayMs(5);RS_CLR;RW_CLR;EN_SET;DataPort = com;_nop_();   //空指令,延时一个指令周期,延时时间为1usEN_CLR;} /****************判忙函数******************/bit LCD_Check_Busy(void){DataPort = 0xFF;RS_CLR;RW_SET;EN_CLR;_nop_();EN_SET;return (bit)(DataPort & 0x80);}/***************写入数据函数****************/void LCD_Write_Data(unsigned char Data){DelayMs(5);RS_SET;RW_CLR;EN_SET;DataPort = Data;_nop_();EN_CLR;} /*****************清屏函数*******************/void LCD_Clear(void){LCD_Write_Com(0X01);DelayMs(5);} /*****************写入字符串函数******************/void LCD_Write_String(unsigned char x,unsigned char y, unsigned char *s){if(y == 0){LCD_Write_Com(0X80 + x);}else{ LCD_Write_Com(0XC0 + x);}while(*s){ LCD_Write_Data(*s); s++;}}/*****************写入字符函数******************/void LCD_Write_Char(unsigned char x,unsigned char y, unsigned char Data){if(y == 0){LCD_Write_Com(0X80 + x);}else{ LCD_Write_Com(0XC0 + x);}LCD_Write_Data(Data);}#define  _Nop()  _nop_()  //定义空指令                         bit ack;              //应答标志位sbit SDA=P2^1;sbit SCL=P2^0;/***************启动总线******************/void Start_I2c(){SDA=1;   //发送起始条件的数据信号  _Nop();   SCL=1;   _Nop();    //起始条件建立时间大于4.7us,延时   _Nop();   _Nop();   _Nop();   _Nop();       SDA=0;     //发送起始信号   _Nop();    //起始条件锁定时间大于4μ   _Nop();   _Nop();   _Nop();   _Nop();         SCL=0;    //钳住I2C总线,准备发送或接收数据  _Nop();  _Nop();}/******************结束总线******************/void Stop_I2c(){  SDA=0;    //发送结束条件的数据信号  _Nop();   //发送结束条件的时钟信号  SCL=1;    //结束条件建立时间大于4μ  _Nop();  _Nop();  _Nop();  _Nop();  _Nop();  SDA=1;    //发送I2C总线结束信号  _Nop();  _Nop();  _Nop();  _Nop();}/*********************字节数据传送函数**************************/void  SendByte(unsigned char c){ unsigned char BitCnt;  for(BitCnt=0;BitCnt<8;BitCnt++)  //要传送的数据长度为8位    {     if((c<<BitCnt)&0x80)SDA=1;   //判断发送位       else  SDA=0;                     _Nop();     SCL=1;               //置时钟线为高,通知被控器开始接收数据位     _Nop();      _Nop();             //保证时钟高电平周期大于4μ      _Nop();        _Nop();      _Nop();              SCL=0;     }        _Nop();    _Nop();    SDA=1;               //8位发送完后释放数据线,准备接收应答位    _Nop();    _Nop();       SCL=1;    _Nop();    _Nop();    _Nop();    if(SDA==1)ack=0;            else ack=1;        //判断是否接收到应答信号    SCL=0;    _Nop();    _Nop();}/************************字节数据传送函数*************************/unsigned char  RcvByte(){  unsigned char retc;  unsigned char BitCnt;    retc=0;   SDA=1;             //置数据线为输入方式  for(BitCnt=0;BitCnt<8;BitCnt++)    {     _Nop();                   SCL=0;       //置时钟线为低,准备接收数据位        _Nop();        _Nop();      //时钟低电平周期大于4.7us        _Nop();        _Nop();        _Nop();        SCL=1;       //置时钟线为高使数据线上数据有效        _Nop();        _Nop();        retc=retc<<1;        if(SDA==1)retc=retc+1; //读数据位,接收的数据位放入retc中        _Nop();        _Nop();     }    SCL=0;        _Nop();    _Nop();    return(retc);}/*********************应答子函数*********************/void Ack_I2c(void){SDA=0;      _Nop();   _Nop();  _Nop();        SCL=1;    _Nop();  _Nop();              //时钟低电平周期大于4μ  _Nop();  _Nop();    _Nop();    SCL=0;               //清时钟线,钳住I2C总线以便继续接收    _Nop();  _Nop();    }/**********************非应答子函数************************/void NoAck_I2c(void){SDA=1;  _Nop();  _Nop();  _Nop();        SCL=1;  _Nop();  _Nop();              //时钟低电平周期大于4μ  _Nop();  _Nop();  _Nop();    SCL=0;                //清时钟线,钳住I2C总线以便继续接收  _Nop();  _Nop();    }/******************向有子地址器件发送多字节数据函数************************/bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no){unsigned char i;for(i=0;i<no;i++)    {     Start_I2c();               //启动总线   SendByte(sla);             //发送器件地址     if(ack==0)return(0);   SendByte(suba);            //发送器件子地址     if(ack==0)return(0);       SendByte(*s);            //发送数据           if(ack==0)return(0);     Stop_I2c();                  //结束总线     DelayMs(2);               //必须延时等待芯片内部自动处理数据完毕 s++; suba++;    }   return(1);}/**********************向有子地址器件读取多字节数据函数**********************/bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no){unsigned char i;Start_I2c();               //启动总线   SendByte(sla);             //发送器件地址    if(ack==0)return(0);  SendByte(suba);            //发送器件子地址    if(ack==0)return(0);   Start_I2c();   SendByte(sla+1);    if(ack==0)return(0);  for(i=0;i<no-1;i++)    {     *s=RcvByte();              //发送数据      Ack_I2c();                //发送就答位      s++;    }     *s=RcvByte();    NoAck_I2c();                 //发送非应位    Stop_I2c();                    //结束总线  return(1);}/*****************主函数********************/void main(){LCD_Init();TMOD = 0X01;TH0 = 0X3C;TL0 = 0xb0;EA = 1;ET0 = 1;TR0 = 1; IRcvStr(0xae,80,dat,8);  sec = dat[0]; min = dat[1];h = dat[2];                                         while(1){/////////////////////////秒////////////////////////////{LCD_Write_Char(7,0,sec % 10 + '0');  DelayUs2x(2000); LCD_Write_Char(6,0,sec / 10 + '0');  DelayUs2x(2000);if(sec == 60){sec = 0;min++;}dat[0] = sec;}  /////////////////////////分////////////////////////////{LCD_Write_Char(4,0,min % 10 + '0');  DelayUs2x(2000); LCD_Write_Char(3,0,min / 10 + '0');  DelayUs2x(2000);LCD_Write_Char(5,0,':');if(min == 60){min = 0;h++;}dat[1] = min;}/////////////////////////时////////////////////////////{LCD_Write_Char(1,0,h % 10 + '0');  DelayUs2x(2000); LCD_Write_Char(0,0,h / 10 + '0');  DelayUs2x(2000);LCD_Write_Char(2,0,':');if(h == 24){h = 0;}dat[2] = h;}ISendStr(0xae,80,dat,8);}}

0 0
原创粉丝点击