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

📄 at24c512.h

📁 基于ICCAVR平台的
💻 H
字号:
/*                                                                              
                              AT24C512驱动头文件:                              
								                                                
注:本头文件默认单片机频率为8M,I2C传输速率为400K,如果改变单片机频率,         
    需要将i2cdelay()函数  BIT率寄存器TWBR的值进行修改                           
								                                                
   AT24C512最大传输速率:1 MHz (5V), 400 kHz (2.7V), 100 kHz (1.8V)             
   AT24C512拥有128-byte的页面缓存空间                                           
   AT24C512读写安全时间间隔为5 ms                                               
                                                                                
   使用此头文件前,首先必须在main()函数中调用I2cinit()以初始化通信接口          
   发送:                                                                       
        1.选择需要写入的器件号icnumber,范围1--4,格式:icnumber=1;             
		  (AT24C512允许4片并行使用,空间可以扩展到512*4=1024 BIT位)             
		2.选择写入data首地址,范围0x0000--0xffff,格式:address=0x0000;         
		3.输入需要发送的字节数total,范围1--128,格式:total=12;                
注:前面3步可以直接调用                                                         
    i2control(char i2cicnumber,unsigned int i2caddress,char i2ctotal);          
		4.给发送缓存Send_buffer[]赋值,最多128个8位变量                         
		5.调用Send_i2c_data();函数来完成对data数据的发送                        
		                                                                        
   接收:                                                                       
        1.选择需要读取的器件号icnumber,范围1--4,格式:icnumber=1;             
		2.选择接收data首地址,范围0x0000--0xffff,格式:address=0x0000;          
		3.输入需要接收的字节数total,范围1--128,格式:total=12;                
注:前面3步可以直接调用                                                         
    i2control(char i2cicnumber,unsigned int i2caddress,char i2ctotal);          
		4.调用Read_i2c_data();函数来完成对data数据的接收,                       
		  接收数据将存入Receive_buffer[];                                       
		                                                                        
   编写:李科 2006-02-25                                                        
   修改:李科 2006-10-16                                                      */
   
/******************************定义变量区**************************************/
char  Send_buffer[128];     //(主控mcu/通信模块中设置的)发送缓冲区
char  Load_point=0;         //中断内,发送数据存储位置            
char  SendI2c_data=0;       //需要发送I2c数据                     
char  newpoint=0;           //已经发送个数标志位                  

char  Receive_buffer[128];  //(主控mcu/通信模块中设置的)接收缓冲区
char  Get_point=0;          //中断内,接收数据存储位置            
char  ReceiveI2c_data=0;    //接收到的I2c数据                     


char  Error_flag=0;         //出错标志位                          
char  icnumber=0;           //ic地址号码A1 A0                     
unsigned int address=0;     //数据储存地址                        
unsigned int laddress=0;    //数据储存地址低8位数据               
char  addresstime=0;        //地址高低位发送判断                  
char  total=0;              //需要发送接收的数据数量              
char  total1=0;             //第一次需要发送的数据数量            
char  total2=0;             //第二次需要发送的数据数量            
char  mt=1;                 //master 发送接收切换标志             

/******************************函数声明区**************************************/
void twi_isr(void);         //判断TWI状态子程序                   
void I2cinit(void);         //初始化I2C                           
void Send_i2c_data(void);   //I2C发送函数                         
void Read_i2c_data(void);   //I2C读取函数                         
void I2CReset(void);        //I2C复位函数                         
void i2cdelay(char x);      //延时间函数                          
void i2control(char i2cicnumber,unsigned int i2caddress,char i2ctotal);//变量赋值

/****************************I2c事件中断***************************************/
/*为进入主机模式,必须发送START信号。紧接着的地址包格式决定进入MT或MR模式
如果发送 SLA+W 进入MT 模式;如果发送SLA+R 则进入MR 模式。                
在MT模式下再次发送START信号,再发送SLA+R可以进入MR模式                 */
#pragma interrupt_handler twi_isr:18
void twi_isr(void)          //判断TWI状态子程序                          
{
  if((TWSR&0xf8)==0x08)     //读取TWI状态:START已发送                   
    { 	    
	 TWDR=(0b10100000+icnumber);//主机选择发送器件号码                   
	 TWCR=0X85;//启动发送(TWINT置位,TWI使能标志TWEN置位,中断允许TWIE置位)
	}
  else if((TWSR&0XF8)==0x10)//重复START信号发送,转换为主机接收模式      
    {
     TWDR=(0b10100001+icnumber); //主机向器件指定器件接收数据;          
	 TWCR=0X85;//启动发送(TWINT置位,TWI使能标志TWEN置位,中断允许TWIE置位)
    }
  else if((TWSR&0XF8)==0x18)//读取TWI状态:SLA+W 已发送;且接收到ACK     
    { 
	 newpoint=0;            //复位发送个数变量                           
	 Error_flag=0;          //错误标志清0                                
	 TWDR=(address>>8);     //发送起始地址高8位                          
	 addresstime=1;         //起始地址高8位已经发送,标志位置1           
	 TWCR=0X85;//启动发送(TWINT置位,TWI使能标志TWEN置位,中断允许TWIE置位)
	}
  else if(((TWSR&0XF8)==0x28)&&(addresstime==1))//接收到ACK,发送低8位地址
    {
	 TWDR=address;          //发送起始地址低8位                          
	 addresstime=0;         //起始地址低8位已经发送,标志位清0           
	 TWCR=0X85;//启动发送(TWINT置位,TWI使能标志TWEN置位,中断允许TWIE置位)
    }
  else if(((TWSR&0XF8)==0x28)&&(addresstime==0))//读取TWI状态:页地址已发送;接收到ACK;
    { 
	 if(mt==1)              //主机发送模式                               
	  {  
	    SendI2c_data=Send_buffer[Load_point];//载入数据                  
        TWDR=SendI2c_data;	//发送数据                                   
		if(newpoint<total)  //判断是否已经发送了total个数据              
		 {
		  newpoint++;       //发送个数变量自加1                          
		  Load_point++;     //储存空间位置自加1                          
		  TWCR=0X85; //启动发送(TWINT置位,TWI使能标志TWEN置位,中断允许TWIE置位)
		 } 
	    else  
		 {
		  Error_flag=0x28;  //发送结束标识                               
		  TWCR=0X95;//启动停止位发送(TWINT置1,TWSTO置1,TWI使能标志TWEN置1,中断允许TWIE置1)
		 }   
	  }
	 else if(mt==0)         //准备转换成主机接收模式:发送重复START信号  
	  {
	   TWCR=0XA5;//重复START信号发送(TWINT置位,START信号发送,TWI使能标志TWEN置位,中断允许TWIE置位)
	  }
	}
   else if((TWSR&0XF8)==0x38)//SLA+W 或数据的仲裁失败;释放总线          
    {	  
	 TWCR=0XA5;//TWINT置位,START信号发送,TWI使能标志TWEN置位,中断允许TWIE置位
	}
   else if((TWSR&0XF8)==0x40)//进入主机接收模式,清除start标志           
    {
	 Get_point=0;            //储存缓冲区指针归0                         
	 TWCR=0xc5;//进行应答(TWINT置1,应答允许,TWI使能标志TWEN置位,中断允许TWIE置位)
	}
   else if((TWSR&0XF8)==0x50)//主机接收模式接收数据                      
    {
	 Error_flag=0x00;
     ReceiveI2c_data=TWDR;   //赋值接收到的I2c数据                       
	 Receive_buffer[Get_point]=ReceiveI2c_data;//将收到的数据存入接收缓存区
	 Get_point++;            //储存空间位置自加1                         
	 if(Get_point<total)     //判断是否已经接收了total个数据             
	  {TWCR=0xc5;}//进行应答(TWINT置位,TWI使能应答,TWI使能标志TWEN置位,中断允许TWIE置位)
	 else                    //已经接收了total个数据                     
	  {
	   Get_point=0;          //储存缓冲区指针归0                         
	   Error_flag=0x50;
	   TWCR=0x00;//启动停止位发送(TWINT置0,TWSTO置0,TWI使能标志TWEN置0,中断允许TWIE置0) 
	  } 	 
	}
  else                       //错误处理。重新启动                        
    {
     Error_flag=0;           //置位错误标志                              
	 TWCR=0x00;              //清0                                       
    }
}

/*********************************初始化I2C************************************/
void I2cinit(void)
{   
 TWCR=0x00;
 TWBR=0x02;                  //设置BIT率400k (单片机晶振为8M)          
 TWSR=0x00;                  //设置分频1                                 
 TWAR=0x01;                  //允许识别TWI 总线广播(高7位为从机地址)     
 TWCR=0x45;            //TWI使能应答,TWI使能标志TWEN置位,中断允许TWIE置位
} 

/*****************************I2C变量赋值函数**********************************/
void i2control(char i2cicnumber,unsigned int i2caddress,char i2ctotal)
{
 icnumber=i2cicnumber;
 address=i2caddress;
 total=i2ctotal;
 laddress=((address<<8)>>8); //将低8位地址赋给laddress                   
}

/*******************************I2C发送函数************************************/
void Send_i2c_data(void)     //I2C发送函数1                              
{
 SEI();                      //允许中断                                  
 I2CReset();                 //i2c复位                                   
 Error_flag=0x00;
 Load_point=0;               //复位缓存地址	                             
 mt=1;                       //打开MCU发送标志                           
 icnumber--;                 //IC器件地址校正                            
 icnumber<<=1;               //IC器件地址校正                            
 if((laddress+total)>256)    //如果发送地址超过了256,则分2次发送        
  {
   total2=(laddress+total)-256;//计算第二次发送的数据个数                
   total1=total-total2;      //计算第一次发送的数据个数                  
   total=total1;             //准备第一次发送个数                        
   TWCR=0XA5;//开始发送(TWINT置位,start发送,TWI使能标志TWEN置位,中断允许TWIE置位)
   while(Error_flag!=0x28)   //等待发送完成                              
    {;}
   i2cdelay(30);             //200us X 30                                
   address+=total1;          //第二次发送首地址更新                      
   total=total2;             //准备第二次发送个数                        
   TWCR=0XA5;//开始发送(TWINT置位,start发送,TWI使能标志TWEN置位,中断允许TWIE置位)
   while(Error_flag!=0x28)   //等待发送完成                              
    {;}
   i2cdelay(30);             //200us X 30                                
  }
 else                        //如果发送地址没有超过256,则按照常规发送   
  {
   TWCR=0XA5;//开始发送(TWINT置位,start发送,TWI使能标志TWEN置位,中断允许TWIE置位)
   while(Error_flag!=0x28)   //等待发送完成                              
    {;}
   i2cdelay(30);             //200us X 30                                
  }
}

/*************************读取接收到的I2C数据**********************************/
void Read_i2c_data(void)
{
  SEI();                     //允许中断                                  
  I2CReset();                //i2c复位                                   
  Error_flag=0x00;     
  mt=0;                      //打开MCU接收标志                           
  icnumber--;                //IC器件地址校正                            
  icnumber<<=1;              //IC器件地址校正                            
  TWCR=0XA5;//开始发送(TWINT置位,start发送,TWI使能标志TWEN置位,中断允许TWIE置位)
  while(Error_flag!=0x50)    //等待接收完成                              
   {;}
  i2cdelay(30);
}

/*************************I2C软件延时函数**************************************/
void i2cdelay(char x)        //200us延时                                 
{
 char i=0,j=0;
 for(i=0;i<x;i++)
  {
   for(j=0;j<200;j++)
    {;}
  }
}

/******************************I2C复位函数*************************************/
void I2CReset(void)
{
  TWCR=0x45;        //TWI使能应答,TWI使能标志TWEN置位,中断允许TWIE置位 
}

⌨️ 快捷键说明

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