/* Includes ------------------------------------------------------------------*/
#include "stm32l1xx.h"
//#include "com.h"
#include "stm32l1xx_i2c.h"
#define Timed(x) Timeout = 0xFFFF; while (x) \
{ if (Timeout -- == 0) goto errReturn ;}
int I2C_Write(const uint8_t* buf, uint32_t nbyte, uint8_t SlaveAddress) {
__IO uint32_t Timeout = 0;
if (nbyte) {
Timed(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY));
// Intiate Start Sequence
I2C_GenerateSTART(I2C2, ENABLE);
Timed(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));
// Send Address EV5
I2C_Send7bitAddress(I2C2, SlaveAddress, I2C_Direction_Transmitter);
Timed(
!I2C_CheckEvent(I2C2,
I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
// EV6 Write first byte EV8_1
I2C_SendData(I2C2, *buf++);
while (--nbyte) {
// wait on BTF
Timed(!I2C_GetFlagStatus(I2C2, I2C_FLAG_BTF));
I2C_SendData(I2C2, *buf++);
}
Timed(!I2C_GetFlagStatus(I2C2, I2C_FLAG_BTF));
I2C_GenerateSTOP(I2C2, ENABLE);
Timed (I2C_GetFlagStatus( I2C2, I2C_FLAG_STOPF));
}
return 0;
errReturn:
return 1;
}
int I2C_Read(uint8_t *buf, uint32_t nbyte, uint8_t SlaveAddress) {
__IO uint32_t Timeout = 0;
if (!nbyte)
return 0;
// Wait for idle I2C interface
Timed(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY));
// Enable Acknowledgment , clear POS flag
I2C_AcknowledgeConfig(I2C2, ENABLE);
I2C_NACKPositionConfig(I2C2, I2C_NACKPosition_Current);
// Intiate Start Sequence (wait for EV5)
I2C_GenerateSTART(I2C2, ENABLE);
Timed(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));
// Send Address
I2C_Send7bitAddress(I2C2, SlaveAddress, I2C_Direction_Receiver);
// EV6
Timed(!I2C_GetFlagStatus(I2C2, I2C_FLAG_ADDR));
if (nbyte == 1) { /* read 1 byte */
// Clear Ack bit
I2C_AcknowledgeConfig(I2C2, DISABLE);
// EV6_1 -- must be atomic -- Clear ADDR , generate STOP
__disable_irq();
(void) I2C2->SR2;
I2C_GenerateSTOP(I2C2, ENABLE);
__enable_irq();
// Receive data EV7
Timed(!I2C_GetFlagStatus(I2C2, I2C_FLAG_RXNE));
*buf++ = I2C_ReceiveData(I2C2);
} else if (nbyte == 2) {
// Set POS flag
I2C_NACKPositionConfig(I2C2, I2C_NACKPosition_Next);
// EV6_1 -- must be atomic and in this order
__disable_irq();
(void) I2C2->SR2; // Clear ADDR flag
I2C_AcknowledgeConfig(I2C2, DISABLE); // Clear Ack bit
__enable_irq();
// EV7_3 -- Wait for BTF , program stop , read data twice
Timed(!I2C_GetFlagStatus(I2C2, I2C_FLAG_BTF));
__disable_irq();
I2C_GenerateSTOP(I2C2, ENABLE);
*buf++ = I2C2->DR;
__enable_irq();
*buf++ = I2C2->DR;
} else {
(void) I2C2->SR2; // Clear ADDR flag
while (nbyte-- != 3) {
// EV7 -- cannot guarantee 1 transfer completion time ,
// wait for BTF instead of RXNE
Timed(!I2C_GetFlagStatus(I2C2, I2C_FLAG_BTF));
*buf++ = I2C_ReceiveData(I2C2);
}
Timed(!I2C_GetFlagStatus(I2C2, I2C_FLAG_BTF));
// EV7_2 -- Figure 1 has an error , doesn 't read N-2 !
I2C_AcknowledgeConfig(I2C2, DISABLE); // clear ack bit
__disable_irq();
*buf++ = I2C_ReceiveData(I2C2); // receive byte N-2
I2C_GenerateSTOP(I2C2, ENABLE); // program stop
__enable_irq();
*buf++ = I2C_ReceiveData(I2C2); // receive byte N-1
// wait for byte N
Timed(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED));
*buf++ = I2C_ReceiveData(I2C2);
nbyte = 0;
}
// Wait for stop
Timed(I2C_GetFlagStatus(I2C2, I2C_FLAG_STOPF));
return 0;
errReturn:
return 1;
}