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

📄 i2c.c

📁 MPC8241:本程序是freescale的824*系列的BSP源程序
💻 C
📖 第 1 页 / 共 3 页
字号:
 * note: this is master receive API
 **********************************************************/
static I2CStatus I2C_get( unsigned int eumbbar,
		   unsigned char rcv_from,    /* sender's address */
		   unsigned char *buffer_ptr, /* pointer of receiving buffer */
		   unsigned int  length,      /* length of the receiving buffer */
		   unsigned int  stop_flag,   /* 1 - signal STOP when buffer is full
			                       * 0 - no STOP signal when buffer is full 
				               */
		   unsigned int is_cnt )      /* 1 - this is a restart, don't check MBB
					       * 0 - this is a new start, check MBB
                                               */
{
    if ( buffer_ptr == 0 || length == 0 )
    {
      return I2CERROR;
    }
	
#ifdef I2CDBG0
	printf( "%s(%d): I2C_get\n", __FILE__, __LINE__ );
#endif

    RcvByte = 0;
    ByteToRcv = length;
    RcvBuf = buffer_ptr;
    RcvBufFulStop = stop_flag;
	
    XmitByte = 0;
    ByteToXmit = 0;
    XmitBuf = 0;
	
    /* we are the master, start the transaction */
    return I2C_Start( eumbbar, rcv_from, RCV, is_cnt );

}

#if 0 /* turn off dead code */
/*********************************************************
 * function: I2C_write
 *
 * description:
 * Send a buffer of data to the requiring master. 
 * If stop_flag is set, after the whole buffer is sent,
 * generate a STOP signal provided that the requiring 
 * receiver doesn't signal the STOP in the middle.
 * I2C is the slave performing transmitting.
 *
 * Note: this is slave xmit API.
 *
 *       due to the current Kahlua design, slave transmitter
 *       shall not signal STOP since there is no way
 *       for master to detect it, causing I2C bus hung.
 *
 *       For the above reason, the stop_flag is always
 *       set, i.e., 0.
 *
 *       programmer shall use the timer on Kahlua to 
 *       control the interval of data byte at the 
 *       master side.
 *******************************************************/
static I2CStatus I2C_write( unsigned int eumbbar,
		     unsigned char *buffer_ptr, /* pointer of data to be sent */
		     unsigned int  length,      /* number of byte of in the buffer */
		     unsigned int  stop_flag )  /* 1 - signal STOP when buffer is empty
			                         * 0 - no STOP signal when buffer is empty
				                 */
{
    if ( buffer_ptr == 0 || length == 0 )
    {
      return I2CERROR;
    }

    XmitByte = 0;
    ByteToXmit = length;
    XmitBuf = buffer_ptr;
    XmitBufEmptyStop = 0; /* in order to avoid bus hung, ignored the user's stop_flag */

    RcvByte = 0;
    ByteToRcv = 0;
    RcvBuf = 0;
	
    /* we are the slave, just wait for being called, or pull */
    /* I2C_Timer_Event( eumbbar ); */
}

/******************************************************
 * function: I2C_read
 *
 * description:
 * Receive a buffer of data from the sending master.
 * If stop_flag is set, when the buffer is full and the 
 * sender does not signal STOP, generate a STOP signal.
 * I2C is the slave performing receiving.
 *
 * note: this is slave receive API
 ****************************************************/
static I2CStatus I2C_read(unsigned int eumbbar,
                   unsigned char *buffer_ptr, /* pointer of receiving buffer */
		   unsigned int  length,      /* length of the receiving buffer */
		   unsigned int  stop_flag )  /* 1 - signal STOP when buffer is full
			                       * 0 - no STOP signal when buffer is full 
			 		       */
{
    if ( buffer_ptr == 0 || length == 0 )
    {
      return I2CERROR;
    }

    RcvByte = 0;
    ByteToRcv = length;
    RcvBuf = buffer_ptr;
    RcvBufFulStop = stop_flag;

    XmitByte = 0;
    ByteToXmit = 0;
    XmitBuf = 0;
	
    /* wait for master to call us, or poll */
    /* I2C_Timer_Event( eumbbar ); */
}
#endif /* turn off dead code */

/*********************************************************
 * function: I2c_Timer_Event
 *
 * description:
 * if interrupt is not used, this is the timer event handler.
 * After each fixed time interval, this function can be called
 * to check the I2C status and call appropriate function to
 * handle the status event.
 ********************************************************/
static I2CStatus I2C_Timer_Event( unsigned int eumbbar, I2CStatus (*handler)( unsigned int ) )
{
 I2C_STAT stat;
#ifdef I2CDBG0
	printf( "%s(%d): I2C_Timer_Event\n", __FILE__, __LINE__ );
#endif
	
    stat = I2C_Get_Stat( eumbbar );

    if ( stat.mif == 1 )
    {
       if ( handler == 0 )
       {
	   return I2C_ISR( eumbbar );
       }
       else
       {
	   return (*handler)( eumbbar );
       }
    }

	else if (stat.rxak == 1) {
/*		printf("tick\n");*/
		delay( 50 );

/* {
	int x;
		for (x = 1000; x > 0; x--)
			;
   }*/
		if (--GlobalTimer <= 0)
			return( I2CRCVERROR );
	}

    return I2CNOEVENT;
}


/****************** Device I/O function *****************/

/******************************************************
 * function: I2C_Start
 *
 * description: Generate a START signal in the desired mode.
 *              I2C is the master.
 *
 *              Return I2CSUCCESS if no error.
 *
 * note:
 ****************************************************/
static I2CStatus I2C_Start( unsigned int  eumbbar,
                     unsigned char slave_addr, /* address of the receiver */ 
	                 I2C_MODE      mode,       /* XMIT(1) - put (write)
			                                    * RCV(0)  - get (read)
					                            */
		             unsigned int is_cnt )    /* 1 - this is a restart, don't check MBB
					                           * 0 - this is a new start
					                           */
{

unsigned int tmp = 0;
 I2C_STAT stat;
 I2C_CTRL ctrl;

#ifdef I2CDBG0
	printf( "%s(%d): I2C_Start addr 0x%x mode %d cnt %d\n", __FILE__,  __LINE__ ,
      slave_addr,mode,is_cnt);
#endif

   
     ctrl = I2C_Get_Ctrl( eumbbar );

    /* first make sure I2C has been initialized */
    if ( ctrl.men == 0 )
    {
	   return I2CERROR;
    }

    /* next make sure bus is idle */
    stat = I2C_Get_Stat( eumbbar );
	
    if ( is_cnt == 0 && stat.mbb == 1 )
    {
	   /* sorry, we lost */
	   return I2CBUSBUSY;
    }
    else if ( is_cnt == 1 && stat.mif == 1 && stat.mal == 0 )
    {
	/* sorry, we lost the bus */
        return I2CALOSS;
    }
	     

    /* OK, I2C is enabled and we have the bus */

    /* prepare to write the slave address */
    ctrl.msta = 1;
    ctrl.mtx  = 1;
    ctrl.txak = 0;	
    ctrl.rsta = is_cnt;   /* set the repeat start bit */
    I2C_Set_Ctrl( eumbbar, ctrl );
	
    /* write the slave address and xmit/rcv mode bit */
    tmp = load_runtime_reg( eumbbar, I2CDR );
    tmp = ( tmp & 0xffffff00 ) | ((slave_addr & 0x007f)<<1) | ( mode == XMIT ? 0x0 : 0x1 );
    store_runtime_reg( eumbbar, I2CDR, tmp );

	if ( mode == RCV )
	{
		MasterRcvAddress = 1;
	}
	else
	{
		MasterRcvAddress = 0;
	}
	
#ifdef I2CDBG0
	printf( "%s(%d): I2C_Start exit\n", __FILE__, __LINE__ );
#endif
	
    /* wait for the interrupt or poll  */
    return I2CSUCCESS;
}

/***********************************************************
 * function: I2c_Stop
 *
 * description: Generate a STOP signal to terminate the master
 *              transaction.
 *              return I2CSUCCESS
 *
 **********************************************************/
static I2CStatus I2C_Stop( unsigned int eumbbar )
{
 I2C_CTRL ctrl;
#ifdef I2CDBG0
	printf( "%s(%d): I2C_Stop enter\n", __FILE__, __LINE__ );
#endif
	
    ctrl = I2C_Get_Ctrl(eumbbar );
    ctrl.msta = 0;
    I2C_Set_Ctrl( eumbbar, ctrl );

#ifdef I2CDBG0
	printf( "%s(%d): I2C_Stop exit\n", __FILE__, __LINE__ );
#endif
	
    return I2CSUCCESS;
}

/****************************************************
 * function: I2C_Master_Xmit
 *
 * description: Master sends one byte of data to 
 *              slave target
 * 
 *              return I2CSUCCESS if the byte transmitted.
 *              Otherwise no-zero
 *
 * Note: condition must meet when this function is called:
 *       I2CSR(MIF) == 1 && I2CSR(MCF)  == 1  && I2CSR(RXAK) == 0
 *       I2CCR(MSTA) == 1  && I2CCR(MTX) == 1
 *
 ***************************************************/ 
static I2CStatus I2C_Master_Xmit( unsigned int eumbbar )
{
	unsigned int val;
    if ( ByteToXmit > 0 )
    {

      if ( ByteToXmit == XmitByte )
      {
	     /* all xmitted */
	     ByteToXmit = 0;

	     if ( XmitBufEmptyStop == 1 )
	     {
	       I2C_Stop( eumbbar );
	     }

             return I2CBUFFEMPTY;

      }

#ifdef I2CDBG0
	printf( "%s(%d): xmit 0x%02x\n", __FILE__, __LINE__, *(XmitBuf + XmitByte) );
#endif
	  
       val = *(XmitBuf + XmitByte);
       val &= 0x000000ff;
       store_runtime_reg( eumbbar, I2CDR, val );
       XmitByte++;
       
       return I2CSUCCESS;
    	
    }

    return I2CBUFFEMPTY;
}

/***********************************************
 * function: I2C_Master_Rcv
 *
 * description: master reads one byte data
 *              from slave source
 *
 *              return I2CSUCCESS if no error
 * 
 * Note: condition must meet when this function is called:
 *       I2CSR(MIF) == 1 && I2CSR(MCF) == 1 &&
 *       I2CCR(MSTA) == 1 && I2CCR(MTX) == 0
 * 
 ***********************************************/
static I2CStatus I2C_Master_Rcv( unsigned int eumbbar )
{
	I2C_CTRL ctrl;
	unsigned int val;
    if ( ByteToRcv > 0 )
    {

      if ( ByteToRcv - RcvByte == 2 && RcvBufFulStop == 1 )
      {
	    /* master requests more than or equal to 2 bytes
	     * we are reading 2nd to last byte
	     */
	
        /* we need to set I2CCR(TXAK) to generate a STOP */
          ctrl = I2C_Get_Ctrl( eumbbar );
	      ctrl.txak = 1;
	      I2C_Set_Ctrl( eumbbar, ctrl );
		  
                            /* Kahlua will automatically generate a STOP
			                 * next time a transaction happens
			                 */

	    /* note: the case of master requesting one byte is
	     *       handled in I2C_ISR
	     */
      }
	
	  /* generat a STOP before reading the last byte */
	  if ( RcvByte + 1 == ByteToRcv && RcvBufFulStop == 1 )
	  {
		  I2C_Stop( eumbbar );
	  }

      val = load_runtime_reg( eumbbar, I2CDR );
      *(RcvBuf + RcvByte) = val & 0xFF;

#ifdef I2CDBG0
	printf( "%s(%d): rcv 0x%02x\n", __FILE__, __LINE__, *(RcvBuf + RcvByte) );
#endif
      
      RcvByte++;

	  if ( ByteToRcv == RcvByte )
      {
	    ByteToRcv = 0;

        return I2CBUFFFULL;		
      }
	  
      return I2CSUCCESS;
   }
      
   return I2CBUFFFULL;
   
}

/****************************************************
 * function: I2C_Slave_Xmit
 *
 * description: Slave sends one byte of data to 
 *              requesting destination
 * 
 *        return SUCCESS if the byte transmitted. Otherwise
 *        No-zero
 *
 * Note: condition must meet when this function is called:
 *       I2CSR(MIF) == 1 && I2CSR(MCF) == 1 &&  I2CSR(RXAK) = 0
 *       I2CCR(MSTA) == 0  && I2CCR(MTX) == 1
 *
 ***************************************************/
static I2CStatus I2C_Slave_Xmit( unsigned int eumbbar )
{
    unsigned int val;	

⌨️ 快捷键说明

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