Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
lpc17xx_i2c.c
00001 /***********************************************************************//** 00002 * @file lpc17xx_i2c.c 00003 * @brief Contains all functions support for I2C firmware library on LPC17xx 00004 * @version 2.0 00005 * @date 21. May. 2010 00006 * @author NXP MCU SW Application Team 00007 ************************************************************************** 00008 * Software that is described herein is for illustrative purposes only 00009 * which provides customers with programming information regarding the 00010 * products. This software is supplied "AS IS" without any warranties. 00011 * NXP Semiconductors assumes no responsibility or liability for the 00012 * use of the software, conveys no license or title under any patent, 00013 * copyright, or mask work right to the product. NXP Semiconductors 00014 * reserves the right to make changes in the software without 00015 * notification. NXP Semiconductors also make no representation or 00016 * warranty that such application will be suitable for the specified 00017 * use without further testing or modification. 00018 **********************************************************************/ 00019 00020 /* Peripheral group ----------------------------------------------------------- */ 00021 /** @addtogroup I2C 00022 * @{ 00023 */ 00024 00025 /* Includes ------------------------------------------------------------------- */ 00026 #include "lpc17xx_i2c.h" 00027 #include "lpc17xx_clkpwr.h" 00028 #include "lpc17xx_pinsel.h" 00029 00030 00031 /* If this source file built with example, the LPC17xx FW library configuration 00032 * file in each example directory ("lpc17xx_libcfg.h") must be included, 00033 * otherwise the default FW library configuration file must be included instead 00034 */ 00035 #ifdef __BUILD_WITH_EXAMPLE__ 00036 #include "lpc17xx_libcfg.h" 00037 #else 00038 #include "lpc17xx_libcfg_default.h" 00039 #endif /* __BUILD_WITH_EXAMPLE__ */ 00040 00041 00042 #ifdef _I2C 00043 00044 00045 /* Private Types -------------------------------------------------------------- */ 00046 /** @defgroup I2C_Private_Types I2C Private Types 00047 * @{ 00048 */ 00049 00050 /** 00051 * @brief I2C device configuration structure type 00052 */ 00053 typedef struct 00054 { 00055 uint32_t txrx_setup; /* Transmission setup */ 00056 int32_t dir; /* Current direction phase, 0 - write, 1 - read */ 00057 } I2C_CFG_T; 00058 00059 /** 00060 * @} 00061 */ 00062 00063 /* Private Variables ---------------------------------------------------------- */ 00064 /** 00065 * @brief II2C driver data for I2C0, I2C1 and I2C2 00066 */ 00067 static I2C_CFG_T i2cdat[3]; 00068 00069 static uint32_t I2C_MasterComplete[3]; 00070 static uint32_t I2C_SlaveComplete[3]; 00071 00072 static uint32_t I2C_MonitorBufferIndex; 00073 00074 /* Private Functions ---------------------------------------------------------- */ 00075 00076 /* Get I2C number */ 00077 static int32_t I2C_getNum(LPC_I2C_TypeDef *I2Cx); 00078 00079 /* Generate a start condition on I2C bus (in master mode only) */ 00080 static uint32_t I2C_Start (LPC_I2C_TypeDef *I2Cx); 00081 00082 /* Generate a stop condition on I2C bus (in master mode only) */ 00083 static void I2C_Stop (LPC_I2C_TypeDef *I2Cx); 00084 00085 /* I2C send byte subroutine */ 00086 static uint32_t I2C_SendByte (LPC_I2C_TypeDef *I2Cx, uint8_t databyte); 00087 00088 /* I2C get byte subroutine */ 00089 static uint32_t I2C_GetByte (LPC_I2C_TypeDef *I2Cx, uint8_t *retdat, Bool ack); 00090 00091 /* I2C set clock (hz) */ 00092 static void I2C_SetClock (LPC_I2C_TypeDef *I2Cx, uint32_t target_clock); 00093 00094 /*--------------------------------------------------------------------------------*/ 00095 /********************************************************************//** 00096 * @brief Convert from I2C peripheral to number 00097 * @param[in] I2Cx: I2C peripheral selected, should be: 00098 * - LPC_I2C0 00099 * - LPC_I2C1 00100 * - LPC_I2C2 00101 * @return I2C number, could be: 0..2 00102 *********************************************************************/ 00103 static int32_t I2C_getNum(LPC_I2C_TypeDef *I2Cx){ 00104 if (I2Cx == LPC_I2C0) { 00105 return (0); 00106 } else if (I2Cx == LPC_I2C1) { 00107 return (1); 00108 } else if (I2Cx == LPC_I2C2) { 00109 return (2); 00110 } 00111 return (-1); 00112 } 00113 00114 /********************************************************************//** 00115 * @brief Generate a start condition on I2C bus (in master mode only) 00116 * @param[in] I2Cx: I2C peripheral selected, should be: 00117 * - LPC_I2C0 00118 * - LPC_I2C1 00119 * - LPC_I2C2 00120 * @return value of I2C status register after generate a start condition 00121 *********************************************************************/ 00122 static uint32_t I2C_Start (LPC_I2C_TypeDef *I2Cx) 00123 { 00124 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00125 I2Cx->I2CONSET = I2C_I2CONSET_STA; 00126 00127 // Wait for complete 00128 while (!(I2Cx->I2CONSET & I2C_I2CONSET_SI)); 00129 I2Cx->I2CONCLR = I2C_I2CONCLR_STAC; 00130 return (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK); 00131 } 00132 00133 /********************************************************************//** 00134 * @brief Generate a stop condition on I2C bus (in master mode only) 00135 * @param[in] I2Cx: I2C peripheral selected, should be: 00136 * - LPC_I2C0 00137 * - LPC_I2C1 00138 * - LPC_I2C2 00139 * @return None 00140 *********************************************************************/ 00141 static void I2C_Stop (LPC_I2C_TypeDef *I2Cx) 00142 { 00143 00144 /* Make sure start bit is not active */ 00145 if (I2Cx->I2CONSET & I2C_I2CONSET_STA) 00146 { 00147 I2Cx->I2CONCLR = I2C_I2CONCLR_STAC; 00148 } 00149 I2Cx->I2CONSET = I2C_I2CONSET_STO; 00150 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00151 } 00152 00153 /********************************************************************//** 00154 * @brief Send a byte 00155 * @param[in] I2Cx: I2C peripheral selected, should be: 00156 * - LPC_I2C0 00157 * - LPC_I2C1 00158 * - LPC_I2C2 00159 * @param[in] databyte: number of byte 00160 * @return value of I2C status register after sending 00161 *********************************************************************/ 00162 static uint32_t I2C_SendByte (LPC_I2C_TypeDef *I2Cx, uint8_t databyte) 00163 { 00164 /* Make sure start bit is not active */ 00165 if (I2Cx->I2CONSET & I2C_I2CONSET_STA) 00166 { 00167 I2Cx->I2CONCLR = I2C_I2CONCLR_STAC; 00168 } 00169 I2Cx->I2DAT = databyte & I2C_I2DAT_BITMASK; 00170 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00171 00172 while (!(I2Cx->I2CONSET & I2C_I2CONSET_SI)); 00173 return (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK); 00174 } 00175 00176 /********************************************************************//** 00177 * @brief Get a byte 00178 * @param[in] I2Cx: I2C peripheral selected, should be: 00179 * - LPC_I2C0 00180 * - LPC_I2C1 00181 * - LPC_I2C2 00182 * @param[out] retdat pointer to return data 00183 * @param[in] ack assert acknowledge or not, should be: TRUE/FALSE 00184 * @return value of I2C status register after sending 00185 *********************************************************************/ 00186 static uint32_t I2C_GetByte (LPC_I2C_TypeDef *I2Cx, uint8_t *retdat, Bool ack) 00187 { 00188 if (ack == TRUE) 00189 { 00190 I2Cx->I2CONSET = I2C_I2CONSET_AA; 00191 } 00192 else 00193 { 00194 I2Cx->I2CONCLR = I2C_I2CONCLR_AAC; 00195 } 00196 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00197 00198 while (!(I2Cx->I2CONSET & I2C_I2CONSET_SI)); 00199 *retdat = (uint8_t) (I2Cx->I2DAT & I2C_I2DAT_BITMASK); 00200 return (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK); 00201 } 00202 00203 /*********************************************************************//** 00204 * @brief Setup clock rate for I2C peripheral 00205 * @param[in] I2Cx I2C peripheral selected, should be: 00206 * - LPC_I2C0 00207 * - LPC_I2C1 00208 * - LPC_I2C2 00209 * @param[in] target_clock : clock of SSP (Hz) 00210 * @return None 00211 ***********************************************************************/ 00212 static void I2C_SetClock (LPC_I2C_TypeDef *I2Cx, uint32_t target_clock) 00213 { 00214 volatile uint32_t temp = 0; 00215 00216 CHECK_PARAM(PARAM_I2Cx(I2Cx)); 00217 00218 // Get PCLK of I2C controller 00219 if (I2Cx == LPC_I2C0) 00220 { 00221 temp = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_I2C0) / target_clock; 00222 } 00223 else if (I2Cx == LPC_I2C1) 00224 { 00225 temp = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_I2C1) / target_clock; 00226 } 00227 else if (I2Cx == LPC_I2C2) 00228 { 00229 temp = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_I2C2) / target_clock; 00230 } 00231 00232 /* Set the I2C clock value to register */ 00233 I2Cx->I2SCLH = (uint32_t)(temp / 2); 00234 I2Cx->I2SCLL = (uint32_t)(temp - I2Cx->I2SCLH); 00235 } 00236 /* End of Private Functions --------------------------------------------------- */ 00237 00238 00239 /* Public Functions ----------------------------------------------------------- */ 00240 /** @addtogroup I2C_Public_Functions 00241 * @{ 00242 */ 00243 00244 /********************************************************************//** 00245 * @brief Initializes the I2Cx peripheral with specified parameter. 00246 * @param[in] I2Cx I2C peripheral selected, should be 00247 * - LPC_I2C0 00248 * - LPC_I2C1 00249 * - LPC_I2C2 00250 * @param[in] clockrate Target clock rate value to initialized I2C 00251 * peripheral (Hz) 00252 * @return None 00253 *********************************************************************/ 00254 void I2C_Init(LPC_I2C_TypeDef *I2Cx, uint32_t clockrate) 00255 { 00256 CHECK_PARAM(PARAM_I2Cx(I2Cx)); 00257 00258 if (I2Cx==LPC_I2C0) 00259 { 00260 /* Set up clock and power for I2C0 module */ 00261 CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCI2C0, ENABLE); 00262 /* As default, peripheral clock for I2C0 module 00263 * is set to FCCLK / 2 */ 00264 CLKPWR_SetPCLKDiv(CLKPWR_PCLKSEL_I2C0, CLKPWR_PCLKSEL_CCLK_DIV_2); 00265 } 00266 else if (I2Cx==LPC_I2C1) 00267 { 00268 /* Set up clock and power for I2C1 module */ 00269 CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCI2C1, ENABLE); 00270 /* As default, peripheral clock for I2C1 module 00271 * is set to FCCLK / 2 */ 00272 CLKPWR_SetPCLKDiv(CLKPWR_PCLKSEL_I2C1, CLKPWR_PCLKSEL_CCLK_DIV_2); 00273 } 00274 else if (I2Cx==LPC_I2C2) 00275 { 00276 /* Set up clock and power for I2C2 module */ 00277 CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCI2C2, ENABLE); 00278 /* As default, peripheral clock for I2C2 module 00279 * is set to FCCLK / 2 */ 00280 CLKPWR_SetPCLKDiv(CLKPWR_PCLKSEL_I2C2, CLKPWR_PCLKSEL_CCLK_DIV_2); 00281 } 00282 else { 00283 // Up-Support this device 00284 return; 00285 } 00286 00287 /* Set clock rate */ 00288 I2C_SetClock(I2Cx, clockrate); 00289 /* Set I2C operation to default */ 00290 I2Cx->I2CONCLR = (I2C_I2CONCLR_AAC | I2C_I2CONCLR_STAC | I2C_I2CONCLR_I2ENC); 00291 } 00292 00293 /*********************************************************************//** 00294 * @brief De-initializes the I2C peripheral registers to their 00295 * default reset values. 00296 * @param[in] I2Cx I2C peripheral selected, should be 00297 * - LPC_I2C0 00298 * - LPC_I2C1 00299 * - LPC_I2C2 00300 * @return None 00301 **********************************************************************/ 00302 void I2C_DeInit(LPC_I2C_TypeDef* I2Cx) 00303 { 00304 CHECK_PARAM(PARAM_I2Cx(I2Cx)); 00305 00306 /* Disable I2C control */ 00307 I2Cx->I2CONCLR = I2C_I2CONCLR_I2ENC; 00308 00309 if (I2Cx==LPC_I2C0) 00310 { 00311 /* Disable power for I2C0 module */ 00312 CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCI2C0, DISABLE); 00313 } 00314 else if (I2Cx==LPC_I2C1) 00315 { 00316 /* Disable power for I2C1 module */ 00317 CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCI2C1, DISABLE); 00318 } 00319 else if (I2Cx==LPC_I2C2) 00320 { 00321 /* Disable power for I2C2 module */ 00322 CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCI2C2, DISABLE); 00323 } 00324 } 00325 00326 /*********************************************************************//** 00327 * @brief Enable or disable I2C peripheral's operation 00328 * @param[in] I2Cx I2C peripheral selected, should be 00329 * - LPC_I2C0 00330 * - LPC_I2C1 00331 * - LPC_I2C2 00332 * @param[in] NewState New State of I2Cx peripheral's operation 00333 * @return none 00334 **********************************************************************/ 00335 void I2C_Cmd(LPC_I2C_TypeDef* I2Cx, FunctionalState NewState) 00336 { 00337 CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState)); 00338 CHECK_PARAM(PARAM_I2Cx(I2Cx)); 00339 00340 if (NewState == ENABLE) 00341 { 00342 I2Cx->I2CONSET = I2C_I2CONSET_I2EN; 00343 } 00344 else 00345 { 00346 I2Cx->I2CONCLR = I2C_I2CONCLR_I2ENC; 00347 } 00348 } 00349 00350 /*********************************************************************//** 00351 * @brief Enable/Disable interrupt for I2C peripheral 00352 * @param[in] I2Cx I2C peripheral selected, should be: 00353 * - LPC_I2C0 00354 * - LPC_I2C1 00355 * - LPC_I2C2 00356 * @param[in] NewState New State of I2C peripheral interrupt in NVIC core 00357 * should be: 00358 * - ENABLE: enable interrupt for this I2C peripheral 00359 * - DISABLE: disable interrupt for this I2C peripheral 00360 * @return None 00361 **********************************************************************/ 00362 void I2C_IntCmd (LPC_I2C_TypeDef *I2Cx, Bool NewState) 00363 { 00364 if (NewState) 00365 { 00366 if(I2Cx == LPC_I2C0) 00367 { 00368 NVIC_EnableIRQ(I2C0_IRQn); 00369 } 00370 else if (I2Cx == LPC_I2C1) 00371 { 00372 NVIC_EnableIRQ(I2C1_IRQn); 00373 } 00374 else if (I2Cx == LPC_I2C2) 00375 { 00376 NVIC_EnableIRQ(I2C2_IRQn); 00377 } 00378 } 00379 else 00380 { 00381 if(I2Cx == LPC_I2C0) 00382 { 00383 NVIC_DisableIRQ(I2C0_IRQn); 00384 } 00385 else if (I2Cx == LPC_I2C1) 00386 { 00387 NVIC_DisableIRQ(I2C1_IRQn); 00388 } 00389 else if (I2Cx == LPC_I2C2) 00390 { 00391 NVIC_DisableIRQ(I2C2_IRQn); 00392 } 00393 } 00394 return; 00395 } 00396 00397 00398 /*********************************************************************//** 00399 * @brief General Master Interrupt handler for I2C peripheral 00400 * @param[in] I2Cx I2C peripheral selected, should be: 00401 * - LPC_I2C 00402 * - LPC_I2C1 00403 * - LPC_I2C2 00404 * @return None 00405 **********************************************************************/ 00406 void I2C_MasterHandler (LPC_I2C_TypeDef *I2Cx) 00407 { 00408 int32_t tmp; 00409 uint8_t returnCode; 00410 I2C_M_SETUP_Type *txrx_setup; 00411 00412 tmp = I2C_getNum(I2Cx); 00413 txrx_setup = (I2C_M_SETUP_Type *) i2cdat[tmp].txrx_setup; 00414 00415 returnCode = (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK); 00416 // Save current status 00417 txrx_setup->status = returnCode; 00418 // there's no relevant information 00419 if (returnCode == I2C_I2STAT_NO_INF){ 00420 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00421 return; 00422 } 00423 00424 /* ----------------------------- TRANSMIT PHASE --------------------------*/ 00425 if (i2cdat[tmp].dir == 0){ 00426 switch (returnCode) 00427 { 00428 /* A start/repeat start condition has been transmitted -------------------*/ 00429 case I2C_I2STAT_M_TX_START: 00430 case I2C_I2STAT_M_TX_RESTART: 00431 I2Cx->I2CONCLR = I2C_I2CONCLR_STAC; 00432 /* 00433 * If there's any transmit data, then start to 00434 * send SLA+W right now, otherwise check whether if there's 00435 * any receive data for next state. 00436 */ 00437 if ((txrx_setup->tx_data != NULL) && (txrx_setup->tx_length != 0)){ 00438 I2Cx->I2DAT = (txrx_setup->sl_addr7bit << 1); 00439 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00440 } else { 00441 goto next_stage; 00442 } 00443 break; 00444 00445 /* SLA+W has been transmitted, ACK has been received ----------------------*/ 00446 case I2C_I2STAT_M_TX_SLAW_ACK: 00447 /* Data has been transmitted, ACK has been received */ 00448 case I2C_I2STAT_M_TX_DAT_ACK: 00449 /* Send more data */ 00450 if ((txrx_setup->tx_count < txrx_setup->tx_length) \ 00451 && (txrx_setup->tx_data != NULL)){ 00452 I2Cx->I2DAT = *(uint8_t *)(txrx_setup->tx_data + txrx_setup->tx_count); 00453 txrx_setup->tx_count++; 00454 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00455 } 00456 // no more data, switch to next stage 00457 else { 00458 next_stage: 00459 // change direction 00460 i2cdat[tmp].dir = 1; 00461 // Check if any data to receive 00462 if ((txrx_setup->rx_length != 0) && (txrx_setup->rx_data != NULL)){ 00463 // check whether if we need to issue an repeat start 00464 if ((txrx_setup->tx_length != 0) && (txrx_setup->tx_data != NULL)){ 00465 // Send out an repeat start command 00466 I2Cx->I2CONSET = I2C_I2CONSET_STA; 00467 I2Cx->I2CONCLR = I2C_I2CONCLR_AAC | I2C_I2CONCLR_SIC; 00468 } 00469 // Don't need issue an repeat start, just goto send SLA+R 00470 else { 00471 goto send_slar; 00472 } 00473 } 00474 // no more data send, the go to end stage now 00475 else { 00476 // success, goto end stage 00477 txrx_setup->status |= I2C_SETUP_STATUS_DONE; 00478 goto end_stage; 00479 } 00480 } 00481 break; 00482 00483 /* SLA+W has been transmitted, NACK has been received ----------------------*/ 00484 case I2C_I2STAT_M_TX_SLAW_NACK: 00485 /* Data has been transmitted, NACK has been received -----------------------*/ 00486 case I2C_I2STAT_M_TX_DAT_NACK: 00487 // update status 00488 txrx_setup->status |= I2C_SETUP_STATUS_NOACKF; 00489 goto retry; 00490 /* Arbitration lost in SLA+R/W or Data bytes -------------------------------*/ 00491 case I2C_I2STAT_M_TX_ARB_LOST: 00492 // update status 00493 txrx_setup->status |= I2C_SETUP_STATUS_ARBF; 00494 default: 00495 goto retry; 00496 } 00497 } 00498 00499 /* ----------------------------- RECEIVE PHASE --------------------------*/ 00500 else if (i2cdat[tmp].dir == 1){ 00501 switch (returnCode){ 00502 /* A start/repeat start condition has been transmitted ---------------------*/ 00503 case I2C_I2STAT_M_RX_START: 00504 case I2C_I2STAT_M_RX_RESTART: 00505 I2Cx->I2CONCLR = I2C_I2CONCLR_STAC; 00506 /* 00507 * If there's any receive data, then start to 00508 * send SLA+R right now, otherwise check whether if there's 00509 * any receive data for end of state. 00510 */ 00511 if ((txrx_setup->rx_data != NULL) && (txrx_setup->rx_length != 0)){ 00512 send_slar: 00513 I2Cx->I2DAT = (txrx_setup->sl_addr7bit << 1) | 0x01; 00514 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00515 } else { 00516 // Success, goto end stage 00517 txrx_setup->status |= I2C_SETUP_STATUS_DONE; 00518 goto end_stage; 00519 } 00520 break; 00521 00522 /* SLA+R has been transmitted, ACK has been received -----------------*/ 00523 case I2C_I2STAT_M_RX_SLAR_ACK: 00524 if (txrx_setup->rx_count < (txrx_setup->rx_length - 1)) { 00525 /*Data will be received, ACK will be return*/ 00526 I2Cx->I2CONSET = I2C_I2CONSET_AA; 00527 } 00528 else { 00529 /*Last data will be received, NACK will be return*/ 00530 I2Cx->I2CONCLR = I2C_I2CONSET_AA; 00531 } 00532 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00533 break; 00534 00535 /* Data has been received, ACK has been returned ----------------------*/ 00536 case I2C_I2STAT_M_RX_DAT_ACK: 00537 // Note save data and increase counter first, then check later 00538 /* Save data */ 00539 if ((txrx_setup->rx_data != NULL) && (txrx_setup->rx_count < txrx_setup->rx_length)){ 00540 *(uint8_t *)(txrx_setup->rx_data + txrx_setup->rx_count) = (I2Cx->I2DAT & I2C_I2DAT_BITMASK); 00541 txrx_setup->rx_count++; 00542 } 00543 if (txrx_setup->rx_count < (txrx_setup->rx_length - 1)) { 00544 /*Data will be received, ACK will be return*/ 00545 I2Cx->I2CONSET = I2C_I2CONSET_AA; 00546 } 00547 else { 00548 /*Last data will be received, NACK will be return*/ 00549 I2Cx->I2CONCLR = I2C_I2CONSET_AA; 00550 } 00551 00552 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00553 break; 00554 00555 /* Data has been received, NACK has been return -------------------------*/ 00556 case I2C_I2STAT_M_RX_DAT_NACK: 00557 /* Save the last data */ 00558 if ((txrx_setup->rx_data != NULL) && (txrx_setup->rx_count < txrx_setup->rx_length)){ 00559 *(uint8_t *)(txrx_setup->rx_data + txrx_setup->rx_count) = (I2Cx->I2DAT & I2C_I2DAT_BITMASK); 00560 txrx_setup->rx_count++; 00561 } 00562 // success, go to end stage 00563 txrx_setup->status |= I2C_SETUP_STATUS_DONE; 00564 goto end_stage; 00565 00566 /* SLA+R has been transmitted, NACK has been received ------------------*/ 00567 case I2C_I2STAT_M_RX_SLAR_NACK: 00568 // update status 00569 txrx_setup->status |= I2C_SETUP_STATUS_NOACKF; 00570 goto retry; 00571 00572 /* Arbitration lost ----------------------------------------------------*/ 00573 case I2C_I2STAT_M_RX_ARB_LOST: 00574 // update status 00575 txrx_setup->status |= I2C_SETUP_STATUS_ARBF; 00576 default: 00577 retry: 00578 // check if retransmission is available 00579 if (txrx_setup->retransmissions_count < txrx_setup->retransmissions_max){ 00580 // Clear tx count 00581 txrx_setup->tx_count = 0; 00582 I2Cx->I2CONSET = I2C_I2CONSET_STA; 00583 I2Cx->I2CONCLR = I2C_I2CONCLR_AAC | I2C_I2CONCLR_SIC; 00584 txrx_setup->retransmissions_count++; 00585 } 00586 // End of stage 00587 else { 00588 end_stage: 00589 // Disable interrupt 00590 I2C_IntCmd(I2Cx, FALSE); 00591 // Send stop 00592 I2C_Stop(I2Cx); 00593 00594 I2C_MasterComplete[tmp] = TRUE; 00595 } 00596 break; 00597 } 00598 } 00599 } 00600 00601 00602 /*********************************************************************//** 00603 * @brief General Slave Interrupt handler for I2C peripheral 00604 * @param[in] I2Cx I2C peripheral selected, should be: 00605 * - LPC_I2C0 00606 * - LPC_I2C1 00607 * - LPC_I2C2 00608 * @return None 00609 **********************************************************************/ 00610 void I2C_SlaveHandler (LPC_I2C_TypeDef *I2Cx) 00611 { 00612 int32_t tmp; 00613 uint8_t returnCode; 00614 I2C_S_SETUP_Type *txrx_setup; 00615 uint32_t timeout; 00616 00617 tmp = I2C_getNum(I2Cx); 00618 txrx_setup = (I2C_S_SETUP_Type *) i2cdat[tmp].txrx_setup; 00619 00620 returnCode = (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK); 00621 // Save current status 00622 txrx_setup->status = returnCode; 00623 // there's no relevant information 00624 if (returnCode == I2C_I2STAT_NO_INF){ 00625 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00626 return; 00627 } 00628 00629 00630 switch (returnCode) 00631 { 00632 00633 /* No status information */ 00634 case I2C_I2STAT_NO_INF: 00635 I2Cx->I2CONSET = I2C_I2CONSET_AA; 00636 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00637 break; 00638 00639 /* Reading phase -------------------------------------------------------- */ 00640 /* Own SLA+R has been received, ACK has been returned */ 00641 case I2C_I2STAT_S_RX_SLAW_ACK: 00642 /* General call address has been received, ACK has been returned */ 00643 case I2C_I2STAT_S_RX_GENCALL_ACK: 00644 I2Cx->I2CONSET = I2C_I2CONSET_AA; 00645 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00646 break; 00647 00648 /* Previously addressed with own SLA; 00649 * DATA byte has been received; 00650 * ACK has been returned */ 00651 case I2C_I2STAT_S_RX_PRE_SLA_DAT_ACK: 00652 /* DATA has been received, ACK hasn been return */ 00653 case I2C_I2STAT_S_RX_PRE_GENCALL_DAT_ACK: 00654 /* 00655 * All data bytes that over-flow the specified receive 00656 * data length, just ignore them. 00657 */ 00658 if ((txrx_setup->rx_count < txrx_setup->rx_length) \ 00659 && (txrx_setup->rx_data != NULL)){ 00660 *(uint8_t *)(txrx_setup->rx_data + txrx_setup->rx_count) = (uint8_t)I2Cx->I2DAT; 00661 txrx_setup->rx_count++; 00662 } 00663 I2Cx->I2CONSET = I2C_I2CONSET_AA; 00664 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00665 break; 00666 00667 /* Previously addressed with own SLA; 00668 * DATA byte has been received; 00669 * NOT ACK has been returned */ 00670 case I2C_I2STAT_S_RX_PRE_SLA_DAT_NACK: 00671 /* DATA has been received, NOT ACK has been returned */ 00672 case I2C_I2STAT_S_RX_PRE_GENCALL_DAT_NACK: 00673 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00674 break; 00675 00676 /* 00677 * Note that: Return code only let us know a stop condition mixed 00678 * with a repeat start condition in the same code value. 00679 * So we should provide a time-out. In case this is really a stop 00680 * condition, this will return back after time out condition. Otherwise, 00681 * next session that is slave receive data will be completed. 00682 */ 00683 00684 /* A Stop or a repeat start condition */ 00685 case I2C_I2STAT_S_RX_STA_STO_SLVREC_SLVTRX: 00686 // Temporally lock the interrupt for timeout condition 00687 I2C_IntCmd(I2Cx, FALSE); 00688 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00689 // enable time out 00690 timeout = I2C_SLAVE_TIME_OUT; 00691 while(1){ 00692 if (I2Cx->I2CONSET & I2C_I2CONSET_SI){ 00693 // re-Enable interrupt 00694 I2C_IntCmd(I2Cx, TRUE); 00695 break; 00696 } else { 00697 timeout--; 00698 if (timeout == 0){ 00699 // timeout occur, it's really a stop condition 00700 txrx_setup->status |= I2C_SETUP_STATUS_DONE; 00701 goto s_int_end; 00702 } 00703 } 00704 } 00705 break; 00706 00707 /* Writing phase -------------------------------------------------------- */ 00708 /* Own SLA+R has been received, ACK has been returned */ 00709 case I2C_I2STAT_S_TX_SLAR_ACK: 00710 /* Data has been transmitted, ACK has been received */ 00711 case I2C_I2STAT_S_TX_DAT_ACK: 00712 /* 00713 * All data bytes that over-flow the specified receive 00714 * data length, just ignore them. 00715 */ 00716 if ((txrx_setup->tx_count < txrx_setup->tx_length) \ 00717 && (txrx_setup->tx_data != NULL)){ 00718 I2Cx->I2DAT = *(uint8_t *) (txrx_setup->tx_data + txrx_setup->tx_count); 00719 txrx_setup->tx_count++; 00720 } 00721 I2Cx->I2CONSET = I2C_I2CONSET_AA; 00722 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00723 break; 00724 00725 /* Data has been transmitted, NACK has been received, 00726 * that means there's no more data to send, exit now */ 00727 /* 00728 * Note: Don't wait for stop event since in slave transmit mode, 00729 * since there no proof lets us know when a stop signal has been received 00730 * on slave side. 00731 */ 00732 case I2C_I2STAT_S_TX_DAT_NACK: 00733 I2Cx->I2CONSET = I2C_I2CONSET_AA; 00734 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00735 txrx_setup->status |= I2C_SETUP_STATUS_DONE; 00736 goto s_int_end; 00737 00738 // Other status must be captured 00739 default: 00740 s_int_end: 00741 // Disable interrupt 00742 I2C_IntCmd(I2Cx, FALSE); 00743 I2Cx->I2CONCLR = I2C_I2CONCLR_AAC | I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC; 00744 I2C_SlaveComplete[tmp] = TRUE; 00745 break; 00746 } 00747 } 00748 00749 /*********************************************************************//** 00750 * @brief Transmit and Receive data in master mode 00751 * @param[in] I2Cx I2C peripheral selected, should be: 00752 * - LPC_I2C0 00753 * - LPC_I2C1 00754 * - LPC_I2C2 00755 * @param[in] TransferCfg Pointer to a I2C_M_SETUP_Type structure that 00756 * contains specified information about the 00757 * configuration for master transfer. 00758 * @param[in] Opt a I2C_TRANSFER_OPT_Type type that selected for 00759 * interrupt or polling mode. 00760 * @return SUCCESS or ERROR 00761 * 00762 * Note: 00763 * - In case of using I2C to transmit data only, either transmit length set to 0 00764 * or transmit data pointer set to NULL. 00765 * - In case of using I2C to receive data only, either receive length set to 0 00766 * or receive data pointer set to NULL. 00767 * - In case of using I2C to transmit followed by receive data, transmit length, 00768 * transmit data pointer, receive length and receive data pointer should be set 00769 * corresponding. 00770 **********************************************************************/ 00771 Status I2C_MasterTransferData(LPC_I2C_TypeDef *I2Cx, I2C_M_SETUP_Type *TransferCfg, \ 00772 I2C_TRANSFER_OPT_Type Opt) 00773 { 00774 uint8_t *txdat; 00775 uint8_t *rxdat; 00776 uint32_t CodeStatus; 00777 uint8_t tmp; 00778 00779 // reset all default state 00780 txdat = (uint8_t *) TransferCfg->tx_data; 00781 rxdat = (uint8_t *) TransferCfg->rx_data; 00782 // Reset I2C setup value to default state 00783 TransferCfg->tx_count = 0; 00784 TransferCfg->rx_count = 0; 00785 TransferCfg->status = 0; 00786 00787 if (Opt == I2C_TRANSFER_POLLING){ 00788 00789 /* First Start condition -------------------------------------------------------------- */ 00790 TransferCfg->retransmissions_count = 0; 00791 retry: 00792 // reset all default state 00793 txdat = (uint8_t *) TransferCfg->tx_data; 00794 rxdat = (uint8_t *) TransferCfg->rx_data; 00795 // Reset I2C setup value to default state 00796 TransferCfg->tx_count = 0; 00797 TransferCfg->rx_count = 0; 00798 CodeStatus = 0; 00799 00800 // Start command 00801 CodeStatus = I2C_Start(I2Cx); 00802 if ((CodeStatus != I2C_I2STAT_M_TX_START) \ 00803 && (CodeStatus != I2C_I2STAT_M_TX_RESTART)){ 00804 TransferCfg->retransmissions_count++; 00805 if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){ 00806 // save status 00807 TransferCfg->status = CodeStatus; 00808 goto error; 00809 } else { 00810 goto retry; 00811 } 00812 } 00813 00814 /* In case of sending data first --------------------------------------------------- */ 00815 if ((TransferCfg->tx_length != 0) && (TransferCfg->tx_data != NULL)){ 00816 00817 /* Send slave address + WR direction bit = 0 ----------------------------------- */ 00818 CodeStatus = I2C_SendByte(I2Cx, (TransferCfg->sl_addr7bit << 1)); 00819 if (CodeStatus != I2C_I2STAT_M_TX_SLAW_ACK){ 00820 TransferCfg->retransmissions_count++; 00821 if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){ 00822 // save status 00823 TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_NOACKF; 00824 goto error; 00825 } else { 00826 goto retry; 00827 } 00828 } 00829 00830 /* Send a number of data bytes ---------------------------------------- */ 00831 while (TransferCfg->tx_count < TransferCfg->tx_length) 00832 { 00833 CodeStatus = I2C_SendByte(I2Cx, *txdat); 00834 if (CodeStatus != I2C_I2STAT_M_TX_DAT_ACK){ 00835 TransferCfg->retransmissions_count++; 00836 if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){ 00837 // save status 00838 TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_NOACKF; 00839 goto error; 00840 } else { 00841 goto retry; 00842 } 00843 } 00844 00845 txdat++; 00846 TransferCfg->tx_count++; 00847 } 00848 } 00849 00850 /* Second Start condition (Repeat Start) ------------------------------------------- */ 00851 if ((TransferCfg->tx_length != 0) && (TransferCfg->tx_data != NULL) \ 00852 && (TransferCfg->rx_length != 0) && (TransferCfg->rx_data != NULL)){ 00853 00854 CodeStatus = I2C_Start(I2Cx); 00855 if ((CodeStatus != I2C_I2STAT_M_RX_START) \ 00856 && (CodeStatus != I2C_I2STAT_M_RX_RESTART)){ 00857 TransferCfg->retransmissions_count++; 00858 if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){ 00859 // Update status 00860 TransferCfg->status = CodeStatus; 00861 goto error; 00862 } else { 00863 goto retry; 00864 } 00865 } 00866 } 00867 00868 /* Then, start reading after sending data -------------------------------------- */ 00869 if ((TransferCfg->rx_length != 0) && (TransferCfg->rx_data != NULL)){ 00870 /* Send slave address + RD direction bit = 1 ----------------------------------- */ 00871 00872 CodeStatus = I2C_SendByte(I2Cx, ((TransferCfg->sl_addr7bit << 1) | 0x01)); 00873 if (CodeStatus != I2C_I2STAT_M_RX_SLAR_ACK){ 00874 TransferCfg->retransmissions_count++; 00875 if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){ 00876 // update status 00877 TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_NOACKF; 00878 goto error; 00879 } else { 00880 goto retry; 00881 } 00882 } 00883 00884 /* Receive a number of data bytes ------------------------------------------------- */ 00885 while (TransferCfg->rx_count < TransferCfg->rx_length){ 00886 00887 /* 00888 * Note that: if data length is only one, the master should not 00889 * issue an ACK signal on bus after reading to avoid of next data frame 00890 * on slave side 00891 */ 00892 if (TransferCfg->rx_count < (TransferCfg->rx_length - 1)){ 00893 // Issue an ACK signal for next data frame 00894 CodeStatus = I2C_GetByte(I2Cx, &tmp, TRUE); 00895 if (CodeStatus != I2C_I2STAT_M_RX_DAT_ACK){ 00896 TransferCfg->retransmissions_count++; 00897 if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){ 00898 // update status 00899 TransferCfg->status = CodeStatus; 00900 goto error; 00901 } else { 00902 goto retry; 00903 } 00904 } 00905 } else { 00906 // Do not issue an ACK signal 00907 CodeStatus = I2C_GetByte(I2Cx, &tmp, FALSE); 00908 if (CodeStatus != I2C_I2STAT_M_RX_DAT_NACK){ 00909 TransferCfg->retransmissions_count++; 00910 if (TransferCfg->retransmissions_count > TransferCfg->retransmissions_max){ 00911 // update status 00912 TransferCfg->status = CodeStatus; 00913 goto error; 00914 } else { 00915 goto retry; 00916 } 00917 } 00918 } 00919 *rxdat++ = tmp; 00920 TransferCfg->rx_count++; 00921 } 00922 } 00923 00924 /* Send STOP condition ------------------------------------------------- */ 00925 I2C_Stop(I2Cx); 00926 return SUCCESS; 00927 00928 error: 00929 // Send stop condition 00930 I2C_Stop(I2Cx); 00931 return ERROR; 00932 } 00933 00934 else if (Opt == I2C_TRANSFER_INTERRUPT){ 00935 // Setup tx_rx data, callback and interrupt handler 00936 tmp = I2C_getNum(I2Cx); 00937 i2cdat[tmp].txrx_setup = (uint32_t) TransferCfg; 00938 // Set direction phase, write first 00939 i2cdat[tmp].dir = 0; 00940 00941 /* First Start condition -------------------------------------------------------------- */ 00942 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 00943 I2Cx->I2CONSET = I2C_I2CONSET_STA; 00944 I2C_IntCmd(I2Cx, TRUE); 00945 00946 return (SUCCESS); 00947 } 00948 00949 return ERROR; 00950 } 00951 00952 /*********************************************************************//** 00953 * @brief Receive and Transmit data in slave mode 00954 * @param[in] I2Cx I2C peripheral selected, should be 00955 * - LPC_I2C0 00956 * - LPC_I2C1 00957 * - LPC_I2C2 00958 * @param[in] TransferCfg Pointer to a I2C_S_SETUP_Type structure that 00959 * contains specified information about the 00960 * configuration for master transfer. 00961 * @param[in] Opt I2C_TRANSFER_OPT_Type type that selected for 00962 * interrupt or polling mode. 00963 * @return SUCCESS or ERROR 00964 * 00965 * Note: 00966 * The mode of slave's operation depends on the command sent from master on 00967 * the I2C bus. If the master send a SLA+W command, this sub-routine will 00968 * use receive data length and receive data pointer. If the master send a SLA+R 00969 * command, this sub-routine will use transmit data length and transmit data 00970 * pointer. 00971 * If the master issue an repeat start command or a stop command, the slave will 00972 * enable an time out condition, during time out condition, if there's no activity 00973 * on I2C bus, the slave will exit, otherwise (i.e. the master send a SLA+R/W), 00974 * the slave then switch to relevant operation mode. The time out should be used 00975 * because the return status code can not show difference from stop and repeat 00976 * start command in slave operation. 00977 * In case of the expected data length from master is greater than data length 00978 * that slave can support: 00979 * - In case of reading operation (from master): slave will return I2C_I2DAT_IDLE_CHAR 00980 * value. 00981 * - In case of writing operation (from master): slave will ignore remain data from master. 00982 **********************************************************************/ 00983 Status I2C_SlaveTransferData(LPC_I2C_TypeDef *I2Cx, I2C_S_SETUP_Type *TransferCfg, \ 00984 I2C_TRANSFER_OPT_Type Opt) 00985 { 00986 uint8_t *txdat; 00987 uint8_t *rxdat; 00988 volatile uint32_t CodeStatus = 0; 00989 uint32_t timeout; 00990 int32_t time_en; 00991 int32_t tmp; 00992 00993 // reset all default state 00994 txdat = (uint8_t *) TransferCfg->tx_data; 00995 rxdat = (uint8_t *) TransferCfg->rx_data; 00996 // Reset I2C setup value to default state 00997 TransferCfg->tx_count = 0; 00998 TransferCfg->rx_count = 0; 00999 TransferCfg->status = 0; 01000 01001 01002 // Polling option 01003 if (Opt == I2C_TRANSFER_POLLING){ 01004 01005 /* Set AA bit to ACK command on I2C bus */ 01006 I2Cx->I2CONSET = I2C_I2CONSET_AA; 01007 /* Clear SI bit to be ready ... */ 01008 I2Cx->I2CONCLR = (I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC); 01009 01010 time_en = 0; 01011 timeout = 0; 01012 01013 while (1) 01014 { 01015 /* Check SI flag ready */ 01016 if (I2Cx->I2CONSET & I2C_I2CONSET_SI) 01017 { 01018 time_en = 0; 01019 01020 switch (CodeStatus = (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK)) 01021 { 01022 01023 /* No status information */ 01024 case I2C_I2STAT_NO_INF: 01025 I2Cx->I2CONSET = I2C_I2CONSET_AA; 01026 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 01027 break; 01028 01029 /* Reading phase -------------------------------------------------------- */ 01030 /* Own SLA+R has been received, ACK has been returned */ 01031 case I2C_I2STAT_S_RX_SLAW_ACK: 01032 /* General call address has been received, ACK has been returned */ 01033 case I2C_I2STAT_S_RX_GENCALL_ACK: 01034 I2Cx->I2CONSET = I2C_I2CONSET_AA; 01035 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 01036 break; 01037 01038 /* Previously addressed with own SLA; 01039 * DATA byte has been received; 01040 * ACK has been returned */ 01041 case I2C_I2STAT_S_RX_PRE_SLA_DAT_ACK: 01042 /* DATA has been received, ACK hasn been return */ 01043 case I2C_I2STAT_S_RX_PRE_GENCALL_DAT_ACK: 01044 /* 01045 * All data bytes that over-flow the specified receive 01046 * data length, just ignore them. 01047 */ 01048 if ((TransferCfg->rx_count < TransferCfg->rx_length) \ 01049 && (TransferCfg->rx_data != NULL)){ 01050 *rxdat++ = (uint8_t)I2Cx->I2DAT; 01051 TransferCfg->rx_count++; 01052 } 01053 I2Cx->I2CONSET = I2C_I2CONSET_AA; 01054 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 01055 break; 01056 01057 /* Previously addressed with own SLA; 01058 * DATA byte has been received; 01059 * NOT ACK has been returned */ 01060 case I2C_I2STAT_S_RX_PRE_SLA_DAT_NACK: 01061 /* DATA has been received, NOT ACK has been returned */ 01062 case I2C_I2STAT_S_RX_PRE_GENCALL_DAT_NACK: 01063 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 01064 break; 01065 01066 /* 01067 * Note that: Return code only let us know a stop condition mixed 01068 * with a repeat start condition in the same code value. 01069 * So we should provide a time-out. In case this is really a stop 01070 * condition, this will return back after time out condition. Otherwise, 01071 * next session that is slave receive data will be completed. 01072 */ 01073 01074 /* A Stop or a repeat start condition */ 01075 case I2C_I2STAT_S_RX_STA_STO_SLVREC_SLVTRX: 01076 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 01077 // enable time out 01078 time_en = 1; 01079 timeout = 0; 01080 break; 01081 01082 /* Writing phase -------------------------------------------------------- */ 01083 /* Own SLA+R has been received, ACK has been returned */ 01084 case I2C_I2STAT_S_TX_SLAR_ACK: 01085 /* Data has been transmitted, ACK has been received */ 01086 case I2C_I2STAT_S_TX_DAT_ACK: 01087 /* 01088 * All data bytes that over-flow the specified receive 01089 * data length, just ignore them. 01090 */ 01091 if ((TransferCfg->tx_count < TransferCfg->tx_length) \ 01092 && (TransferCfg->tx_data != NULL)){ 01093 I2Cx->I2DAT = *txdat++; 01094 TransferCfg->tx_count++; 01095 } 01096 I2Cx->I2CONSET = I2C_I2CONSET_AA; 01097 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 01098 break; 01099 01100 /* Data has been transmitted, NACK has been received, 01101 * that means there's no more data to send, exit now */ 01102 /* 01103 * Note: Don't wait for stop event since in slave transmit mode, 01104 * since there no proof lets us know when a stop signal has been received 01105 * on slave side. 01106 */ 01107 case I2C_I2STAT_S_TX_DAT_NACK: 01108 I2Cx->I2CONSET = I2C_I2CONSET_AA; 01109 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 01110 // enable time out 01111 time_en = 1; 01112 timeout = 0; 01113 break; 01114 01115 // Other status must be captured 01116 default: 01117 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 01118 goto s_error; 01119 } 01120 } else if (time_en){ 01121 if (timeout++ > I2C_SLAVE_TIME_OUT){ 01122 // it's really a stop condition, goto end stage 01123 goto s_end_stage; 01124 } 01125 } 01126 } 01127 01128 s_end_stage: 01129 /* Clear AA bit to disable ACK on I2C bus */ 01130 I2Cx->I2CONCLR = I2C_I2CONCLR_AAC; 01131 // Check if there's no error during operation 01132 // Update status 01133 TransferCfg->status = CodeStatus | I2C_SETUP_STATUS_DONE; 01134 return SUCCESS; 01135 01136 s_error: 01137 /* Clear AA bit to disable ACK on I2C bus */ 01138 I2Cx->I2CONCLR = I2C_I2CONCLR_AAC; 01139 // Update status 01140 TransferCfg->status = CodeStatus; 01141 return ERROR; 01142 } 01143 01144 else if (Opt == I2C_TRANSFER_INTERRUPT){ 01145 // Setup tx_rx data, callback and interrupt handler 01146 tmp = I2C_getNum(I2Cx); 01147 i2cdat[tmp].txrx_setup = (uint32_t) TransferCfg; 01148 // Set direction phase, read first 01149 i2cdat[tmp].dir = 1; 01150 01151 // Enable AA 01152 I2Cx->I2CONSET = I2C_I2CONSET_AA; 01153 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC; 01154 I2C_IntCmd(I2Cx, TRUE); 01155 01156 return (SUCCESS); 01157 } 01158 01159 return ERROR; 01160 } 01161 01162 /*********************************************************************//** 01163 * @brief Set Own slave address in I2C peripheral corresponding to 01164 * parameter specified in OwnSlaveAddrConfigStruct. 01165 * @param[in] I2Cx I2C peripheral selected, should be 01166 * - LPC_I2C0 01167 * - LPC_I2C1 01168 * - LPC_I2C2 01169 * @param[in] OwnSlaveAddrConfigStruct Pointer to a I2C_OWNSLAVEADDR_CFG_Type 01170 * structure that contains the configuration information for the 01171 * specified I2C slave address. 01172 * @return None 01173 **********************************************************************/ 01174 void I2C_SetOwnSlaveAddr(LPC_I2C_TypeDef *I2Cx, I2C_OWNSLAVEADDR_CFG_Type *OwnSlaveAddrConfigStruct) 01175 { 01176 uint32_t tmp; 01177 CHECK_PARAM(PARAM_I2Cx(I2Cx)); 01178 CHECK_PARAM(PARAM_I2C_SLAVEADDR_CH(OwnSlaveAddrConfigStruct->SlaveAddrChannel)); 01179 CHECK_PARAM(PARAM_FUNCTIONALSTATE(OwnSlaveAddrConfigStruct->GeneralCallState)); 01180 01181 tmp = (((uint32_t)(OwnSlaveAddrConfigStruct->SlaveAddr_7bit << 1)) \ 01182 | ((OwnSlaveAddrConfigStruct->GeneralCallState == ENABLE) ? 0x01 : 0x00))& I2C_I2ADR_BITMASK; 01183 switch (OwnSlaveAddrConfigStruct->SlaveAddrChannel) 01184 { 01185 case 0: 01186 I2Cx->I2ADR0 = tmp; 01187 I2Cx->I2MASK0 = I2C_I2MASK_MASK((uint32_t) \ 01188 (OwnSlaveAddrConfigStruct->SlaveAddrMaskValue)); 01189 break; 01190 case 1: 01191 I2Cx->I2ADR1 = tmp; 01192 I2Cx->I2MASK1 = I2C_I2MASK_MASK((uint32_t) \ 01193 (OwnSlaveAddrConfigStruct->SlaveAddrMaskValue)); 01194 break; 01195 case 2: 01196 I2Cx->I2ADR2 = tmp; 01197 I2Cx->I2MASK2 = I2C_I2MASK_MASK((uint32_t) \ 01198 (OwnSlaveAddrConfigStruct->SlaveAddrMaskValue)); 01199 break; 01200 case 3: 01201 I2Cx->I2ADR3 = tmp; 01202 I2Cx->I2MASK3 = I2C_I2MASK_MASK((uint32_t) \ 01203 (OwnSlaveAddrConfigStruct->SlaveAddrMaskValue)); 01204 break; 01205 } 01206 } 01207 01208 01209 /*********************************************************************//** 01210 * @brief Configures functionality in I2C monitor mode 01211 * @param[in] I2Cx I2C peripheral selected, should be 01212 * - LPC_I2C0 01213 * - LPC_I2C1 01214 * - LPC_I2C2 01215 * @param[in] MonitorCfgType Monitor Configuration type, should be: 01216 * - I2C_MONITOR_CFG_SCL_OUTPUT: I2C module can 'stretch' 01217 * the clock line (hold it low) until it has had time to 01218 * respond to an I2C interrupt. 01219 * - I2C_MONITOR_CFG_MATCHALL: When this bit is set to '1' 01220 * and the I2C is in monitor mode, an interrupt will be 01221 * generated on ANY address received. 01222 * @param[in] NewState New State of this function, should be: 01223 * - ENABLE: Enable this function. 01224 * - DISABLE: Disable this function. 01225 * @return None 01226 **********************************************************************/ 01227 void I2C_MonitorModeConfig(LPC_I2C_TypeDef *I2Cx, uint32_t MonitorCfgType, FunctionalState NewState) 01228 { 01229 CHECK_PARAM(PARAM_I2Cx(I2Cx)); 01230 CHECK_PARAM(PARAM_I2C_MONITOR_CFG(MonitorCfgType)); 01231 CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState)); 01232 01233 if (NewState == ENABLE) 01234 { 01235 I2Cx->MMCTRL |= MonitorCfgType; 01236 } 01237 else 01238 { 01239 I2Cx->MMCTRL &= (~MonitorCfgType) & I2C_I2MMCTRL_BITMASK; 01240 } 01241 } 01242 01243 01244 /*********************************************************************//** 01245 * @brief Enable/Disable I2C monitor mode 01246 * @param[in] I2Cx I2C peripheral selected, should be 01247 * - LPC_I2C0 01248 * - LPC_I2C1 01249 * - LPC_I2C2 01250 * @param[in] NewState New State of this function, should be: 01251 * - ENABLE: Enable monitor mode. 01252 * - DISABLE: Disable monitor mode. 01253 * @return None 01254 **********************************************************************/ 01255 void I2C_MonitorModeCmd(LPC_I2C_TypeDef *I2Cx, FunctionalState NewState) 01256 { 01257 CHECK_PARAM(PARAM_I2Cx(I2Cx)); 01258 CHECK_PARAM(PARAM_FUNCTIONALSTATE(NewState)); 01259 01260 if (NewState == ENABLE) 01261 { 01262 I2Cx->MMCTRL |= I2C_I2MMCTRL_MM_ENA; 01263 I2Cx->I2CONSET = I2C_I2CONSET_AA; 01264 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC; 01265 } 01266 else 01267 { 01268 I2Cx->MMCTRL &= (~I2C_I2MMCTRL_MM_ENA) & I2C_I2MMCTRL_BITMASK; 01269 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC | I2C_I2CONCLR_AAC; 01270 } 01271 I2C_MonitorBufferIndex = 0; 01272 } 01273 01274 01275 /*********************************************************************//** 01276 * @brief Get data from I2C data buffer in monitor mode. 01277 * @param[in] I2Cx I2C peripheral selected, should be 01278 * - LPC_I2C0 01279 * - LPC_I2C1 01280 * - LPC_I2C2 01281 * @return None 01282 * Note: In monitor mode, the I2C module may lose the ability to stretch 01283 * the clock (stall the bus) if the ENA_SCL bit is not set. This means that 01284 * the processor will have a limited amount of time to read the contents of 01285 * the data received on the bus. If the processor reads the I2DAT shift 01286 * register, as it ordinarily would, it could have only one bit-time to 01287 * respond to the interrupt before the received data is overwritten by 01288 * new data. 01289 **********************************************************************/ 01290 uint8_t I2C_MonitorGetDatabuffer(LPC_I2C_TypeDef *I2Cx) 01291 { 01292 CHECK_PARAM(PARAM_I2Cx(I2Cx)); 01293 return ((uint8_t)(I2Cx->I2DATA_BUFFER)); 01294 } 01295 01296 /*********************************************************************//** 01297 * @brief Get data from I2C data buffer in monitor mode. 01298 * @param[in] I2Cx I2C peripheral selected, should be 01299 * - LPC_I2C0 01300 * - LPC_I2C1 01301 * - LPC_I2C2 01302 * @return None 01303 * Note: In monitor mode, the I2C module may lose the ability to stretch 01304 * the clock (stall the bus) if the ENA_SCL bit is not set. This means that 01305 * the processor will have a limited amount of time to read the contents of 01306 * the data received on the bus. If the processor reads the I2DAT shift 01307 * register, as it ordinarily would, it could have only one bit-time to 01308 * respond to the interrupt before the received data is overwritten by 01309 * new data. 01310 **********************************************************************/ 01311 BOOL_8 I2C_MonitorHandler(LPC_I2C_TypeDef *I2Cx, uint8_t *buffer, uint32_t size) 01312 { 01313 BOOL_8 ret=FALSE; 01314 01315 I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; 01316 01317 buffer[I2C_MonitorBufferIndex] = (uint8_t)(I2Cx->I2DATA_BUFFER); 01318 I2C_MonitorBufferIndex++; 01319 if(I2C_MonitorBufferIndex >= size) 01320 { 01321 ret = TRUE; 01322 } 01323 return ret; 01324 } 01325 /*********************************************************************//** 01326 * @brief Get status of Master Transfer 01327 * @param[in] I2Cx I2C peripheral selected, should be: 01328 * - LPC_I2C0 01329 * - LPC_I2C1 01330 * - LPC_I2C2 01331 * @return Master transfer status, could be: 01332 * - TRUE master transfer completed 01333 * - FALSE master transfer have not completed yet 01334 **********************************************************************/ 01335 uint32_t I2C_MasterTransferComplete(LPC_I2C_TypeDef *I2Cx) 01336 { 01337 uint32_t retval, tmp; 01338 tmp = I2C_getNum(I2Cx); 01339 retval = I2C_MasterComplete[tmp]; 01340 I2C_MasterComplete[tmp] = FALSE; 01341 return retval; 01342 } 01343 01344 /*********************************************************************//** 01345 * @brief Get status of Slave Transfer 01346 * @param[in] I2Cx I2C peripheral selected, should be: 01347 * - LPC_I2C0 01348 * - LPC_I2C1 01349 * - LPC_I2C2 01350 * @return Complete status, could be: TRUE/FALSE 01351 **********************************************************************/ 01352 uint32_t I2C_SlaveTransferComplete(LPC_I2C_TypeDef *I2Cx) 01353 { 01354 uint32_t retval, tmp; 01355 tmp = I2C_getNum(I2Cx); 01356 retval = I2C_SlaveComplete[tmp]; 01357 I2C_SlaveComplete[tmp] = FALSE; 01358 return retval; 01359 } 01360 01361 01362 01363 /** 01364 * @} 01365 */ 01366 01367 #endif /* _I2C */ 01368 01369 /** 01370 * @} 01371 */ 01372 01373 /* --------------------------------- End Of File ------------------------------ */
Generated on Tue Jul 12 2022 17:33:24 by
