⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eeprom_ht1380.c

📁 自己的平时一些制作 现在整理一下 与大家一起分享
💻 C
字号:
#pragma ot(5,SIZE)
#include <reg51.h>
#include <intrins.h>

/******定义蜂鸣器接口******/
sbit beep=P1^7;
/*****定义EEPROM接口及相关参数******/
#define ERRORCOUNT 10
sbit SDA=P3^3;
sbit SCL=P3^5;
enum eepromtype {M2401,M2402,M2404,M2408,M2416,M2432,M2464,M24128,M24256};
enum eepromtype EepromType;           /* 器件类型枚举变量取值为0-8 */

/*****定义ht1380芯片接口********/
// ht1380 ht1380_sclk --->P1.0
// ht1380 I/O  --->P1.1
// ht1380 ht1380_rest --->P1.2
sbit ht1380_sclk=P1^0;
sbit ht1380_data=P1^1;
sbit ht1380_rest=P1^2;
/**********定义两个全局变量*********/
//定义数组变量用于存放四个数码管的显示数据
//定义number存放动态显示是第几个数码管
unsigned char d[4],number=0;

/*********定义时间变量年月日时分秒***********/
unsigned char year,month,day,hour,minute,second;
/**********定义冒号变量 distime=1 是数码管冒号显示出来************/
bit distime=1;

/*******与数码管相关的两个表*********/
//一个显示译码表
//一个使能译码表
unsigned char code tab[10]={0x3f,6,0x5b,0x4f,0x66,0x6d,0x7d,7,0x7f,0x6f};
unsigned char code digit[4]={0xf8,0xf4,0xf2,0xf1};

/******延时程序***********/
void delay(unsigned char dy)
{
   while(--dy);
}
/*******  ht1380 子程序*****************/
//------------- sent_char to ht1380----------
//上升沿写入
void sent_char(unsigned char sentchar)
{
 unsigned char ii;  

 for(ii=0;ii<8;ii++)
    {
      ht1380_sclk=0;
      if ((sentchar & 1)!=0) ht1380_data=1;
      else ht1380_data=0;
      ht1380_sclk=1;
      sentchar=sentchar>>1;
    }
}
//------------- get_char from ht1380---------
unsigned char get_char()
{
 unsigned char getchar,ii,temp;
    getchar=0;temp=1;
    for(ii=0;ii<8;ii++)
      {
       ht1380_sclk=0;
       ht1380_data=1;
       if(ht1380_data==1) getchar=getchar |temp;
       ht1380_sclk=1;
       temp=temp<<1;
      }
    return(getchar);
}
 
//-------------set_wp_off------------------
void set_wp_off()
{
    ht1380_rest=1;
    sent_char(0x8e);     //10001110b
    sent_char(0);        //00000000b
    ht1380_sclk=0;
    ht1380_rest=0;
}
//-----------set_wp_on--------------------
void set_wp_on()
{
  ht1380_rest=1;
  sent_char(0x8e);       //10001110b
  sent_char(0x80);       //10000000b
  ht1380_sclk=0;
  ht1380_rest=0;
}
//----------read_time --------------------
void read_time()
 {
  unsigned char temp;
    ht1380_rest=1;
    sent_char(0xbf);      //10111111b
    second=get_char();
    minute=get_char();
    hour=  get_char();
    day=   get_char();
    month= get_char();
    temp=  get_char();   /* week day */
    year=  get_char();
    temp=  get_char();            
    ht1380_sclk=0;
    ht1380_rest=0;
   
 }
//--------------set time-----------------
void set_time()
 {
   set_wp_off();
   ht1380_rest=1;
   sent_char(0xbe);      //10111110b
   sent_char(second);
   sent_char(minute);
   sent_char(hour);
   sent_char(day);
   sent_char(month);
   sent_char(1);         /* week  day */
   sent_char(year);
   sent_char(0);
   ht1380_sclk=0;
   ht1380_rest=0;
   set_wp_on();
 }

/******EEPROM 24cxx**********/
/***********************************************************************************/
bit RW24XX(unsigned char *DataBuff,unsigned char ByteQuantity,unsigned int Address,
unsigned char ControlByte,enum eepromtype EepromType)
{
  void Delay(unsigned char DelayCount);
  void IICStart(void);
  void IICStop(void);
  bit IICRecAck(void);
  void IICNoAck(void);
  void IICAck(void);
  unsigned char IICReceiveByte(void);
  void IICSendByte(unsigned char sendbyte);
  unsigned char data j,i=ERRORCOUNT;
  bit errorflag=1;                      /* clr errorflag */
  while(i--)                            /* 启动IIC总线并发送EEPROM从器件地址 */
   {
    IICStart();                         /* 启动IIC总线 */
    IICSendByte(ControlByte&0xfe);      /* 发送EEPROM地址 */
    if(IICRecAck())                     /* 接收EEPROM应答信号 */
      continue;                         /* 接收EEPROM应答信号,为1重新启动 */
    if(EepromType>M2416)                /* EEPROM为24C32以上器件内地址为2字节 */
      {
        IICSendByte((unsigned char)(Address>>8));/* 先发送高字节,参考硬件相关说明 */
        if(IICRecAck())
           continue;
      }
    IICSendByte((unsigned char)Address);/* 再发送低字节或单字节地址 */
    if(IICRecAck())
      continue;
    if(!(ControlByte&0x01))             /* 以下为写操作 */
      {
        j=ByteQuantity;                 /* ByteQuantity为写入字节数 */
        errorflag=0;
        while(j--)
          {
            IICSendByte(*DataBuff++);   /* DataBuff写操作缓冲区 */
            if(!IICRecAck())
              continue;
            errorflag=1;
            break;
          }
        if(errorflag==1)
          continue;
        break;
     }
    else                                /* 以下为读操作 */
     {
      IICStart();                       /* 重新启动IIC总线并发送EEPROM从器件地址 */
      IICSendByte(ControlByte);
      if(IICRecAck())
        continue;
      while(--ByteQuantity)             /* 每次读一字节,共ByteQuantity字节 */
       {
         *DataBuff++=IICReceiveByte();  /*读1字节并存入DataBuff为指针的存储单元 */
         IICAck();                      /* 发送应答信号 */
       }
      *DataBuff=IICReceiveByte();       /*read last byte data*/
      IICNoAck();                       /* 读入最后一字节无须发送应答信号 */
      errorflag=0;
      break;
     }
    }
   IICStop();                           /* 停止IIC总线信号 */
   if(!(ControlByte&0x01))              /* 写入操作需延时,确保足够长写入时间 */
      {
       Delay(255);
       Delay(255);
       Delay(255);
       Delay(255);
      }
   return(errorflag);
}

/*******************
以下是对IIC操作子程序
*******************/
/*******************
      启动IIC
*******************/
void IICStart(void)
{
SCL=0;
SDA=1;
SCL=1;
_nop_();
_nop_();
_nop_();
SDA=0;
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
SDA=1;
}
/*****************
   停止IIC总线
*****************/
void IICStop(void)
{
SCL=0;
SDA=0;
SCL=1;
_nop_();
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
_nop_();
SCL=0;
}
/**************
   检查应答位
**************/
bit IICRecAck(void)
{
SCL=0;
SDA=1;
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
CY=SDA;                                 /* 应答位返回值在CY中,0有效 */
SCL=0;
return(CY);
}
/***************
对IIC总线产生应答
***************/

void IICAck(void)
{
SDA=0;
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
_nop_();
SDA=1;
}

/*****************
不对IIC总线产生应答
*****************/
void IICNoAck(void)
{
SDA=1;
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
}

/*******************
   向IIC总线写数据
*******************/
void IICSendByte(unsigned char sendbyte)
{
unsigned char data j=8;
for(;j>0;j--)
{
SCL=0;
sendbyte<<=1;  /* 发送字节变量sendbyte左移1位,CY=sendbyte^7,并回存 */
SDA=CY;
SCL=1;
}
SCL=0;
}

/********************
从IIC总线读数据子程序
********************/
unsigned char IICReceiveByte(void)
{
register receivebyte,i=8;
SCL=0;
while(i--)
{
SCL=1;
receivebyte=(receivebyte<<1)|SDA;
SCL=0;
}
return(receivebyte);
}



/******按键接口描述********/
//左第一 二 三 四 个按键分别对应于 P2.7 P2.6 P2.5 P2.4 
//左第一个按键键值为1 
//左第二个按键键值为2 
//左第三个按键键值为3 
//左第四个按键键值为4
 
/******读取按键子程序 getkey()*************/
unsigned char getkey (void)
{    unsigned char k,tem,keytem;
     keytem=0;
     tem=P2 & 0xf0;			 //第一次读取按键值
     if(tem!=0xf0)			//判断有无按键按下
     {   
         for(k=0;k<20;k++)
         delay(250);		 //延时一段时间
         tem=P2 & 0xf0;		//再次读取按键值
         if(tem!=0xf0)
         {    if(tem==0x70) keytem=1;	       //表示左第一个按键按下
              else if(tem==0xb0) keytem=2;	   //表示左第二个按键按下
              else if(tem==0xd0) keytem=3;	   //表示左第三个按键按下
              else if(tem==0xe0) keytem=4;	   //表示左第四个按键按下
         }
      }
      
      while(tem!=0xf0) tem=P2 & 0xf0;  //等待按键释放 
      return(keytem);				   //返回按键值
}


/*****定时器初始化程序*******/
void Init_Timer (void)
{
    TMOD=0x21;
	TH0=(65536-1000)/256;
    TL0=(65536-1000)%256;
    TR0=1;
    ET0=1;
    EA=1;
} 

/*****定时器0中断服务程序******/
//显示处理,具体可以参考前面的实验
void timer0() interrupt 1 using 1
{
    TH0=(65536-1000)/256;
    TL0=(65536-1000)%256;
    number=number++;
    if(number>3) number=0;
    P2=digit[number];
    P0=tab[d[number]]; 
	//在第二个数码管显示时,将最高位的小数点显示出来,这里为冒号
    if(distime==1 && number==1)  
       P0=tab[d[number]]+0x80;  
 }
/*******主函数***********/
//效果:显示 分:秒
void main (void)
{
  /**EEPROM变量****/ 
 unsigned char *point_in,*point_out;  //定义输入输出指针
 unsigned char ii;
  
 unsigned char keyboard;         //键值变量
 unsigned char state=0;          //状态指示 =1设定定时状态  =0正常显示状态
 unsigned char i,distem,w=3;                //变量
 /*时钟处理以及定时器初始化*/
 year=07;month=03;day=0x04;hour=0x19;minute=0x16;second=13; //软件预设时间参数

 		
*point_in=year;
*(point_in+1)=month;
*(point_in+2)=day;
*(point_in+3)=hour;
*(point_in+4)=minute;		
*(point_in+5)=second;


ht1380_rest=0;ht1380_sclk=0;   //选中时钟芯片
 set_time();                    //设置时间
 Init_Timer();                  //初始化定时器及全局变量

Delay(50);                              /* 检查内部数据区0x30-0x39与0x40-0x49应完全相同 */                   
beep=1;
		*point_out=year;
		*(point_out+1)=month;
		*(point_out+2)=day;
		*(point_out+3)=hour;
		*(point_out+4)=minute+0x01;		
		*(point_out+5)=second;
		RW24XX(point_out,6,0x0010,0xa0,6);
while(1)
     {
	 	distime=~distime;  // 闪动冒号    
	 	read_time();      //读时间

		*point_in=year;
		*(point_in+1)=month;
		*(point_in+2)=day;
		*(point_in+3)=hour;
		*(point_in+4)=minute;		
		*(point_in+5)=second;
	    
		RW24XX(point_out,6,0x0010,0xa1,6);
		
		if((*point_in==*point_out) || (*point_in==*point_out)  || (*(point_in+1)==*(point_out+1))  || (*(point_in+2)==*(point_out+2))  || (*(point_in+3)==*(point_out+3))  || (*(point_in+4)==*(point_out+4))  || (*(point_in+5)==*(point_out+5)))
		{
		beep=0;
		}
	
		if(state==0)      //state=0 正常显示状态
        {
           read_time();
           d[0]=hour/16;
           d[1]=hour %16;
           d[2]=minute/16;
           d[3]=minute %16;
        }
	   
        else               //较时状态。让需要较时的位闪动
        {
           distem=d[w];
           d[w]=10;
           for(i=0;i<250;i++)
               delay(250);
           d[w]=distem;
           for(i=0;i<250;i++)
               delay(250);
        }
	 	
		keyboard=getkey(); //读按键
		
        if(keyboard==1)    // keyboard=1时,切换转态到较时并且多次..
        {   
			state=1;       // ..按键后会同时向后退到下一位
            w++;
            if(w>3) w=0; 
        }
        else if(keyboard==2)
        {   
			d[w]++;
            if(d[w]>9) d[w]=0;
        }
        else if(keyboard==3)
        {   
			if(d[w]>0) d[w]--; 
		}
        else if(keyboard==4)
        {    
			hour=d[0]*16+d[1];
            minute=d[2]*16+d[3];
            second=0;
			*point_out=year;
			*(point_out+1)=month;
			*(point_out+2)=day;
			*(point_out+3)=hour;
			*(point_out+4)=minute;		
			*(point_out+5)=second;
			RW24XX(point_out,6,0x0010,0xa0,6);
            state=0;
        }
		
     }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -