void I2C_writeSlv(const unsigned int slvAddr, const unsigned int slvReg, const unsigned int data){ volatile unsigned int x_data_a = 0; unsigned int Error = 0; //Waits for i2c I2C_waitTillDone(); //Send START, Register I2C_setReadSlv(slvAddr,0); I2C_setData(slvReg,0); I2C_Execute(I2C_START_EXECUTE); I2C_waitTillIdle(); Error = I2C_CheckError(); if(Error) UART4_DATA = 'E'; //Send Data, STOP I2C_setData(data,0); I2C_Execute(I2C_EXECUTE_STOP); I2C_waitTillDone(); Error = I2C_CheckError(); if(Error) UART4_DATA = 'E'; }
void I2C_readSlv(const unsigned int slvAddr, const unsigned int slvReg){ volatile unsigned int x_data_a = 0; unsigned int Error = 0; //Waits for i2c I2C_waitTillDone(); //Send Register I2C_setReadSlv(slvAddr,0); I2C_setData(slvReg,0); I2C_sendRecieveWithStop(0); I2C_waitTillIdle(); Error = I2C_CheckError(); if(Error) UART4_DATA = 'E'; //Receive Data I2C_setReadSlv(slvAddr,1); I2C_sendRecieveWithStop(1); I2C_waitTillDone(); if(I2C_CheckError()==0){ x_data_a = I2C0_MDR; UART4_DATA = x_data_a; } }
/* General Slave Interrupt handler for I2C peripheral */ void IP_I2C_Interrupt_SlaveHandler(IP_I2C_001_Type *LPC_I2C, I2C_ID_Type I2C_Num) { uint32_t returnCode; I2C_S_SETUP_Type *txrx_setup; int32_t Ret = I2C_OK; txrx_setup = (I2C_S_SETUP_Type *) &i2cdat[I2C_Num].txrx_setup_slave; while (!(LPC_I2C->CONSET & I2C_I2CONSET_SI)) {} returnCode = (uint32_t) (LPC_I2C->STAT & I2C_STAT_CODE_BITMASK); /* Save current status */ txrx_setup->status = returnCode; Ret = IP_I2C_SlaveHanleStates(LPC_I2C, returnCode, txrx_setup); if ((I2C_CheckError(Ret)) || (Ret & I2C_STA_STO_RECV) || (Ret & I2C_SEND_END)) { goto s_int_end; } else { return; } s_int_end: LPC_I2C->CONCLR = I2C_I2CONCLR_AAC | I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC; I2C_SlaveComplete[I2C_Num] = true; }
void I2C_readSlvChunk(const unsigned int slvAddr, const unsigned int startReg, const unsigned int noRegs, char array[]){ volatile char data_a = 0; int i=0; //Waits for i2c I2C_waitTillDone(); //Send Register I2C_setReadSlv(slvAddr,0); I2C_setData(startReg, 1); I2C_sendRecieveWithStop(0); //I2C_Execute(I2C_START_EXECUTE); I2C_waitTillIdle(); I2C_setReadSlv(slvAddr,1); I2C_Execute(0x0B); for(i=0; i<noRegs; i++){ I2C_waitTillIdle(); if(I2C_CheckError()==0){ data_a = I2C0_MDR; array[i] = data_a; //UART4_DATA = x_data_a; } I2C_Execute((i==noRegs-1)?I2C_EXECUTE_STOP:I2C_EXECUTE); } }
/* General Master Interrupt handler for I2C peripheral */ void IP_I2C_Interrupt_MasterHandler(IP_I2C_001_Type *LPC_I2C, I2C_ID_Type I2C_Num) { uint32_t returnCode; I2C_M_SETUP_Type *txrx_setup; int32_t Ret = I2C_OK; txrx_setup = (I2C_M_SETUP_Type *) &i2cdat[I2C_Num].txrx_setup_master; while (!(LPC_I2C->CONSET & I2C_I2CONSET_SI)) {} returnCode = (uint32_t) (LPC_I2C->STAT & I2C_STAT_CODE_BITMASK); /* Save current status */ txrx_setup->status = returnCode; Ret = IP_I2C_MasterHanleStates(LPC_I2C, returnCode, txrx_setup, I2C_TRANSFER_INTERRUPT); if (I2C_CheckError(Ret)) { if (txrx_setup->retransmissions_count < txrx_setup->retransmissions_max) { /* Retry */ txrx_setup->retransmissions_count++; txrx_setup->tx_count = 0; txrx_setup->rx_count = 0; /* Reset STA, STO, SI */ IP_I2C_Start(LPC_I2C, I2C_TRANSFER_INTERRUPT); return; } else { goto s_int_end; } } else if (Ret & I2C_SEND_END) { /* If no need to wait for data from Slave */ if (txrx_setup->rx_count >= (txrx_setup->rx_length)) { goto s_int_end; } else { /* Start to wait for data from Slave */ /* Reset STA, STO, SI */ IP_I2C_Start(LPC_I2C, I2C_TRANSFER_INTERRUPT); return; } } else if (Ret & I2C_RECV_END) { goto s_int_end; } else { return; } s_int_end: LPC_I2C->CONCLR = I2C_I2CONCLR_AAC | I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC; I2C_MasterComplete[I2C_Num] = true; }
/***************************************************************************** ** Function name: I2C_MstReceive ** Descriptions: the module will receive a block of data from ** the I2C. ** parameters: Device address, buffer pointer, and block length ** Returned value: None ** *****************************************************************************/ void I2C_MstReceive( LPC_I2C_TypeDef *I2Cx, uint32_t addr, uint8_t *rx, uint32_t Length ) { uint32_t i; I2Cx->MSTDAT = addr; I2Cx->MSTCTL = CTL_MSTSTART; #if I2C_INTERRUPT mstrxrdy = 0; I2Cx->INTENSET = STAT_MSTPEND; #endif for ( i = 0; i < Length; i++ ) { #if I2C_INTERRUPT while(!mstrxrdy) { if ( I2C_CheckError(I2Cx) ) { I2C_CheckIdle(I2Cx); /* Recursive call here. Be very careful with stack over flow if come here. especially when the other master trys to grab the bus all the time. */ // while ( 1 ); I2C_MstReceive( I2Cx, addr, rx, Length ); return; } } mstrxrdy = 0; *rx++ = I2Cx->MSTDAT; if ( i != Length -1 ) { I2Cx->MSTCTL = CTL_MSTCONTINUE; I2Cx->INTENSET = STAT_MSTPEND; } #else /* Slave address has been sent, master receive is ready. */ while (!(I2Cx->STAT & STAT_MSTPEND)); if((I2Cx->STAT & MASTER_STATE_MASK) != STAT_MSTRX) while( 1 ); *rx++ = I2Cx->MSTDAT; if ( i != Length -1 ) { I2Cx->MSTCTL = CTL_MSTCONTINUE; } #endif } I2Cx->MSTCTL = CTL_MSTSTOP | CTL_MSTCONTINUE; I2C_CheckIdle(I2Cx); return; }
/* Receive and Transmit data in slave mode */ Status IP_I2C_SlaveTransferData(IP_I2C_001_Type *LPC_I2C, I2C_ID_Type I2C_Num, I2C_S_SETUP_Type *TransferCfg, I2C_TRANSFER_OPT_Type Opt) { int32_t Ret = I2C_OK; uint32_t CodeStatus = 0; /* Reset I2C setup value to default state */ TransferCfg->tx_count = 0; TransferCfg->rx_count = 0; TransferCfg->status = 0; /* Polling option */ if (Opt == I2C_TRANSFER_POLLING) { /* Set AA bit to ACK command on I2C bus */ LPC_I2C->CONSET = I2C_I2CONSET_AA; /* Clear SI bit to be ready ... */ LPC_I2C->CONCLR = (I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC | I2C_I2CONCLR_STOC); while (1) { /* Check SI flag ready */ if (LPC_I2C->CONSET & I2C_I2CONSET_SI) { CodeStatus = (LPC_I2C->STAT & I2C_STAT_CODE_BITMASK); Ret = IP_I2C_SlaveHanleStates(LPC_I2C, CodeStatus, TransferCfg); if (I2C_CheckError(Ret)) { goto s_error; } else if ((Ret & I2C_STA_STO_RECV) || (Ret & I2C_SEND_END)) { goto s_end_stage; } } } s_end_stage: /* Clear AA bit to disable ACK on I2C bus */ LPC_I2C->CONCLR = I2C_I2CONCLR_AAC; /* Check if there's no error during operation * Update status */ TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_DONE; return SUCCESS; s_error: /* Clear AA bit to disable ACK on I2C bus */ LPC_I2C->CONCLR = I2C_I2CONCLR_AAC; /* Update status */ TransferCfg->status = CodeStatus; return ERROR; } else if (Opt == I2C_TRANSFER_INTERRUPT) { I2C_SlaveComplete[I2C_Num] = false; /* Setup tx_rx data, callback and interrupt handler */ i2cdat[I2C_Num].txrx_setup_slave = *TransferCfg; /* Set direction phase, read first */ i2cdat[I2C_Num].dir = 1; /* Enable AA */ LPC_I2C->CONSET = I2C_I2CONSET_AA; LPC_I2C->CONCLR = I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC; return SUCCESS; } return ERROR; }
/* Transmit and Receive data in master mode */ Status IP_I2C_MasterTransferData(IP_I2C_001_Type *LPC_I2C, I2C_ID_Type I2C_Num, I2C_M_SETUP_Type *TransferCfg, I2C_TRANSFER_OPT_Type Opt) { uint32_t CodeStatus; int32_t Ret = I2C_OK; /* Reset I2C setup value to default state */ TransferCfg->tx_count = 0; TransferCfg->rx_count = 0; TransferCfg->status = 0; if (Opt == I2C_TRANSFER_POLLING) { /* First Start condition -------------------------------------------------------------- */ TransferCfg->retransmissions_count = 0; retry: /* Reset I2C setup value to default state */ TransferCfg->tx_count = 0; TransferCfg->rx_count = 0; /* Start command */ CodeStatus = IP_I2C_Start(LPC_I2C, I2C_TRANSFER_POLLING); while (1) { /* send data first and then receive data from Slave */ Ret = IP_I2C_MasterHanleStates(LPC_I2C, CodeStatus, TransferCfg, I2C_TRANSFER_POLLING); if (I2C_CheckError(Ret)) { TransferCfg->retransmissions_count++; if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max) { /* save status */ TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_NOACKF; goto error; } else { goto retry; } } else if ( (Ret & I2C_BYTE_SENT) || (Ret & I2C_BYTE_RECV)) { /* Wait for sending ends/ Wait for next byte */ while (!(LPC_I2C->CONSET & I2C_I2CONSET_SI)) {} } else if (Ret & I2C_SEND_END) { /* already send all data */ /* If no need to wait for data from Slave */ if (TransferCfg->rx_count >= (TransferCfg->rx_length)) { break; } else { IP_I2C_Start(LPC_I2C, I2C_TRANSFER_POLLING); } } else if (Ret & I2C_RECV_END) { /* already receive all data */ break; } CodeStatus = LPC_I2C->STAT & I2C_STAT_CODE_BITMASK; } return SUCCESS; error: return ERROR; } else if (Opt == I2C_TRANSFER_INTERRUPT) { I2C_MasterComplete[I2C_Num] = false; /* Setup tx_rx data, callback and interrupt handler */ i2cdat[I2C_Num].txrx_setup_master = *TransferCfg; /* Set direction phase, write first */ i2cdat[I2C_Num].dir = 0; /* First Start condition -------------------------------------------------------------- */ /* Reset STA, STO, SI */ LPC_I2C->CONCLR = I2C_I2CONCLR_SIC | I2C_I2CONCLR_STOC | I2C_I2CONCLR_STAC; LPC_I2C->CONSET = I2C_I2CONSET_STA; return SUCCESS; } return ERROR; }
/*********************************************************************//** * @brief Transmit and Receive data in master mode * @param[in] I2Cx I2C peripheral selected, should be: * - LPC_I2C0 * - LPC_I2C1 * - LPC_I2C2 * @param[in] TransferCfg Pointer to a I2C_M_SETUP_Type structure that * contains specified information about the * configuration for master transfer. * @param[in] Opt a I2C_TRANSFER_OPT_Type type that selected for * interrupt or polling mode. * @return SUCCESS or ERROR * * Note: * - In case of using I2C to transmit data only, either transmit length set to 0 * or transmit data pointer set to NULL. * - In case of using I2C to receive data only, either receive length set to 0 * or receive data pointer set to NULL. * - In case of using I2C to transmit followed by receive data, transmit length, * transmit data pointer, receive length and receive data pointer should be set * corresponding. **********************************************************************/ Status I2C_MasterTransferData(en_I2C_unitId i2cId, I2C_M_SETUP_Type *TransferCfg, I2C_TRANSFER_OPT_Type Opt) { LPC_I2C_TypeDef* I2Cx = I2C_GetPointer(i2cId); uint32_t CodeStatus; int32_t Ret = I2C_OK; // Reset I2C setup value to default state TransferCfg->tx_count = 0; TransferCfg->rx_count = 0; TransferCfg->status = 0; if (Opt == I2C_TRANSFER_POLLING) { /* First Start condition -------------------------------------------------------------- */ TransferCfg->retransmissions_count = 0; retry: // Reset I2C setup value to default state TransferCfg->tx_count = 0; TransferCfg->rx_count = 0; // Start command CodeStatus = I2C_Start(I2Cx, I2C_TRANSFER_POLLING); while(1) // send data first and then receive data from Slave. { Ret = I2C_MasterHanleStates(i2cId, CodeStatus, TransferCfg, I2C_TRANSFER_POLLING); if(I2C_CheckError(Ret)) { TransferCfg->retransmissions_count++; if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){ // save status TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_NOACKF; goto error; } else { goto retry; } } else if( (Ret & I2C_BYTE_SENT) || (Ret & I2C_BYTE_RECV)) { // Wait for sending ends/ Wait for next byte while (!(I2Cx->CONSET & I2C_I2CONSET_SI)); } else if (Ret & I2C_SEND_END) // already send all data { // If no need to wait for data from Slave if(TransferCfg->rx_count >= (TransferCfg->rx_length)) { break; } else { I2C_Start(I2Cx, I2C_TRANSFER_POLLING); } } else if (Ret & I2C_RECV_END) // already receive all data { break; } CodeStatus = I2Cx->STAT & I2C_STAT_CODE_BITMASK; } return SUCCESS; error: return ERROR; } else if (Opt == I2C_TRANSFER_INTERRUPT) { // Setup tx_rx data, callback and interrupt handler i2cdat[i2cId].txrx_setup = (uint32_t) TransferCfg; // Set direction phase, write first i2cdat[i2cId].dir = 0; /* First Start condition -------------------------------------------------------------- */ // Reset STA, STO, SI I2C_Start(I2Cx, I2C_TRANSFER_INTERRUPT); I2C_IntCmd(i2cId, TRUE); return (SUCCESS); } return ERROR; }
/*********************************************************************//** * @brief General Slave Interrupt handler for I2C peripheral * @param[in] I2Cx I2C peripheral selected, should be: * - LPC_I2C0 * - LPC_I2C1 * - LPC_I2C2 * @return None **********************************************************************/ void I2C_SlaveHandler (en_I2C_unitId i2cId) { LPC_I2C_TypeDef* I2Cx = I2C_GetPointer(i2cId); uint8_t returnCode; I2C_S_SETUP_Type *txrx_setup; uint32_t timeout; int32_t Ret = I2C_OK; txrx_setup = (I2C_S_SETUP_Type *) i2cdat[i2cId].txrx_setup; handle_state: returnCode = (I2Cx->STAT & I2C_STAT_CODE_BITMASK); // Save current status txrx_setup->status = returnCode; Ret = I2C_SlaveHanleStates(i2cId, returnCode, txrx_setup); if(I2C_CheckError(Ret)) { goto s_int_end; } else if (Ret & I2C_STA_STO_RECV) { // Temporally lock the interrupt for timeout condition I2C_IntCmd(i2cId, FALSE); // enable time out timeout = I2C_SLAVE_TIME_OUT; while(1) { if (I2Cx->CONSET & I2C_I2CONSET_SI) { // re-Enable interrupt I2C_IntCmd(i2cId, TRUE); goto handle_state; } else { timeout--; if (timeout == 0) { // timeout occur, it's really a stop condition txrx_setup->status |= I2C_SETUP_STATUS_DONE; goto s_int_end; } } } } else if(Ret &I2C_SEND_END) { goto s_int_end; } else { return; } s_int_end: // Disable interrupt I2C_IntCmd(i2cId, FALSE); I2Cx->CONCLR = I2C_I2CONCLR_AAC | I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC; I2C_SlaveComplete[i2cId] = TRUE; }
/*********************************************************************//** * @brief General Master Interrupt handler for I2C peripheral * @param[in] I2Cx I2C peripheral selected, should be: * - LPC_I2C * - LPC_I2C1 * - LPC_I2C2 * @return None **********************************************************************/ void I2C_MasterHandler(en_I2C_unitId i2cId) { LPC_I2C_TypeDef* I2Cx = I2C_GetPointer(i2cId); uint8_t returnCode; I2C_M_SETUP_Type *txrx_setup; int32_t Ret = I2C_OK; txrx_setup = (I2C_M_SETUP_Type *) i2cdat[i2cId].txrx_setup; returnCode = (I2Cx->STAT & I2C_STAT_CODE_BITMASK); // Save current status txrx_setup->status = returnCode; Ret = I2C_MasterHanleStates(i2cId, returnCode, txrx_setup, I2C_TRANSFER_INTERRUPT); if(I2C_CheckError(Ret)) { if(txrx_setup->retransmissions_count < txrx_setup->retransmissions_max) { // Retry txrx_setup->retransmissions_count ++; txrx_setup->tx_count = 0; txrx_setup->rx_count = 0; // Reset STA, STO, SI I2C_Start(I2Cx, I2C_TRANSFER_INTERRUPT); return; } else { goto s_int_end; } } else if (Ret & I2C_SEND_END) { // If no need to wait for data from Slave if(txrx_setup->rx_count >= (txrx_setup->rx_length)) { goto s_int_end; } else // Start to wait for data from Slave { // Reset STA, STO, SI I2C_Start(I2Cx, I2C_TRANSFER_INTERRUPT); return; } } else if (Ret & I2C_RECV_END) { goto s_int_end; } else { return; } s_int_end: // Disable interrupt I2C_IntCmd(i2cId, FALSE); I2Cx->CONCLR = I2C_I2CONCLR_AAC | I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC; I2C_MasterComplete[i2cId] = TRUE; }
/*********************************************************************//** * @brief Receive and Transmit data in slave mode * @param[in] I2Cx I2C peripheral selected, should be * - LPC_I2C0 * - LPC_I2C1 * - LPC_I2C2 * @param[in] TransferCfg Pointer to a I2C_S_SETUP_Type structure that * contains specified information about the * configuration for master transfer. * @param[in] Opt I2C_TRANSFER_OPT_Type type that selected for * interrupt or polling mode. * @return SUCCESS or ERROR * * Note: * The mode of slave's operation depends on the command sent from master on * the I2C bus. If the master send a SLA+W command, this sub-routine will * use receive data length and receive data pointer. If the master send a SLA+R * command, this sub-routine will use transmit data length and transmit data * pointer. * If the master issue an repeat start command or a stop command, the slave will * enable an time out condition, during time out condition, if there's no activity * on I2C bus, the slave will exit, otherwise (i.e. the master send a SLA+R/W), * the slave then switch to relevant operation mode. The time out should be used * because the return status code can not show difference from stop and repeat * start command in slave operation. * In case of the expected data length from master is greater than data length * that slave can support: * - In case of reading operation (from master): slave will return I2C_I2DAT_IDLE_CHAR * value. * - In case of writing operation (from master): slave will ignore remain data from master. **********************************************************************/ Status I2C_SlaveTransferData(en_I2C_unitId i2cId, I2C_S_SETUP_Type *TransferCfg, I2C_TRANSFER_OPT_Type Opt) { LPC_I2C_TypeDef* I2Cx = I2C_GetPointer(i2cId); int32_t Ret = I2C_OK; uint32_t CodeStatus; uint32_t timeout; int32_t time_en; // Reset I2C setup value to default state TransferCfg->tx_count = 0; TransferCfg->rx_count = 0; TransferCfg->status = 0; // Polling option if (Opt == I2C_TRANSFER_POLLING) { /* Set AA bit to ACK command on I2C bus */ I2Cx->CONSET = I2C_I2CONSET_AA; /* Clear SI bit to be ready ... */ I2Cx->CONCLR = (I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC|I2C_I2CONCLR_STOC); time_en = 0; timeout = 0; while (1) { /* Check SI flag ready */ if (I2Cx->CONSET & I2C_I2CONSET_SI) { time_en = 0; CodeStatus = (I2Cx->STAT & I2C_STAT_CODE_BITMASK); Ret = I2C_SlaveHanleStates(i2cId, CodeStatus, TransferCfg); if(I2C_CheckError(Ret)) { goto s_error; } else if(Ret & I2C_STA_STO_RECV) { time_en = 1; timeout = 0; } else if (Ret & I2C_SEND_END) { goto s_end_stage; } } else if (time_en) { if (timeout++ > I2C_SLAVE_TIME_OUT) { // it's really a stop condition, goto end stage goto s_end_stage; } } } s_end_stage: /* Clear AA bit to disable ACK on I2C bus */ I2Cx->CONCLR = I2C_I2CONCLR_AAC; // Check if there's no error during operation // Update status TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_DONE; return SUCCESS; s_error: /* Clear AA bit to disable ACK on I2C bus */ I2Cx->CONCLR = I2C_I2CONCLR_AAC; // Update status TransferCfg->status = CodeStatus; return ERROR; } else if (Opt == I2C_TRANSFER_INTERRUPT) { // Setup tx_rx data, callback and interrupt handler i2cdat[i2cId].txrx_setup = (uint32_t) TransferCfg; // Set direction phase, read first i2cdat[i2cId].dir = 1; // Enable AA I2Cx->CONSET = I2C_I2CONSET_AA; I2Cx->CONCLR = I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC; I2C_IntCmd(i2cId, TRUE); return (SUCCESS); } return ERROR; }
/***************************************************************************** ** Function name: I2C_MstSendRcv ** ** Descriptions: Send a block of data to the I2C port combining master ** send and master recevie with repeated start in the middle. ** ** parameters: Dev addr. TX ptr, TX length, RX ptr, and RX length. ** Returned value: None ** *****************************************************************************/ void I2C_MstSendRcv( LPC_I2C_TypeDef *I2Cx, uint32_t addr, uint8_t *tx, uint32_t txlen, uint8_t *rx, uint32_t rxlen ) { uint32_t i; I2Cx->MSTDAT = addr; I2Cx->MSTCTL = CTL_MSTSTART; #if I2C_INTERRUPT msttxrdy = mstrxrdy = 0; I2Cx->INTENSET = STAT_MSTPEND; #endif for ( i = 0; i < txlen; i++ ) { #if I2C_INTERRUPT while(!msttxrdy) { if ( I2C_CheckError(I2Cx) ) { I2C_CheckIdle(I2Cx); /* Recursive call here. Be very careful with stack over flow if come here, especially when the other master trys to grab the bus all the time. */ // while ( 1 ); I2C_MstSend( I2Cx, addr, tx, txlen ); return; } } msttxrdy = 0; I2Cx->MSTDAT = *tx++; I2Cx->MSTCTL = CTL_MSTCONTINUE; I2Cx->INTENSET = STAT_MSTPEND; #else /* Move only if TXRDY is ready */ while (!(I2Cx->STAT & STAT_MSTPEND)); if((I2Cx->STAT & MASTER_STATE_MASK) != STAT_MSTTX) while(1); I2Cx->MSTDAT = *tx++; I2Cx->MSTCTL = CTL_MSTCONTINUE; #endif } /* Wait for the last TX to finish before setting repeated start. */ #if I2C_INTERRUPT while(!msttxrdy) { if ( I2C_CheckError(I2Cx) ) { I2C_CheckIdle(I2Cx); /* Recursive call here. Be very careful with stack over flow if come here. especially when the other master trys to grab the bus all the time. */ // while ( 1 ); I2C_MstSend( I2Cx, addr, tx, txlen ); return; } } msttxrdy = 0; #else /* Move on only if TXRDY is ready */ while (!(I2Cx->STAT & STAT_MSTPEND)); if((I2Cx->STAT & MASTER_STATE_MASK) != STAT_MSTTX) while(1); #endif /* Repeated Start */ I2Cx->MSTDAT = addr|RD_BIT; I2Cx->MSTCTL = CTL_MSTSTART|CTL_MSTCONTINUE; #if I2C_INTERRUPT I2Cx->INTENSET = STAT_MSTPEND; #endif for ( i = 0; i < rxlen; i++ ) { #if I2C_INTERRUPT while(!mstrxrdy) { if ( I2C_CheckError(I2Cx) ) { I2C_CheckIdle(I2Cx); /* Recursive call here. Be very careful with stack over flow if come here, especially when the other master trys to grab the bus all the time. */ // while ( 1 ); I2C_MstReceive( I2Cx, addr|RD_BIT, rx, rxlen ); return; } } mstrxrdy = 0; *rx++ = I2Cx->MSTDAT; if ( i != rxlen-1 ) { I2Cx->MSTCTL = CTL_MSTCONTINUE; I2Cx->INTENSET = STAT_MSTPEND; } #else /* Slave address has been sent, master receive is ready. */ while (!(I2Cx->STAT & STAT_MSTPEND)); if((I2Cx->STAT & MASTER_STATE_MASK) != STAT_MSTRX) while(1); *rx++ = I2Cx->MSTDAT; if ( i != rxlen-1 ) { I2Cx->MSTCTL = CTL_MSTCONTINUE; } #endif } I2Cx->MSTCTL = CTL_MSTSTOP | CTL_MSTCONTINUE; I2C_CheckIdle(I2Cx); return; }
/***************************************************************************** ** Function name: I2C_MstSend ** ** Descriptions: Send a block of data to the I2C port, the ** first parameter is the device addre, the 2nd is buffer ** pointer, the 3rd is the block length. ** ** parameters: device addr, buffer pointer, and the block length ** Returned value: None ** *****************************************************************************/ void I2C_MstSend( LPC_I2C_TypeDef *I2Cx, uint32_t addr, uint8_t *tx, uint32_t Length ) { uint32_t i; I2Cx->MSTDAT = addr; I2Cx->MSTCTL = CTL_MSTSTART; #if I2C_INTERRUPT msttxrdy = 0; I2Cx->INTENSET = STAT_MSTPEND; #endif #if I2C_INTERRUPT for ( i = 0; i < Length; i++ ) { while(!msttxrdy) { if ( I2C_CheckError(I2Cx) ) { I2C_CheckIdle(I2Cx); /* Recursive call here. Be very careful with stack over flow if come here, especially when the other master trys to grab the bus all the time. */ // while ( 1 ); I2C_MstSend( I2Cx, addr, tx, Length ); return; } } msttxrdy = 0; I2Cx->MSTDAT = tx[i]; I2Cx->MSTCTL = CTL_MSTCONTINUE; I2Cx->INTENSET = STAT_MSTPEND; } /* Wait for the last one to go out. */ while(!msttxrdy) { if ( I2C_CheckError(I2Cx) ) { I2C_CheckIdle(I2Cx); /* Recursive call here. Be very careful with stack over flow if come here. especially when the other master trys to grab the bus all the time. */ // while ( 1 ); I2C_MstSend( I2Cx, addr, tx, Length ); return; } } msttxrdy = 0; #else for ( i = 0; i < Length; i++ ) { /* Move only if TXRDY is ready */ while (!(I2Cx->STAT & STAT_MSTPEND)); if((I2Cx->STAT & MASTER_STATE_MASK) != STAT_MSTTX) while(1); I2Cx->MSTDAT = *tx++; I2Cx->MSTCTL = CTL_MSTCONTINUE; } /* Wait for the last one to go out. */ while (!(I2Cx->STAT & STAT_MSTPEND)); if((I2Cx->STAT & MASTER_STATE_MASK) != STAT_MSTTX) while(1); #endif /* Send STOP condition. */ I2Cx->MSTCTL = CTL_MSTSTOP | CTL_MSTCONTINUE; I2C_CheckIdle(I2Cx); return; }