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

📄 i2c.c

📁 自己编写的用普通IO口模拟实现的IIC协议
💻 C
字号:

//IO口模拟IIC实现代码

void Sda_Output(void)
{
 PFR61_I2CE0 = 0;  
 PFR6_A20E = 0;   

 DDR6_D64 = 1;
 PCR6_P64 = 1;
 
}

//----------------------------------------------------------------------
//----------------------------------------------------------------------

void Sda_Input(void)
{
 PFR61_I2CE0 = 0;  
 PFR6_A20E = 0;   

 DDR6_D64 = 0;
 PCR6_P64 = 1;
}

//----------------------------------------------------------------------
//----------------------------------------------------------------------

void Scl_Output(void)
{
 PFR61_I2CE0 = 0;  
 PFR6_A21E = 0;   

 DDR6_D65 = 1;
 PCR6_P65 = 1;
}

//----------------------------------------------------------------------
//----------------------------------------------------------------------

void Scl_Input(void)
{
 PFR61_I2CE0 = 0;  
 PFR6_A21E = 0;   

 DDR6_D65 = 0;
 PCR6_P65 = 1;
}

//----------------------------------------------------------------------
//----------------------------------------------------------------------

void Sda_High(void)
{
 PDR6_P64 = 1;	
}

//----------------------------------------------------------------------
//----------------------------------------------------------------------

void Sda_Low(void)
{
 PDR6_P64 = 0;
}

//----------------------------------------------------------------------
//----------------------------------------------------------------------

void Scl_High(void)
{
  PDR6_P65 = 1;		
}

//----------------------------------------------------------------------
//----------------------------------------------------------------------

void Scl_Low(void)
{
  PDR6_P65 = 0;
}

//----------------------------------------------------------------------
//----------------------------------------------------------------------

int Get_Sda_Val(void)
{
if(PDR6_P64)	
	return(1);
else
	return(0);
}

//----------------------------------------------------------------------
//----------------------------------------------------------------------

void _Nop(void) //~= 1us
{
 volatile int i;
  for(i=0;i<40;i++);
}

void I2c_Wait(void)
{
  _Nop();    /*起始条件建立时间大于4.7us,延时*/
  _Nop();
  _Nop();
  _Nop();
  _Nop();
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
/*******************************************************************
                     起动总线函数               
函数原型: void  Start_I2c();  
功能:       启动I2C总线,即发送I2C起始条件.
  
********************************************************************/
void Start_I2c()
{
  Sda_High();   /*发送起始条件的数据信号*/
  
  I2c_Wait();

  Scl_High();
  
  I2c_Wait();
  I2c_Wait();

  Sda_Low();   /*发送起始信号*/
  
  I2c_Wait();
  I2c_Wait();
  
  Scl_Low();   /*钳住I2C总线,准备发送或接收数据 */
 
  I2c_Wait();
  I2c_Wait();
}


/*******************************************************************
                      结束总线函数               
函数原型: void  Stop_I2c();  
功能:       结束I2C总线,即发送I2C结束条件.
  
********************************************************************/
void Stop_I2c()
{
  Sda_Low();  /*发送结束条件的数据信号*/
  
  I2c_Wait();
  I2c_Wait();

  Scl_High();  /*结束条件建立时间大于4μs*/
  
  I2c_Wait();
  I2c_Wait();
  
  Sda_High();  /*发送I2C总线结束信号*/
  
  I2c_Wait();
  I2c_Wait();
 }


/*******************************************************************
                 字节数据传送函数               
函数原型: void  SendByte(unsigned char c);
功能:  将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
     此状态位进行操作.(不应答或非应答都使ack=0 假)     
     发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
********************************************************************/
void  SendByte(unsigned char c)
{
 unsigned char BitCnt;
 
 for(BitCnt=0;BitCnt<8;BitCnt++)  /*要传送的数据长度为8位*/
    {
       
	if((c<<BitCnt)&0x80)Sda_High();   /*判断发送位*/
    else  Sda_Low();                
      
     I2c_Wait();
     I2c_Wait();
      
     Scl_High();               /*置时钟线为高,通知被控器开始接收数据位*/
     
     I2c_Wait();
     I2c_Wait();

	 Scl_Low(); 
    }
    
      I2c_Wait();
    //lxh 5-16   I2c_Wait();
     
	  Sda_High();               /*8位发送完后释放数据线,准备接收应答位*/
	
     I2c_Wait();
   //lxh 5-16  I2c_Wait();

	 Sda_Input(); //add by lxh for test

  I2c_Wait();

     Scl_High();

  I2c_Wait();
  I2c_Wait();
    	 
 if(Get_Sda_Val()) ack=0;     
 else ack=1;        /*判断是否接收到应答信号*/
    Scl_Low();
 
  I2c_Wait();
  I2c_Wait();

 Sda_Output();
}






/*******************************************************************
                 字节数据传送函数               
函数原型: unsigned char  RcvByte();
功能:  用来接收从器件传来的数据,并判断总线错误(不发应答信号),
     发完后请用应答函数。  
********************************************************************/	
unsigned char  RcvByte()
{
  unsigned char retc;
  unsigned char BitCnt;
  
  retc=0; 
  Sda_High();             /*置数据线为输入方式*/
 
  I2c_Wait();
  
  Sda_Input();

  I2c_Wait();
  
  for(BitCnt=0;BitCnt<8;BitCnt++)
      {
                 
        Scl_Low();       /*置时钟线为低,准备接收数据位*/
        
		I2c_Wait();
        I2c_Wait();

        Scl_High();       /*置时钟线为高使数据线上数据有效*/
        
		I2c_Wait();
        I2c_Wait();

		
		retc=retc<<1;
        if(Get_Sda_Val()) retc=retc+1; /*读数据位,接收的数据位放入retc中 */
        I2c_Wait();
       }
 
  Scl_Low();
  
  I2c_Wait();
  
  Sda_Output();
 
  I2c_Wait();
  I2c_Wait();

  return(retc);
}



/********************************************************************
                     应答子函数
原型:  void Ack_I2c(unsigned char ack);
 
功能:主控器进行应答信号,(可以是应答或非应答信号)
********************************************************************/
void Ack_I2c(unsigned char ack)
{
  
  if(ack == 0) Sda_Low();     /*在此发出应答或非应答信号 */
  else Sda_High();
  
  I2c_Wait();
  I2c_Wait();
  
  Scl_High();
    
  I2c_Wait();
  I2c_Wait();
  
  Scl_Low();                /*清时钟线,钳住I2C总线以便继续接收*/
   
  I2c_Wait();
}


//------------------------------------------------------------------------
//------------------------------------------------------------------------
//GPB10 --dat   GPB9 ---clk
void I2c_Init()
 {
   
    Sda_Output();
    Scl_Output();                //
  
}      

//------------------------------------------------------------------------
//------------------------------------------------------------------------

unsigned char dr_vIIC_ReadByte(unsigned int slvAddr,unsigned int addr,unsigned char *data)
{
   
   Start_I2c();                /*启动总线*/

   SendByte(slvAddr);           /*发送器件地址*/
   if(ack==0)
   {
    Stop_I2c();                  /*结束总线*/ 
 //   RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----1\n")));
     return(0);
   }
   I2c_Wait();
   I2c_Wait();

   SendByte(addr);
   if(ack==0)
   {
    Stop_I2c();                  /*结束总线*/ 
   // RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----2\n")));
    return(0);
   }
   I2c_Wait();

   Start_I2c(); 
    
   I2c_Wait();
   I2c_Wait();

   SendByte(slvAddr+1);
   if(ack==0)
   {
    Stop_I2c();                  /*结束总线*/ 
 //   RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----3\n")));
    return(0);
   }
  
   I2c_Wait();
   I2c_Wait();

   *data=RcvByte();               /*读取数据*/
     Ack_I2c(1);               /*发送非就答位*/
   
  I2c_Wait();
  I2c_Wait();
	 
    Stop_I2c();                  /*结束总线*/ 
     
   return(1); 
}

//------------------------------------------------------------------------
unsigned char dr_ucIIC_ReadSingleByte(unsigned int slvAddr,unsigned char *data)
{
   
   Start_I2c();                /*启动总线*/
   
   SendByte(slvAddr+1);
   if(ack==0)
   {
    Stop_I2c();                  /*结束总线*/ 
 //   RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----3\n")));
    return(0);
   }
  
   I2c_Wait();
   I2c_Wait();

   *data=RcvByte();               /*读取数据*/
     Ack_I2c(1);               /*发送非就答位*/
   
  I2c_Wait();
  I2c_Wait();
	 
    Stop_I2c();                  /*结束总线*/ 
     
   return(1); 
}

//------------------------------------------------------------------------
unsigned char dr_ucIIC_ReadDoubleByte(unsigned int slvAddr,unsigned char *data)
{
   
   Start_I2c();                /*启动总线*/
    
   SendByte(slvAddr+1);
   if(ack==0)
   {
    Stop_I2c();                  /*结束总线*/ 
 //   RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----3\n")));
    return(0);
   }
  
   I2c_Wait();
   I2c_Wait();

   *data=RcvByte();               /*读取数据*/
     Ack_I2c(0);               /*发送非就答位*/
  
  data++;
   
  I2c_Wait();
  I2c_Wait();
	 
	 *data=RcvByte();               /*读取数据*/
     Ack_I2c(1);               /*发送非就答位*/
	 
	I2c_Wait();
  I2c_Wait();
  
    Stop_I2c();                  /*结束总线*/ 
     
   return(1); 
}






//------------------------------------------------------------------------
unsigned char dr_vIIC_WriteByte(unsigned char slvAddr,unsigned int addr,unsigned char data)
{
 

   Start_I2c();    /*启动总线*/

   SendByte(slvAddr);            /*发送器件地址*/
   if(ack==0)
  {
    Stop_I2c();                  /*结束总线*/ 
 //   RETAILMSG(1,(TEXT("GpioI2c: Wd24C080----1\n")));
    return(0);
   }
   
   I2c_Wait();
   I2c_Wait();

   SendByte(addr);               /*发送数据*/
   if(ack==0)
   {
    Stop_I2c();                  /*结束总线*/ 
 //   RETAILMSG(1,(TEXT("GpioI2c: Wd24C080----2\n")));
     return(0);
   }
   
   I2c_Wait();
   I2c_Wait();

   SendByte(data);               /*发送数据*/
   if(ack==0)
   {
    Stop_I2c();                  /*结束总线*/ 
//    RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----3\n")));
    return(0);
   }

   I2c_Wait();
   I2c_Wait();

   Stop_I2c();                 /*结束总线*/ 
  

   return(1);
}

//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------

unsigned char dr_ucIIC_WriteByte(unsigned char *slvAddr,unsigned char *data)
{
   Start_I2c();    /*启动总线*/

   SendByte(*slvAddr);            /*发送器件地址*/
   if(ack==0)
  {
    Stop_I2c();                  /*结束总线*/ 
 //   RETAILMSG(1,(TEXT("GpioI2c: Wd24C080----1\n")));
    return(0);
   }
   
   I2c_Wait();
   I2c_Wait();
  
  
   SendByte(*data);               /*发送数据*/
   if(ack==0)
   {
    Stop_I2c();                  /*结束总线*/ 
//    RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----3\n")));
    return(0);
   }
  
   I2c_Wait();
   I2c_Wait();
  
   data++;
  
   SendByte(*data);               /*发送数据*/
   if(ack==0)
   {
    Stop_I2c();                  /*结束总线*/ 
//    RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----3\n")));
    return(0);
   }
   
   data++;
  
   SendByte(*data);               /*发送数据*/
   if(ack==0)
   {
    Stop_I2c();                  /*结束总线*/ 
//    RETAILMSG(1,(TEXT("GpioI2c: Rd24C080----3\n")));
    return(0);
   }
  
   I2c_Wait();
   I2c_Wait();
  
   Stop_I2c();                 /*结束总线*/ 
  

   return(1);
}

//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------



void Delay_ms(int delay)   
 {
  unsigned int val = 0x03AA;
	  
  TMCSR0 = 0;            /* Stop timer and clear interrupts */
  TMRLR0 = val;       /* Reload value */					
  TMCSR0_CSL1 = 1;       /* Clock: 00=R/2 01=R/8 10=R/32   */
  TMCSR0_CSL0 = 0;       
  TMCSR0_RELD = 1;       /* 1 = reload timer; 0 = one shot timer */
  TMCSR0_INTE = 0;       /* 1 = Interrupt enable */
  TMCSR0_UF   = 0;       /* clear underflow (UF) interrupt bit */
  TMCSR0_CNTE = 1;       /* 1 = timer enable - wait for trigger */
  TMCSR0_TRG  = 1;       /* Trigger : Go ! */	
 
  
  while(delay--) 
	{
		while(TMR0 >= val>>1);
		while(TMR0 <  val>>1);
	}
  
  TMCSR0_CNTE = 0;  	
 	TMCSR0 = 0;
 	
 }

⌨️ 快捷键说明

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