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

📄 i2c.c

📁 MPC8241:本程序是freescale的824*系列的BSP源程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    if ( ByteToXmit > 0 )
    {

	   if ( ByteToXmit == XmitByte )
	   {
	    /* no more data to send */	    
	    ByteToXmit = 0;
		
	    /* do not toggle I2CCR(MTX). Doing so will cause bus-hung
	     * since current Kahlua design does not give master a way
	     * to detect slave stop. It is always a good idea for
	     * master to use timer to prevent the long long delays
	     */

             return I2CBUFFEMPTY;		
	   }

#ifdef I2CDBG
	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_Slave_Rcv
 *
 * description: slave reads one byte data
 *              from master source
 *
 *              return I2CSUCCESS if no error otherwise non-zero
 * 
 * Note: condition must meet when this function is called:
 *       I2CSR(MIF) == 1 && I2CSR(MCF) == 1 &&
 *       I2CCR(MSTA) == 0 && I2CCR(MTX)  = 0
 * 
 ***********************************************/
static I2CStatus I2C_Slave_Rcv(unsigned int eumbbar )
{
	unsigned int val;
    I2C_CTRL ctrl;
    if ( ByteToRcv > 0 )
    {
	  val = load_runtime_reg( eumbbar, I2CDR );
	  *( RcvBuf + RcvByte ) = val & 0xff;
#ifdef I2CDBG
	printf( "%s(%d): rcv 0x%02x\n", __FILE__, __LINE__, *(RcvBuf + RcvByte) );
#endif	  
	  RcvByte++;

        if ( ByteToRcv == RcvByte )
        {
	      if ( RcvBufFulStop == 1 )
	      {
	        /* all done */
	        ctrl = I2C_Get_Ctrl( eumbbar );
	        ctrl.txak = 1;
	        I2C_Set_Ctrl( eumbbar, ctrl );
	      }

	      ByteToRcv = 0;
          return I2CBUFFFULL;		  
        }

	    return I2CSUCCESS;
    }

    return I2CBUFFFULL;
}

/****************** Device Control Function *************/

/*********************************************************
 * function: I2C_Init
 *
 * description: Initialize I2C unit with desired frequency divider,
 *              master's listening address, with interrupt enabled
 *              or disabled.
 *
 * note:
 ********************************************************/
static I2CStatus I2C_Init( unsigned int eumbbar,
		    unsigned char fdr,        /* frequency divider */ 
	            unsigned char slave_addr, /* driver's address used for receiving */
	 	    unsigned int en_int)     /* 1 - enable I2C interrupt 
			                      * 0 - disable I2C interrup 
				              */
{
I2C_CTRL ctrl;
unsigned int tmp;
#ifdef I2CDBG0
	printf( "%s(%d): I2C_Init enter\n", __FILE__, __LINE__);
#endif
	
    ctrl = I2C_Get_Ctrl( eumbbar );

    /* disable the I2C module before we change everything */
    ctrl.men = 0;
    I2C_Set_Ctrl( eumbbar, ctrl );

    /* set the frequency diver */
    tmp = load_runtime_reg( eumbbar, I2CFDR );
    tmp = ( tmp & 0xffffffc0 ) | ( fdr & 0x3f );
    store_runtime_reg( eumbbar, I2CFDR, tmp );

    /* Set our listening (slave) address */
    tmp = load_runtime_reg( eumbbar, I2CADR );
    tmp = ( tmp & 0xffffff01 ) | ( ( slave_addr & 0x7f) << 1 );
    store_runtime_reg( eumbbar, I2CADR, tmp );

    /* enable I2C with desired interrupt setting */
    ctrl.men = 1;
    ctrl.mien = en_int & 0x1;
    I2C_Set_Ctrl( eumbbar, ctrl );
#ifdef I2CDBG0
	printf( "%s(%d): I2C_Init exit\n", __FILE__, __LINE__ );
#endif
	
    return I2CSUCCESS;
    
}

/*****************************************
 * function I2c_Get_Stat
 *
 * description: Query I2C Status, i.e., read I2CSR
 *
 ****************************************/
static I2C_STAT I2C_Get_Stat( unsigned int eumbbar )
{
    unsigned int temp = load_runtime_reg( eumbbar, I2CSR );
 I2C_STAT stat;
#ifdef I2CDBG0
	printf( "%s(%d): get stat = 0x%08x\n", __FILE__, __LINE__, temp );
#endif	
	
   
    stat.rsrv0 = ( temp & 0xffffff00 ) >> 8;
    stat.mcf   = ( temp & 0x00000080 ) >> 7;
    stat.maas  = ( temp & 0x00000040 ) >> 6;
    stat.mbb   = ( temp & 0x00000020 ) >> 5;
    stat.mal   = ( temp & 0x00000010 ) >> 4;
    stat.rsrv1 = ( temp & 0x00000008 ) >> 3;
    stat.srw   = ( temp & 0x00000004 ) >> 2;
    stat.mif   = ( temp & 0x00000002 ) >> 1;
    stat.rxak  = ( temp & 0x00000001 );
    return stat;
}

/*********************************************
 * function: I2c_Set_Ctrl
 *
 * description: Change I2C Control bits,
 *              i.e., write to I2CCR
 *
 ********************************************/
static void I2C_Set_Ctrl( unsigned int eumbbar, I2C_CTRL ctrl ) /* new control value */
{
    unsigned int temp = load_runtime_reg( eumbbar, I2CCR );
    temp &= 0xffffff03;
    temp |= ( ( ctrl.men  & 0x1 ) << 7 );
    temp |= ( ( ctrl.mien & 0x1 ) << 6 );
    temp |= ( ( ctrl.msta & 0x1 ) << 5 );
    temp |= ( ( ctrl.mtx  & 0x1 ) << 4 );
    temp |= ( ( ctrl.txak & 0x1 ) << 3 );
    temp |= ( ( ctrl.rsta & 0x1 ) << 2 );
#ifdef I2CDBG0
	printf( "%s(%d): set ctrl = 0x%08x\n", __FILE__, __LINE__, temp );
#endif	
    store_runtime_reg( eumbbar, I2CCR, temp );

}

/*****************************************
 * function: I2C_Get_Ctrl
 *
 * description: Query I2C Control bits,
 *              i.e., read I2CCR
 *****************************************/
static I2C_CTRL I2C_Get_Ctrl( unsigned int eumbbar )
{
    union {
        I2C_CTRL ctrl ;
        unsigned int temp;
    } s;
    s.temp = load_runtime_reg( eumbbar, I2CCR );
#ifdef I2CDBG0
    printf( "%s(%d): get ctrl = 0x%08x\n", __FILE__, __LINE__, s.temp );
#endif

    return s.ctrl;
}


/****************************************
 * function: I2C_Slave_Addr
 *
 * description: Process slave address phase.
 *              return I2CSUCCESS if no error
 *
 * note: Precondition for calling this function:
 *       I2CSR(MIF) == 1 &&
 *       I2CSR(MAAS) == 1
 ****************************************/
static I2CStatus I2C_Slave_Addr( unsigned int eumbbar )
{
    I2C_STAT stat = I2C_Get_Stat( eumbbar );
    I2C_CTRL ctrl = I2C_Get_Ctrl( eumbbar );
    
    if ( stat.srw == 1 )
    {
	   /* we are asked to xmit */
	   ctrl.mtx = 1;
	   I2C_Set_Ctrl( eumbbar, ctrl );    /* set MTX */
	   return I2C_Slave_Xmit( eumbbar );
    }

   /* we are asked to receive data */
   ctrl.mtx = 0;
   I2C_Set_Ctrl(eumbbar, ctrl );
   (void)load_runtime_reg( eumbbar, I2CDR ); /* do a fake read to start */

    return I2CADDRESS;
}

/***********************************************
 * function: I2C_ISR
 *
 * description: I2C Interrupt service routine
 *
 * note: Precondition:
 *      I2CSR(MIF) == 1
 **********************************************/
static I2CStatus I2C_ISR( unsigned int eumbbar )
{
I2C_STAT stat = I2C_Get_Stat( eumbbar );
I2C_CTRL ctrl = I2C_Get_Ctrl( eumbbar );
#ifdef I2CDBG0
	printf( "%s(%d): I2C_ISR\n", __FILE__, __LINE__ );
#endif
	
   
    /* clear MIF */
    stat.mif = 0;

    /* Now let see what kind of event this is */    
    if ( stat.mcf == 1 )
    {
	/* transfer compete */

	/* clear the MIF bit */
	I2C_Set_Stat( eumbbar, stat );

	if ( ctrl.msta == 1 )
	{
	    /* master */
	    if ( ctrl.mtx == 1 )
	    {
			/* check if this is the address phase for master receive */
            if ( MasterRcvAddress == 1 )
			{
				/* Yes, it is the address phase of master receive */
                ctrl.mtx = 0;
                /* now check how much we want to receive */
                if ( ByteToRcv == 1 && RcvBufFulStop == 1 )
                {
                    ctrl.txak = 1;
                }
				
                I2C_Set_Ctrl( eumbbar, ctrl );
               (void)load_runtime_reg( eumbbar, I2CDR );  /* fake read first */

				MasterRcvAddress = 0;
				return I2CADDRESS;
				
			}

            /* master xmit */		
            if ( stat.rxak == 0 )
            {
		          /* slave has acknowledged */
		          return I2C_Master_Xmit( eumbbar );
            }

            /* slave has not acknowledged yet, generate a STOP */
            if ( XmitBufEmptyStop == 1 )
            {
                   ctrl.msta = 0;
                   I2C_Set_Ctrl( eumbbar, ctrl );
			}
			
            return I2CSUCCESS;
	    }
	    
	    /* master receive */
	    return I2C_Master_Rcv( eumbbar );
	}

	/* slave */
	if ( ctrl.mtx == 1 )
	{
	    /* slave xmit */
	    if ( stat.rxak == 0 )
	    {
		/* master has acknowledged */
		return I2C_Slave_Xmit( eumbbar );
	    }

	    /* master has not acknowledged, wait for STOP */
	    /* do nothing for preventing bus from hung */
	    return I2CSUCCESS;
	}

	/* slave rcv */
	return I2C_Slave_Rcv( eumbbar );
	
    }
    else if ( stat.maas == 1 )
    {
	/* received a call from master */
	
	/* clear the MIF bit */
	I2C_Set_Stat(eumbbar, stat );
	
    /* master is calling us, process the address phase */
	return I2C_Slave_Addr( eumbbar );
    }
    else
    {
       /* has to be arbitration lost */
       stat.mal = 0;
       I2C_Set_Stat( eumbbar, stat );

       ctrl.msta = 0; /* return to receive mode */
       I2C_Set_Ctrl( eumbbar, ctrl );
    }

    return I2CSUCCESS;

}

/******************************************************
 * function: I2C_Set_Stat
 *
 * description: modify the I2CSR
 *
 *****************************************************/
static void I2C_Set_Stat( unsigned int eumbbar, I2C_STAT stat )
{
    union {
      unsigned int val;
      I2C_STAT stat;
    } s_tmp;
    union {
      unsigned int val;
      I2C_STAT stat;
    } s;
    s.val = load_runtime_reg( eumbbar, I2CSR );
    s.val &= 0xffffff08;
    s_tmp.stat = stat;
    s.val |= (s_tmp.val & 0xf7);

#ifdef I2CDBG0
    printf( "%s(%d): set stat = 0x%08x\n", __FILE__, __LINE__, s.val );
#endif	
	
    store_runtime_reg( eumbbar, I2CSR, s.val );
    
}
void delay( int deciseconds )		
{
	int	j,k;

	k = 0xfffff;

	for (j = 0; j < deciseconds; j++) {
		while (k) {					
			k = k-1;				
		}							
	}
}

void I2cRead (unsigned char addr)
{
	unsigned int rc;
	rc = I2C_do_transaction(0,I2C_MASTER_RCV,addr,0,256,READ_BUFFER,I2C_NO_STOP,0,I2C_NO_RESTART);
	
}
void I2cWrite (unsigned char addr)
{
	unsigned int rc,i;
	for(i=0;i<256;i++)WRITE_BUFFER[i]=i;
	
		
	rc = I2C_do_transaction(0,I2C_MASTER_XMIT,addr,0,256,WRITE_BUFFER,I2C_NO_STOP,0,I2C_NO_RESTART);
	
}
unsigned int I2cInit (void)
{
unsigned int rc;
rc = I2C_Initialize(0,0,0);
if(rc)
return 1;
else
return 0; 	
}

⌨️ 快捷键说明

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