Status I2C_Write(I2C_TypeDef* I2Cx, const uint8_t* buf, uint32_t nbyte, uint8_t SlaveAddress) { __IO uint32_t Timeout = 0; /* Enable Error IT (used in all modes: DMA, Polling and Interrupts */ // I2Cx->CR2 |= I2C_IT_ERR; if (nbyte) { Timed(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)); // Intiate Start Sequence I2C_GenerateSTART(I2Cx, ENABLE); Timed(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); // Send Address EV5 I2C_Send7bitAddress(I2Cx, SlaveAddress, I2C_Direction_Transmitter); //Timed(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // EV6 // Write first byte EV8_1 I2C_SendData(I2Cx, *buf++); while (--nbyte) { // wait on BTF //Timed(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF)); I2C_SendData(I2Cx, *buf++); } //Timed(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF)); I2C_GenerateSTOP(I2Cx, ENABLE); //Timed(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF)); } return Success; errReturn: return Error; }
Status I2C_Read(I2C_TypeDef* I2Cx, uint8_t *buf,uint32_t nbyte, uint8_t SlaveAddress) { __IO uint32_t Timeout = 0; // I2Cx->CR2 |= I2C_IT_ERR; interrupts for errors if (!nbyte) return Success; // Wait for idle I2C interface Timed(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)); // Enable Acknowledgement, clear POS flag I2C_AcknowledgeConfig(I2Cx, ENABLE); //I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Current); // Intiate Start Sequence (wait for EV5 I2C_GenerateSTART(I2Cx, ENABLE); Timed(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); // Send Address I2C_Send7bitAddress(I2Cx, SlaveAddress, I2C_Direction_Receiver); // EV6 Timed(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR)); if (nbyte == 1) { // Clear Ack bit I2C_AcknowledgeConfig(I2Cx, DISABLE); // EV6_1 -- must be atomic -- Clear ADDR, generate STOP (void) I2Cx->SR2; I2C_GenerateSTOP(I2Cx,ENABLE); // Receive data EV7 Timed(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_RXNE)); *buf++ = I2C_ReceiveData(I2Cx); } else if (nbyte == 2) { // EV6_1 -- must be atomic and in this order (void) I2Cx->SR2; // Clear ADDR flag I2C_AcknowledgeConfig(I2Cx, DISABLE); // Clear Ack bit // EV7_3 -- Wait for BTF, program stop, read data twice Timed(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF)); I2C_GenerateSTOP(I2Cx,ENABLE); *buf++ = I2Cx->DR; *buf++ = I2Cx->DR; } else { (void) I2Cx->SR2; // Clear ADDR flag while (nbyte-- != 3) { // EV7 -- cannot guarantee 1 transfer completion time, wait for BTF // instead of RXNE Timed(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF)); *buf++ = I2C_ReceiveData(I2Cx); } Timed(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF)); // EV7_2 -- Figure 1 has an error, doesn't read N-2 ! I2C_AcknowledgeConfig(I2Cx, DISABLE); // clear ack bit *buf++ = I2C_ReceiveData(I2Cx); // receive byte N-2 I2C_GenerateSTOP(I2Cx,ENABLE); // program stop *buf++ = I2C_ReceiveData(I2Cx); // receive byte N-1 // wait for byte N Timed(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); *buf++ = I2C_ReceiveData(I2Cx); nbyte = 0; } // Wait for stop Timed(I2C_GetFlagStatus(I2Cx, I2C_FLAG_STOPF)); return Success; errReturn: // Any cleanup here return Error; }