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

📄 i2cdrv.c

📁 powerpc下I2C驱动,支持tornado2.2
💻 C
字号:
/******************************************************************************************************
  I2C driver using I/O port 
******************************************************************************************************/
#include <vxworks.h>
#include <semLib.h>
#if (CPU == PPC860 )
#include "m852reg.h"
#include "m852mask.h"
#else
#include "m8260reg.h"
#include "m8260mask.h"
#endif

#include "base.h"
#include "I2CDrv.h"


#if( HARDWARE_VERSION ==2 )
    #define SDA_PORT_DAT PADAT
    #define SCL_PORT_DAT PADAT
    #define SDA_PORT_DIR PADIR    
#else                                        //8channel
    #define SDA_PORT_DAT M8260_PDDAT         
    #define SCL_PORT_DAT M8260_PDDAT
    #define SDA_PORT_DIR M8260_PDDIR
#endif



void  I2C_stop      (  void    ) ;
void  I2C_start     (  void    ) ;
int   I2C_send_byte ( U8  dat  ) ;
void  I2C_read_byte ( U8 *dat  , int flag ) ;
void  I2C_set_dir   ( int flag ) ;


LOCAL   SEM_ID   I2C_mutex = NULL ;              /*I2C总线互斥访问信号量*/



/*************************************************************************************
*   Function : I2C_start
*Description : start the I2C transfer
*              
*/
void  I2C_start ( void ) 
{
    U32 immBase = vxImmrGet();	

    /*I2C start condition , SDA falling edge with SCL high level*/

    *SDA_PORT_DAT( immBase )  |=  I2C_SDA_PIN ;
    *SCL_PORT_DAT( immBase )  |=  I2C_SCL_PIN ;
    software_delay( 100 ) ;
    *SDA_PORT_DAT( immBase )  &=  ~I2C_SDA_PIN ;    	
    software_delay( 100 ) ;
    
    *SCL_PORT_DAT( immBase )  &=  ~I2C_SCL_PIN ;   
    software_delay( 200 ) ;  	
}

/*************************************************************************************
*   Function : I2C_start
*Description : stop the I2C transfer
*              
*/
void  I2C_stop  ( void ) 
{
    U32 immBase = vxImmrGet();
    
    /*Set SDA pin be output type*/
    I2C_set_dir( SDA_OUTPUT ) ;	
        
    /*I2C stop condition , SDA rising edge with SCL high level*/	

    *SDA_PORT_DAT( immBase ) &=  ~I2C_SDA_PIN ;
    *SCL_PORT_DAT( immBase ) |=   I2C_SCL_PIN ;
    software_delay(200);
    *SDA_PORT_DAT( immBase ) |=   I2C_SDA_PIN ;
    software_delay( 200 ) ; 

}


/*************************************************************************************
*   Function : I2C_send_byte
*Description : sent one byte using I2C timing 
*              > 0 success , < 0 fail            
*/
int  I2C_send_byte ( U8  dat  ) 
{
	U32 immBase = vxImmrGet();
	int i ;
	
	/*set pin type be output*/
	I2C_set_dir( SDA_OUTPUT ) ;
	
	/*clear SDA line*/
   
	*SDA_PORT_DAT(immBase) &=  ~I2C_SDA_PIN ;

	software_delay( 200 ) ;
	/*loop to send out the 8 bit*/
	for( i = 0 ; i < 8 ; i++ )
	{                       
        /*NOTE: I2C using rising egde send bit and falling edge to read bit*/         
   
		*SCL_PORT_DAT( immBase ) &=   ~I2C_SCL_PIN ;	

		software_delay(200);

 
		if( dat & ( 0x80 >> i ) )
		    *SDA_PORT_DAT( immBase ) |=   I2C_SDA_PIN ;
		else
		    *SDA_PORT_DAT( immBase ) &=  ~I2C_SDA_PIN ;
                software_delay( 200 );
								
		*SCL_PORT_DAT( immBase ) |=  I2C_SCL_PIN ;

		software_delay(400);				
	}
	
			
  
	*SCL_PORT_DAT( immBase ) &=   ~I2C_SCL_PIN ;            

                    
    /*Now we should read the slave ack*/	
	I2C_set_dir( SDA_INPUT ) ;	    
    software_delay(200);
                    			    

	*SCL_PORT_DAT( immBase ) |=  I2C_SCL_PIN ;	    
	software_delay(200);	
	
	i = *SDA_PORT_DAT( immBase ) & I2C_SDA_PIN ;
	
	*SCL_PORT_DAT( immBase ) &=  ~I2C_SCL_PIN ;		

	software_delay(200);
    
	if( ~i != 0 )          /*We get the ack*/
	    return 1 ;
	
	/*non ack get , return error*/    
	return -1 ; 

}

/*************************************************************************************
*   Function : I2C_read_byte
*Description : read the one byte from I2C
*              
*/
void  I2C_read_byte ( U8 *dat  , int flag ) 
{
	U32 immBase = vxImmrGet();
	int i , ret ;
	U8  tep ;
		
	
    I2C_set_dir( SDA_INPUT ) ;
	
	tep = 0 ;
	for( i = 0 ; i < 8 ; i++ )
	{

	    *SCL_PORT_DAT( immBase ) |=    I2C_SCL_PIN ;	
		software_delay(400);

		if(( *SDA_PORT_DAT( immBase ) & I2C_SDA_PIN ) ==  I2C_SDA_PIN )
		    tep |= 0x80 >> i ;	

	    *SCL_PORT_DAT( immBase ) &=   ~I2C_SCL_PIN ;	
		software_delay(200);		    		

	}
	
	
	    		
	I2C_set_dir( SDA_OUTPUT ) ;
	if( flag )

	    *SDA_PORT_DAT( immBase ) &=  ~I2C_SDA_PIN ;      /*more byte , not end*/

	    
	else

	    *SDA_PORT_DAT( immBase ) |=   I2C_SDA_PIN ;      /*last byte , end read*/

	
	/*Now we should send ack*/
        software_delay( 200 );
    *SCL_PORT_DAT( immBase )     |=   I2C_SCL_PIN ;	
	software_delay(200);		    
	    
    *SCL_PORT_DAT( immBase )     &=   ~I2C_SCL_PIN ;	
	software_delay(200);		

	*dat = tep ;
}

/*************************************************************************************
*   Function : I2C_set_dir
*Description : change the SDA pin direction 
*              1   output   ;  0  input
*/
void  I2C_set_dir( int flag ) 
{
	U32 immBase = vxImmrGet();	

	if( flag )
	    *SDA_PORT_DIR(immBase)  |=   I2C_SDA_PIN  ; 	
	else
	    *SDA_PORT_DIR(immBase)  &=  ~I2C_SDA_PIN  ; 	
}

/*************************************************************************************
*   Function : I2C_init
*Description : init the I2C driver , config the pin as IO   
*              create mutex semphone
*/
int  I2C_init ()
{
		
    U32 immBase = vxImmrGet();	

    if( I2C_mutex != NULL )
        return ERROR ;
        
    I2C_mutex   = semBCreate ( SEM_Q_FIFO  , SEM_FULL   ) ;
    if( I2C_mutex == NULL )
        return ERROR ;
#if ( HARDWARE_VERSION == 2 )
    *PAODR(immBase)  &= ~( I2C_SDA_PIN | I2C_SCL_PIN ); 
    *PAPAR(immBase)  &= ~( I2C_SDA_PIN | I2C_SCL_PIN ) ;
    /*first config all is output pin*/
    *PADIR(immBase)  |=  ( I2C_SDA_PIN | I2C_SCL_PIN ) ; 
    
    /*Pull to high */
    *PADAT(immBase)  |=  I2C_SCL_PIN | I2C_SDA_PIN ;
#else    
    *M8260_PDODR(immBase)  &= ~( I2C_SDA_PIN | I2C_SCL_PIN ); 
    *M8260_PDPAR(immBase)  &= ~( I2C_SDA_PIN | I2C_SCL_PIN ) ;
    /*first config all is output pin*/
    *M8260_PDDIR(immBase)  |=  ( I2C_SDA_PIN | I2C_SCL_PIN ) ; 
    
    /*Pull to high */
    *M8260_PDDAT(immBase)  |=  I2C_SCL_PIN | I2C_SDA_PIN ;
#endif
    return OK ;

}

/*************************************************************************************
*   Function : I2C_send
*Description : send the data according to the length
*/
int I2C_send ( U8 slave_addr , U8  sub_addr , U16 uLen , U8 *data )
{
	int i , ret ;
	
	if( I2C_mutex == NULL )
	    return ERROR ;
	
	semTake( I2C_mutex , WAIT_FOREVER ) ;  
	    
	I2C_start( );
	
	/*1. send the chip address*/
	slave_addr &= I2C_WRITE ;
	ret = I2C_send_byte( slave_addr ) ;    
	if( ret < 0 ) 
	{
		semGive( I2C_mutex ) ;
		I2C_stop( );
		return -1 ; /*No address ACK*/
	}
	
	/*2. send the chip sub address*/
	ret = I2C_send_byte( sub_addr ) ;
	if( ret < 0 )
	{
		semGive( I2C_mutex ) ;
		I2C_stop( );
		return -2 ; /*No sub address ack*/
	}
	
	/*Loop to send the all the data*/
	for( i = 0 ; i < uLen ; i++ )
	{
		ret = I2C_send_byte( data[i] ) ;
		if( ret < 0 )
		{
			semGive( I2C_mutex ) ;
			I2C_stop( ) ;
			return -3   ;  /*No data ack*/
		}
	}
	
	/*all send out , stop I2C*/
	semGive( I2C_mutex ) ;
	I2C_stop( ) ;
	return uLen ;
}

/*************************************************************************************
*   Function : I2C_read
*Description : read in data
*/
int I2C_read ( U8 slave_addr , U8  sub_addr , U16 uLen , U8 *data )
{
	int i , ret ;
	
	if( I2C_mutex == NULL )
	    return ERROR ;	
	    
	semTake( I2C_mutex , WAIT_FOREVER ) ;

	I2C_start( );
	
	/*1. send the chip address*/
	slave_addr &= I2C_WRITE ;
	ret = I2C_send_byte( slave_addr ) ;    
	if( ret < 0 ) 
	{
		semGive( I2C_mutex ) ;
		I2C_stop( );
		return -1 ; /*No address ACK*/
	}
	
	/*2. send the chip sub address*/
	ret = I2C_send_byte( sub_addr ) ;
	if( ret < 0 )
	{
		semGive( I2C_mutex ) ;
		I2C_stop( );
		return -2 ; /*No sub address ack*/
	}
	
	I2C_stop ( );
	software_delay( 200 ) ;
	
	
	/*3. really to read byte in*/    
	I2C_start( );	
	slave_addr |= I2C_READ  ;	
	ret = I2C_send_byte( slave_addr ) ;	
	if( ret < 0 ) 
	{
		semGive( I2C_mutex ) ;
		I2C_stop( );
		return -4  ;
	}
	
	for( i = 0 ; i < uLen ; i++ )
	{
		if( i < ( uLen - 1 ) )
		    I2C_read_byte( &data[i]  , 1 ) ;  /*should ack*/
		else
		    I2C_read_byte( &data[i]  , 0 ) ;  /*last byte , no ack*/
	}
	
	semGive( I2C_mutex ) ;
	I2C_stop( );
	return uLen ;
}

⌨️ 快捷键说明

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