/* ------------------------------------------------------------------- Name: I2C_RxData - Purpose: To do I2C parallel serial conversion for reception. Passed: None. Returns: Notes: ------------------------------------------------------------------- */ UB8 I2C_RxData (void) { UB8 bResult; UB8 bMask; bResult = 0x00; /* Clear value */ // Release SDA //I2C_SET_SDA(HIGH); BIT1216M_I2C_SDA_HIGH; /* MSB is read first */ for (bMask = 0x80; bMask; bMask >>= 1) { //I2C_SET_SCL(HIGH); BIT1216M_I2C_SCL_HIGH; I2C_Delay(I2C_HIGH); //if ( I2C_GET_SDA ) if (BIT1216M_I2C_SDA_DETECT) bResult |= bMask; //I2C_SET_SCL(LOW); BIT1216M_I2C_SCL_LOW; I2C_Delay(I2C_LOW); // Added by JC 06:31PM 2011/01/12 } /* for */ return( bResult ); } /* I2C_RxData */
unsigned char I2C_Tx(unsigned char data) // Does this comply exactly with I2C?? { unsigned char x; static unsigned char ACK; for ( x=8 ; x>0 ; x-- ) { if (data & 0x80) SDA_Tx = 1; else SDA_Tx = 0; SCL_Tx = 1; I2C_Delay(I2C_Clock); data <<= 1; SCL_Tx = 0; I2C_Delay(I2C_Clock); } SDA_Tx = 1; I2C_Delay(I2C_Clock); SCL_Tx = 1; I2C_Delay(I2C_Clock); ACK = SDA_Rx; // Retrieve ACK bit SCL_Tx = 0; return ACK; }
/*------------------------------------------------------------------*- I2C_Read_Byte() Read a byte of data from the Slave. Supports slow Slaves by allowing 'clock stretching'. -*------------------------------------------------------------------*/ tByte I2C_Read_Byte(void) { tByte result = 0; // Return value with read I2C byte tByte Bit = 0; // Bitcounter for (Bit = 0; Bit < 8; Bit++ ) { I2C_SDA = 1; // Release SDA I2C_SCL = 1; // Release SCL if (I2C_Sync_The_Clock_T0()) { return 1; // Error - failed to sync } I2C_Delay(); result <<= 1; // Shift left the result if (I2C_SDA) { result |= 0x01; // Set actual SDA state to LSB } I2C_SCL = 0; // Force a clock cycle I2C_Delay(); } return(result); }
unsigned char I2C_Rx(unsigned char ACK) { unsigned char x, d = 0; SDA_Tx = 1; for ( x=0 ; x<8 ; x++) { d <<= 1; do { SCL_Tx = 1; } while (SCL_Rx == 0); // Wait through clock-stretching I2C_Delay(I2C_Clock); if (SDA_Rx) d |= 1; SCL_Tx = 0; I2C_Delay(I2C_Clock); } if (!ACK) SDA_Tx = 0; else SDA_Tx = 1; I2C_Delay(I2C_Clock); SCL_Tx = 1; // Sending (N)ACK I2C_Delay(I2C_Clock); SCL_Tx = 0; I2C_Delay(I2C_Clock); SDA_Tx = 1; return d; }
/* ------------------------------------------------------------------- Name: I2C_TxData - Purpose: To do I2C parallel serial conversion for transmission. Passed: Returns: None. Notes: ------------------------------------------------------------------- */ void I2C_TxData (UB8 bData) { UB8 bMask; /* MSB is sent first */ for (bMask = 0x80; bMask; bMask >>= 1) { //I2C_SET_SDA(bData & bMask); if (bData & bMask) { BIT1216M_I2C_SDA_HIGH; } else { BIT1216M_I2C_SDA_LOW; } I2C_Delay(I2C_SU_DAT); //I2C_SET_SCL(HIGH); BIT1216M_I2C_SCL_HIGH; I2C_Delay(I2C_HIGH); //I2C_SET_SCL(LOW); BIT1216M_I2C_SCL_LOW; I2C_Delay(I2C_LOW); } //I2C_SET_SDA(HIGH); // Added by JC 01:47PM 2005/11/23 BIT1216M_I2C_SDA_HIGH; } /* I2C_TxData */
/*------------------------------------------------------------------*- I2C_Send_Stop() Generates a 'stop' condition (see text for details). -*------------------------------------------------------------------*/ void I2C_Send_Stop(void) { I2C_SDA = 0; I2C_Delay(); I2C_SCL = 1; I2C_Delay(); I2C_SDA = 1; }
void S_NoACK(void) //Send No ACK (High) { SDA = 1; I2C_Delay(); SCL = 1; I2C_Delay(); SCL = 0; I2C_Delay(); }
void S_ACK(void) //Send ACK (LOW) { SDA = 0; I2C_Delay(); SCL = 1; I2C_Delay(); SCL = 0; I2C_Delay(); }
void I2C_Stop(void) //STOP the I2C, SDA Low-to-high when SCL is high { SDA = 0; I2C_Delay(); SCL = 1; I2C_Delay(); SDA = 1; I2C_Delay(); }
void I2C_Stop() { SDA_Tx = 0; // Stop sequence I2C_Delay(I2C_Clock); SCL_Tx = 1; I2C_Delay(I2C_Clock); SDA_Tx = 1; I2C_Delay(I2C_Clock); }
void I2C_Stop(void) { SDA_L; SCL_H; I2C_Delay(); SDA_H; I2C_Delay(); }
/***************************************************************************** 函 数 名 : WriteBeforeRead 功能描述 : 输入参数 : 无 输出参数 : 无 返 回 值 : void 调用函数 : 被调函数 : 修改历史 : 1. 2013.4.12 c00213799 对接器件读时序差异 *****************************************************************************/ EFI_STATUS EFIAPI WriteBeforeRead(I2C_DEVICE *I2cInfo, UINT32 ulLength, UINT8 *pBuf) { UINT32 ulFifo; UINT32 ulCnt; UINT32 ulTimes = 0; UINTN Base = PlatformGetI2cBase(I2cInfo->Socket, I2cInfo->Port); //设置slave地址为DIMM0 I2C_SetTarget(I2cInfo->Socket,I2cInfo->Port,I2cInfo->SlaveDeviceAddress); ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); while(0 != ulFifo) { I2C_Delay(2); if(++ulTimes > I2C_READ_TIMEOUT) { return EFI_TIMEOUT; } ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); } ulTimes = 0; for(ulCnt = 0; ulCnt < ulLength; ulCnt++) { while(ulFifo > I2C_TXRX_THRESHOLD) { if(++ulTimes > I2C_READ_TIMEOUT) { return EFI_TIMEOUT; } ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); } I2C_REG_WRITE(Base + I2C_DATA_CMD_OFFSET, *pBuf++); ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); } ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); ulTimes = 0; while(0 != ulFifo) { I2C_Delay(2); if(++ulTimes > I2C_READ_TIMEOUT) { return EFI_TIMEOUT; } ulFifo = I2C_GetTxStatus(I2cInfo->Socket,I2cInfo->Port); } return EFI_SUCCESS; }
void I2C_SW::I2C_Stop(void) { SCL_LO; I2C_Delay(); SDA_LO; I2C_Delay(); I2C_SCLHigh(); I2C_Delay(); SDA_HI; I2C_Delay(); }
bool I2C_Start(void) { SDA_H; SCL_H; I2C_Delay(); SDA_L; I2C_Delay(); SCL_L; return TRUE; }
void I2C_Start(void) //start the I2C, SDA High-to-low when SCL is high { SDA = 1; I2C_Delay(); SCL = 1; I2C_Delay(); SDA = 0; I2C_Delay(); SCL = 0; I2C_Delay(); }
void I2C_SW::I2C_SendNoAck(void) { SCL_LO; I2C_Delay(); SDA_HI; I2C_Delay(); I2C_SCLHigh(); I2C_Delay(); SCL_LO; I2C_Delay(); }
/*------------------------------------------------------------------*- I2C_Send_Start() Generates a 'start' condition (see text for details). -*------------------------------------------------------------------*/ void I2C_Send_Start(void) { // Prepare the bus I2C_SCL = 1; I2C_SDA = 1; I2C_Delay(); // Generate the START condition I2C_SDA = 0; I2C_Delay(); I2C_SCL = 0; }
//void I2C_Check_ACK(void) //Check ACK, If F0=0, then right, if F0=1, then error void I2C_Check_ACK(char ack) //Check ACK, If F0=0, then right, if F0=1, then error { if(ack == 1) SDA = 1; else SDA = 0; I2C_Delay(); SCL = 1; I2C_Delay(); F0 = SDA; SCL = 0; I2C_Delay(); }
void I2C_Ack(void) { SCL_L; I2C_Delay(); SDA_L; I2C_Delay(); SCL_H; I2C_Delay(); SCL_L; I2C_Delay(); SCL_H; SDA_H; }
/* ------------------------------------------------------------------- Name: I2C_SetNAK - Purpose: . Passed: None. Returns: None. Notes: ------------------------------------------------------------------- */ void I2C_SetNAK (void) { //I2C_SET_SDA(HIGH); BIT1216M_I2C_SDA_HIGH; I2C_Delay(I2C_SU_DAT); //I2C_SET_SCL(HIGH); BIT1216M_I2C_SCL_HIGH; I2C_Delay(I2C_HIGH); //I2C_SET_SCL(LOW); BIT1216M_I2C_SCL_LOW; I2C_Delay(I2C_LOW); } /* I2C_SetNAK */
uint8_t I2C_SW::I2C_WaitAck(void) { SCL_LO; I2C_Delay(); SDA_HI; I2C_Delay(); I2C_SCLHigh(); I2C_Delay(); if (SDA_STATE()) { SCL_LO; return 0; } SCL_LO; return 1; }
/*------------------------------------------------------------------*- I2C_Get_Ack_From_Slave() We are implementing a 'Master-Slave' communication protocol here, with the microcontroller as the Master. This function waits (with timeout) for an acknowledgement from the Slave device. -*------------------------------------------------------------------*/ tByte I2C_Get_Ack_From_Slave(void) { // Prepare the bus I2C_SDA = 1; I2C_SCL = 1; if(I2C_Sync_The_Clock_T0()) { return 1; // Error - failed to sync } // Managed to synchronise the clock I2C_Delay(); if (I2C_SDA) { // Generate a clock cycle I2C_SCL = 0; return 1; // Error - No ack from slave } I2C_SCL = 0; // Generate a clock cycle return 0; // OK - Slave issued ack }
/*------------------------------------------------------------------*- I2C_Write_Byte() Send a byte of data to the Slave. Supports slow Slaves by allowing 'clock stretching'. -*------------------------------------------------------------------*/ tByte I2C_Write_Byte(tByte Data) { tByte Bit = 0; // Sending data one bit at a time (MS bit first) for (Bit = 0; Bit < 8; Bit++ ) { I2C_SDA = (bit)((Data & 0x80) >> 7); I2C_SCL = 1; if (I2C_Sync_The_Clock_T0()) { return 1; // Error - failed to sync } I2C_Delay(); // Generate a clock cycle I2C_SCL = 0; // Prepare to send next bit Data <<= 1; } // Make sure the slave acknowledges return(I2C_Get_Ack_From_Slave()); }
/* ------------------------------------------------------------------- Name: I2C_SetACK - Purpose: . Passed: None. Returns: None. Notes: ------------------------------------------------------------------- */ void I2C_SetACK (void) { // I2C_SET_SDA(LOW); BIT1216M_I2C_SDA_LOW; I2C_Delay(I2C_SU_DAT); //I2C_SET_SCL(HIGH); BIT1216M_I2C_SCL_HIGH; I2C_Delay(I2C_HIGH); //I2C_SET_SCL(LOW); BIT1216M_I2C_SCL_LOW; I2C_Delay(I2C_LOW); //I2C_SET_SDA(HIGH); // Added by JC 09:32AM 2010/04/04 BIT1216M_I2C_SDA_HIGH; } /* I2C_SetACK */
u8 I2C_ReadAbyte(void) //read A byte from I2C { u8 i,dat; i = 8; SDA = 1; do { SCL = 1; I2C_Delay(); dat <<= 1; if(SDA) dat++; SCL = 0; I2C_Delay(); } while(--i); return(dat); }
uint8_t I2C_SW::I2C_ReceiveByte(void) { uint8_t i = 8; uint8_t Data = 0; SDA_HI; while (i--) { Data <<= 1; SCL_LO; I2C_Delay(); I2C_SCLHigh(); I2C_Delay(); if (SDA_STATE()) { Data |= 0x01; } } SCL_LO; return Data; }
/** * @brief Main program * @param None * @retval None */ int main() { int i; /*System clock configuration*/ SystemInit(); /* UART0 and UART1 configuration*/ UART_StructInit(&UART_InitStructure); /* Configure UART0 */ UART_Init(UART1,&UART_InitStructure); printf("######## I2C EEPROM TEST #########\r\n"); /* I2C Init */ /* I2C confiugred as follow: * - I2C master mode * - I2C slave address : 0xA0 * - I2C Prescale : 0x61 * /If MCU clock is 20MHz and Prescale value is 0x61, SCL occurs 100KHz as clock. * - I2C Timeout : 0xFFFF */ conf.mode = I2C_Master; conf.slave_address = 0xA0; conf.master.prescale = 0x61; conf.master.timeout = 0xFFFF; /* Cofigure I2C0 */ I2C_Init(I2C0, conf); /* EEPROM Write Test*/ /* It can transmit up to 9data bytes to the EEPROM(24AA02) ( mem_address 1byte, data 8bytes ) */ if( I2C_Burst_Write(I2C0,conf.slave_address,&Transmit_Data[0],9,1) == -1 ) return -1; /*It must be use the delay function between Write operation and Read operation */ I2C_Delay(0x000F0000); /*I2C Core reset */ I2C_Reset(I2C0); // EEPROM Read Test /* I2C Start */ I2C_Start(I2C0,conf.slave_address,I2C_WRITE_SA7); /* The memory address of EEPROM send to EEPROM and it wait the ack signal */ I2C_SendDataAck(I2C0,0x00); /*Once the Slave address and memotu address are clocked in and *acknowledged by the EEPROM, the W7500 must generate another start condition.*/ I2C_Restart_Structure(I2C0,conf.slave_address,I2C_READ_SA7); /* EEPROM Read Test*/ for(i=0;i<MAX_SIZE;i++) { if(i != MAX_SIZE-1) Recv_Data[i] = I2C_ReceiveData(I2C0,0); else Recv_Data[i] = I2C_ReceiveData(I2C0,1); } for(i=0;i<MAX_SIZE-2;i+=2) printf("[%02d]:%02x, [%02d]:%02x\r\n",i,Recv_Data[i],i+1,Recv_Data[i+1]); return 0; }
void I2C_WriteAbyte(u8 dat) //write a byte to I2C { u8 i; i = 8; do { if(dat & 0x80) SDA = 1; else SDA = 0; dat <<= 1; I2C_Delay(); SCL = 1; I2C_Delay(); SCL = 0; I2C_Delay(); } while(--i); I2C_Check_ACK(1); //接收应答信号 }
/*------------------------------------------------------------------*- I2C_Send_Master_NAck() Generates a 'Not Acknowledge' condition (see text for details). -*------------------------------------------------------------------*/ void I2C_Send_Master_NAck(void) { I2C_SDA = 1; I2C_SCL = 1; I2C_Sync_The_Clock_T0(); I2C_Delay(); I2C_SCL = 0; }
/* ------------------------------------------------------------------- Name: I2C_Start - START condition (SDA falling edge). Purpose: . Passed: None. Returns: None. Notes: Reference: [1] p64 ------------------------------------------------------------------- */ void I2C_Start (void) { DEBUG_MSG(("<<====I2C_Start====>>\r\n")); //I2C_SET_SDA(HIGH); BIT1216M_I2C_SDA_HIGH; //I2C_SET_SCL(HIGH); BIT1216M_I2C_SCL_HIGH; I2C_Delay(I2C_SU_STA); //I2C_SET_SDA(LOW); BIT1216M_I2C_SDA_LOW; I2C_Delay(I2C_HD_STA); //I2C_SET_SCL(LOW); BIT1216M_I2C_SCL_LOW; I2C_Delay(I2C_LOW); } /* I2C_Start */