iic_driver.c

来自「M16C瑞萨平台」· C语言 代码 · 共 484 行

C
484
字号
/******************     I2C device driver   ******************************************* 
;;;                   Author: Gong Liang, @EIS LAB, Lulea University of Technology, Sweden
;;;                   Date	: 09/NOV/'2007 (FRI)
;;;                   Object File Name : i2cbus 
;;;                   MCU Type	: M60 62a or 62p   
;;; According to the Table 17.11 Registers to Be Used and Settings in I2C Mode (1)
;;;      on the datasheet of M30626HPGP page 222 to 223 to set registers!
;;; Using UART2 for IIC bus control, the MCU  works under IIC master conditions 
******************************************************************************************/
 
#include "hardware.h"

// #include "intrins.h"
#define  uchar unsigned char  /*宏定义*/
#define  uint  unsigned int



// Defines needed by this module
#define XIN_FREQ 10000000
#define I2C_BIT_RATE 100000

#define TRUE 1
#define FALSE 0

#define ACKRELEASE 0x0100
#define ACKHOLD 0x0000
#define I2CISRLEVEL 1
#define READ 0
#define WRITE 1


#define SDA2 P7.BIT.P7_0
#define SCL2 P7.BIT.P7_1


int ACK_IS_SET;
int ACK;

void  AckI2C_MstAck(int);

/************  SDA2 SCL2 ---- GPIO Test  ***********
  PD7.BIT.PD7_0 = OUTPUT;		     
  PD7.BIT.PD7_1 = OUTPUT;		   
  while(1){
P7.BIT.P7_0 = HIGH;idle();P7.BIT.P7_0 = LOW;	idle();
P7.BIT.P7_1 = HIGH;idle();P7.BIT.P7_1 = LOW;	idle();	
	};
//*****************************************/


  


//--------------------------------------------------------------------------------------
// Name:		i2c_start
// Parameters:	None
// Returns:	None
// Description: Generates the start condition in the i2c line
//--------------------------------------------------------------------------------------

 
 void i2c_start(void)
{		
	 PD7.BIT.PD7_0 = OUTPUT;	// Reset SDA2 as Output Mode
  	 
	 SDA2 = HIGH;
	 SCL2 = LOW;// Put it at the first row ...
	 idle();
	 SCL2 = HIGH;
	 idle();
	 SDA2 = LOW;
	 idle();
	 SCL2 = LOW;				   
} 

//--------------------------------------------------------------------------------------
// Name:		i2c_stop
// Parameters:	None
// Returns:	None
// Description: Generates the stop condition in the i2c line
//--------------------------------------------------------------------------------------

 
void i2c_stop(void)
{		
	 PD7.BIT.PD7_0 = OUTPUT;	// Reset SDA2 as Output Mode
	 
     SCL2 = LOW;
	 idle();
  	 SDA2 = LOW;
	 idle();
	 SCL2 = HIGH;
	 idle();
	 SDA2 = HIGH;
	 idle();
	 SCL2 = LOW;			   
} 

//--------------------------------------------------------------------------------------
// Name:		SendByte(uchar c)
// Parameters:	uchar c
// Returns:  	None
// Description: Send the data( or address) C  and wait for acknowledge after finishing 
//              sending it. Nonacknowledge sets ACK=0 and normal sending sets  ACK=1.
// Notice:      ACK=0 indicates the slave device may be broken. 
//--------------------------------------------------------------------------------------

void  SendByte(uchar c)
{
  PD7.BIT.PD7_0 = OUTPUT;	// Reset SDA2 as Output Mode	
  uchar BitCnt;  
 
  for(BitCnt=0;BitCnt<8;BitCnt++)  /*Byte length 8*/
  { 
     SCL2 = LOW; 
     if((c<<BitCnt)&0x80) SDA2 = HIGH;   /* MSB sending logic*/
     else  SDA2 = LOW; 
	 transition();  /* Use this function to adjust the baut rate of I2C bus*/              
     
	 SCL2 = HIGH;       /* Set SCL2 high to inform slave of receiving sth.*/
     transition();      /* Greater than 4μs*/        
     SCL2 = LOW;  
  }
  
//Slave ACK, use ack or nack alternatively   
//  transition(); // SCL2 holds low state at the 9th clock pulse 

  SDA2 = HIGH;  // Release SDA2 for ACK after sending 8 bits  
  transition();
  
  SCL2 = HIGH;
  transition(); 
  SCL2 = LOW;
  
// ...Check the ACK from the receiver....  
    
//  if(SDA2==1){ACK=0;} /* ACK received?*/    
//  else  ACK= 1;
        
//  SCL2 = LOW;
//  transition(); 

} //End of SendByte(uchar c)


 
//******************************************************************************************************
// Name:		TxNByte(uchar Ad_slave,uchar Ad_sub,uchar *DataBuf,uchar ByteNum)
// Parameters:	Ad_slave -- The address of slave device;
//              Ad_sub -- The address of slave device registers;
//              *DataBuf -- The pointer to the data memory;
//              ByteNum -- The number of bytes for transmission;
// Returns:  	None
// Description: Send multiple bytes to the slave.  
//******************************************************************************************************

 
void  TxNByte(uchar Ad_slave,uchar Ad_sub,uchar *DataBuf,uchar ByteNum){
	
	PD7.BIT.PD7_0 = OUTPUT;	// Reset SDA2 as Output Mode
	
    uchar i;
	
    i2c_start();
	
    SendByte(Ad_slave);
    SendByte(Ad_sub);
 
    for(i=0;i<ByteNum;i++){
		SendByte(*DataBuf);
        DataBuf++;
	}// Data transmission FOR loop
	 
    i2c_stop();
}
//******************************************************************************************************** 



 
//********************************************************************************************************
// Name:		uchar  RcvByte(void)
// Parameters:	None
// Returns:  	The Char being received
// Description:  
//********************************************************************************************************

uchar  RcvByte()
{
  PD7.BIT.PD7_0 = INPUT;	// Set SDA2 Input Mode
   
  uchar RetChar;
  uchar BitCnt;
  RetChar = 0;          //Initially set to 0.
  
  SCL2 = LOW; 
//  transition(); 
    
  for(BitCnt=0;BitCnt<8;BitCnt++)
  {        
	 transition();  
     SCL2 = HIGH;       /* Validate the RevData on the SDA2 line  */
     transition();
     RetChar<<=1;       /* Push each received bit toward MSB  */
     if(SDA2 ==1) RetChar+=1; /* Read the bit on SDA2 line*/
     SCL2 = LOW;
  }
  
//  PD7.BIT.PD7_0 = OUTPUT;	// Reset SDA2 as Output Mode
//  AckI2C_MstAck(TRUE);   //True master ACK.
  
  return(RetChar);
  
  
}

 









 
 
 
//********************************************************************************************************
// Name:		void AckI2C_MstAck(int MstAck)
// Parameters:	MstAck= TRUE or FALSE
// Returns:  	None
// Description: Mater sends the ACK (LowLevel) or NACK(HoldHigh), working as a master-receiver. 
//              If master ack is needed, use the parameter TRUE. Or FALSE if not.
//********************************************************************************************************
 

void AckI2C_MstAck(int MstAck){
	
	PD7.BIT.PD7_0 = OUTPUT;	// Set SDA2 Output Mode
	
    SCL2 = LOW;
    if(MstAck == TRUE) SDA2 = LOW; //Master Ack
    else SDA2 = HIGH;              //Master Nack 
    transition();
	
    SCL2 = HIGH;
    transition(); 
    SCL2 = LOW;
	
	PD7.BIT.PD7_0 = INPUT;	// Set SDA2 Input Mode
}
//*************************************************
 
 
 
 
 
 
//******************************************************************************************************
// Name:		RV8564ByteWrite(uchar Ad_RV8564RW,uchar Ad_Reg,uchar RegContent)
// Parameters:	Ad_RV8564RW -- The address of RV8564;
//              Ad_Reg-- The address of RV8564 registers;
//              RegContent -- The content written to the register;
// Returns:  	None
// Description: Write one specific RV8564 register.  
//******************************************************************************************************

 
void  RV8564ByteWrite(uchar Ad_RV8564RW,uchar Ad_Reg,uchar RegContent){
  
	
    i2c_start();
	
    SendByte(Ad_RV8564RW);
	idle();
    SendByte(Ad_Reg);
	idle();
	SendByte(RegContent);
	idle();
	
 
	 
    i2c_stop();
}
//******************************************************************************************************** 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
// File Local struct that contains data flow information
static struct{
    unsigned char SlaveAddrMsgOne;      /* Slave address to sent/receive message */
    unsigned char NumOfBytesMsgOne;     /* Number of bytes in message buffer */
    unsigned char SlaveAddrMsgTwo;      /* Slave address to sent/receive message */
    unsigned char NumOfBytesMsgTwo;     /* Number of bytes in message buffer */
    unsigned char MsgFormat;            /* What is the transfer format of the data */
    unsigned char NumOfMsg;             /* Total number of messages (used for combined format) */
    unsigned char Bytes2Send;           /* number of bytes to send in current message */
    unsigned char * MsgPtr;             /* pointer to current message */
    unsigned char RdWrFlg : 1;          /* '0' is a Read, '1' is a Write */
    unsigned char Undefined : 2;        /* Extras in case I need them for now */
    unsigned char * MsgBufOne;          /* Pointer for R/W buffer one from passed struct */
    unsigned char * MsgBufTwo;          /* Pointer for R/W buffer two from passed struct */
}I2CLocalStatus;
 
// Other misc. variables needed (GLOBAL)
struct{
    unsigned char I2CBusBusy : 1;       /* I2C Bus is busy */
    unsigned char FailedArb : 1;        /* Bus arbitration failed */
    unsigned char SlaveNack : 1;        /* Slave NACK'd a xmited data byte */
    unsigned char Undefined : 3;
    unsigned char I2CMsgComplete : 1;   /* Message completed sucessfully */
}I2CGlobalStatus;
 
typedef struct{
    unsigned char SlaveAddrMsgOne;      /* Slave address to sent/receive message */
    unsigned char NumOfBytesMsgOne;     /* Number of bytes in message buffer */
    unsigned char SlaveAddrMsgTwo;      /* Slave address to sent/receive message */
    unsigned char NumOfBytesMsgTwo;     /* Number of bytes in message buffer */
    unsigned char MsgFormat;            /* What is the transfer format of the data */
    unsigned char * MsgBufOne;          /* Pointer for R/W buffer one from passed struct */
    unsigned char * MsgBufTwo;          /* Pointer for R/W buffer two from passed struct */
}I2CMessageSetup;

 
 
 
//--------------------------------------------------------------------------------------
/***************************************************************************************/
// Name:		i2c_init                                                                 -------------------------!
// Parameters:	None
// Returns:	None
// Description: This routine configures UART2 as i2c
/***************************************************************************************/
//--------------------------------------------------------------------------------------

void i2c_init(void)
{
	asm("fclr i");
	
   	PD7.BIT.PD7_1 = OUTPUT;// SCL2 input port
	PD7.BIT.PD7_0 = OUTPUT;// SDA2 input port	
	
	U2SMR.BYTE=0x01;//IICM=1 mode
	U2MR.BYTE=0x00;// SMD2 to SMD0 bits in the UiMR register = 000b (Serial interface disabled). 
	            	//set the initial state for the SDA2 -------------------------!
// 	P7.BIT.P7_1 = HIGH;// SCL2 level
// 	P7.BIT.P7_0 = HIGH;// SDA2 level
//
  
	U2BRG= 0xFF;
	U2MR.BYTE=0x02;// SMD2-SMD0“010b”I2C MODE,  CKDIR “0” master internal clock,IOPOL“0”  no conversion-------------------------
	
	U2C0.BYTE=0x92;//Uartform:msb,transmission/receiption at SCL falling/rising edge,SDA2 SCL2 n channel, f32
	U2C1.BYTE=0x05;// enable reception and transmission
	UCON.BYTE=0x00;//reset to 0. 
	
	U2SMR.BYTE=0x07;//IIC mode, BBS“0” STOP condition detected , arbitration lost by byte
	
	U2SMR2.BYTE=0x00;//clock delayed, clock out cmos, with no data delay
	U2SMR3.BYTE=0x02;//if IICM2=0(ACKint),CKPH=1, then the initial and ultimate values for CLK2 are LOW -------------------------Modified!
	U2SMR4.BYTE=0x00;//clock delayed, clock out cmos, with no data delay
	  
    IFSR2A.BIT.IFSR26=1;// UART0 bus confliction detection
    IFSR2A.BIT.IFSR27=1;// UART1 bus confliction detection
  
//    U2SMR2.BIT.CSC=1;/* Clock-synchronous bit enable */
//    idle();
//    U2SMR2.BIT.SWC2=1;//
//    idle(); idle();
//    U2SMR2.BIT.SWC2=0;//*/

  
	 
	S2TIC.BYTE=0x04;	 
    S2RIC.BYTE=0x04;	 //Set IIC_IPL=4; 
    BCNIC.BYTE=0x04;// 0x04;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,!!!modified!!!!!
	// ABT_U2RB
 

	asm("fset i");
 
}
 

//--------------------------------------------------------------------------------------
// 	ROM constants declaration - values declaration
//--------------------------------------------------------------------------------------
 

	

  
void i2c_restart(void)
{		
  	U2SMR4.BYTE=0x02;// Start condition generate
 	idle();
    U2SMR4.BYTE=0x0a;// STSP output enable
 	idle();	
 	 			   
} 
 

 
 
//--------------------------------------------------------------------------------------
// Name:		i2c_enable_rx
// Parameters:	None
// Returns:	None
// Description: Enables the transmission of uart2
//--------------------------------------------------------------------------------------
void i2c_enable_rx(void)
{	
	U2C1.BIT.TE_U2C1 = 1;// TE set 1 to start	 
//	U2C1.BYTE=U2C1.BYTE|0x05;// RE set 1 to receive enable	
} 

void i2c_disable_rx(void)
{	
	U2C1.BYTE=U2C1.BYTE&0xfe;// TE set 1 to start	 
	U2C1.BYTE=U2C1.BYTE|0x05;// RE set 1 to receive enable	
} 

void I2C_WAIT_UNTIL_FINISHED(void)

{
	//while(U2SMR.BIT.BBS);//IF bus busy,loop //wrong...	while (U2SMR.BIT.BBS == 1); 
//	The bus is considered to be busy after the START
//   condition. The bus is considered to be free again a certain
//  time after the STOP condition. no stop, no free
	
//    while(!U2C0.BIT.TXEPT);//Transmit end, U2C0.BIT.TXEPT=1, !U2C0.BIT.TXEPT=0
	                       //if transmission not end, U2C0.BIT.TXEPT=0, !U2C0.BIT.TXEPT=1,loop to wait
//    while(!U2C1.BIT.TI_U2C1);   // wait for tx buffer to be empty	
 

     while(!ACK_IS_SET);
	 while(ACK);// Ack is 0 if it is ACK inter.
     ACK_IS_SET=0;
	 
	 
//	 U2SMR2.BIT.SWC2= 1; //Set SCL output to low
// 	idle();
// 	U2SMR2.BIT.SWC2= 0; //SWC2 :1; /* SCL wait output bit 2   
	
//	idle();	
 
}
 	

	



⌨️ 快捷键说明

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