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

📄 i2c_hard.c

📁 i2c硬件通信例程
💻 C
字号:

			   
//-----头文件-----//
#include <reg922.h>	
//#include <stdio.h>
//#include <intrins.h>

//SI  I2C中断标志。  当进入25种可能的I2C状态中的任何一个后,该位置位。
//    当EA, EI2C(IEN1.0)以及SI置位时,产生一个中断请求。SI必须通过软件清零。
#define uchar unsigned char
#define GENERATE_STOP        0x54     // 置位 STO, 复位 STA 、SI         
#define RELEASE_BUS_ACK      0x44     // 复位 STO,STA,SI 并置位 AA (ack) 
#define RELEASE_BUS_NOACK    0x40     // 复位 STO,STA,SI 并置位 AA (noack) 
#define RELEASE_BUS_STA      0x64     // 起动总线/重新起动总线, 置位 STA   

bit GetBus(void);
bit AckBus(void)  reentrant;
//bit SendByte(uchar data);
//bit ISendStr(uchar sla, uchar suba, uchar *str, uchar str_len);
//bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no);
bit ISendStr(uchar SLA, uchar *SUBA, uchar *DATA_I2C, uchar *DATA_LEN);
bit Write_EEPROM(uchar data_add,uchar *EEPROM,uchar data_len);
bit Read_EEPROM (uchar data_add,uchar *EEPROM,uchar data_len);
extern uchar idata SUBA[2],DATA_I2C[11],DATA_LEN[2],EEPROM[6];//SLA,

//-----申请总线-----//
//功能:进行I2C总线的初始化--包括时钟选择,I2C使能,发送起始信号
//      等等。I2EN为1,设置为主机;CRSEL位为0,使用内部SCL发生器。
      
bit GetBus(void)
{ 
	I2SCLH = 15;				// 设置SCL高电平的PCLK周期数 				    
    I2SCLL = 15;                // 设置SCL低电平的PCLK周期数,6MHz时为100Kbit/S 
    I2CON  = RELEASE_BUS_STA;   // 申请成为主机,起动总线。使用内部SCL发生器,I2EN和AA置位。       	
    //while( SI==0 );        	// 等待起始位的发送                           
	return(AckBus());
}


//-----应答函数-----//
bit AckBus(void)  reentrant
  {
	uchar TimeOut;
	TimeOut = 0xFF;
	while(SI==0)
       {        
         TimeOut--; 
         if( TimeOut==0x00 )                  //100uS无响应,超时退出
               {
               		I2CON = GENERATE_STOP;
                    return(0);
               }
       }
         return(1);
   }


//-----发送数据函数-----//
//功能:用于向总线发送数据 
//入口参数:ACC  待发送的数据                   
 
bit SendByte(uchar ACC)	
 { 
	I2DAT = ACC;
    I2CON = RELEASE_BUS_ACK;                   // 清除SI位等等   
    //while( SI==0 );                          // 等待数据的发送 
    return(AckBus());
 }
   

//-----向有子地址器件发送多字节数据函数-----//                 
// 功能:     从启动总线到发送地址,子地址,数据,结束总线的全过程
// 入口参数: SLA	    从器件地址
//           *SUBA      子地址
//           *DATA_I2C  发送内容的指针
//           *DATA_LEN  发送字节数
// 出口参数: 返回1表示操作成功,否则操作有误。

bit ISendStr(uchar SLA,uchar *SUBA, uchar *DATA_I2C, uchar *DATA_LEN)  //
 { 
	uchar i;

	if( GetBus()==0 )	        return(0); 	   // 启动总线 
                                      	 
    if(SendByte(SLA)==0)	    return(0);     // 发送器件地址 
                        	
	if( I2STAT!=0X18 )
    { 
	   I2CON = GENERATE_STOP;
       return(0);
    }
    for(i=0; i<(*DATA_LEN); i++)
    {
	 
	 if(SendByte(*SUBA)==0)	     return(0);    // 发送器件子地址 		
     
	 if( I2STAT!=0X28 )
     {  I2CON = GENERATE_STOP;
        return(0);
     }
     SUBA++;
    }
     DATA_LEN++;
  
  
	for(i=0; i<(*DATA_LEN); i++)
  { 
  	if(SendByte(*DATA_I2C)==0)	 return(0);     //发送数据					
    
	if( I2STAT!=0X28 )
	{ I2CON = GENERATE_STOP;
	  return(0);
	}
    DATA_I2C++;
  } 

	I2CON = GENERATE_STOP;            // 结束总线				 
    return(1);
}


//-----向有子地址器件读取多字节数据函数-----//                
//功能:    从启动总线到发送地址,子地址,读数据,结束总线的全过程
//入口参数:SLA 		从器件地址
//          *SUBA		子地址
//		    *DATA_I2C	读出的内容存储区的指针
//          *DATA_LEN   读*DATA_LEN个字节。
//出口参数:函数返回1表示操作成功,否则操作有误。

bit IRcvStr(uchar *SUBA,uchar *DATA_I2C,uchar *DATA_LEN )	//uchar SLA,
{ 
	uchar i;
    uchar CheckSum=0;
	
	if(GetBus()==0)             return(0);	    // 启动总线
	if(SendByte(0xA0)==0)       return(0);	    // 发送器件地址              							
                 					
    if( I2STAT!=0X18)
    {  
	    I2CON = GENERATE_STOP;
        return(0);
    }
    
	for(i=0; i<(*DATA_LEN); i++)
    {
	
	if(SendByte(*SUBA)==0)      return(0);	    // 发送器件子地址				
    
	if( I2STAT!=0X28 )
    { 
	    I2CON = GENERATE_STOP;
        return(0);
    }
	SUBA++;
	}
    DATA_LEN++;
	
	I2CON = RELEASE_BUS_STA;      // 重新启动总线					
    //while( SI==0 ); 
	
	if(AckBus()==0)				return(0);  	
	if(SendByte(0xA1)==0)       return(0);	   // 发送器件读地址
    
	if( I2STAT!=0X40 )
    { 
	    I2CON = GENERATE_STOP;
        return(0);
    } 
   
    for(i=0; i<*DATA_LEN-1; i++)
    { 
		I2CON = RELEASE_BUS_ACK;                 // 接收一字节数据并发送应答位	
    	//while( SI==0 );                        // 等待接收数据					 
    	if(AckBus()==0)	            return(0);
		if( I2STAT!=0X50 )
		{ 
	    	I2CON = GENERATE_STOP;
	    	return(0);
		}
    	*DATA_I2C = I2DAT;             // 读取数据						
    	CheckSum+=*DATA_I2C;		   //算出校验码
		DATA_I2C++;
    } 
    I2CON = RELEASE_BUS_NOACK;     // 接收最后一字节数据并发送非应答位
    //while( SI==0 );  
    
	if(AckBus()==0)             return(0);
	
	*DATA_I2C = I2DAT;			   //接收最后一字节数据
    
	//CheckSum+=*DATA_I2C;		   //已经是校验码不能加了
	
	I2CON = GENERATE_STOP;         // 结束总线						
    if(*DATA_I2C==CheckSum)     return(1);	//验证校验码
	else  return(0);
}							 


bit Write_EEPROM(uchar data_add,uchar *EEPROM,uchar data_len)
  {
   //uchar SLA;
   //SLA=0xA0;
   SUBA[0]=data_add;
   //SUBA[1]=data_add;
   DATA_LEN[0]=1;
   DATA_LEN[1]=data_len; 	    
   if(ISendStr(0xA0,SUBA, EEPROM, DATA_LEN)) return (1);
   else return (0);
  }			   

bit Read_EEPROM(uchar data_add, uchar *EEPROM,uchar data_len)
  {
   //uchar SLA;
   //SLA=0xA0;
   SUBA[0]=data_add;
   DATA_LEN[0]=1;
   DATA_LEN[1]=data_len; 	    
   if(IRcvStr(SUBA, EEPROM, DATA_LEN)) return (1);	//0xA0,
   else return (0);
  }	
		 





⌨️ 快捷键说明

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