|
@@ -15,13 +15,32 @@
|
|
|
static i2c_status_t st_Read = I2C_Ret_OK;
|
|
|
|
|
|
/* Private function prototypes */
|
|
|
-i2c_status_t i2c_check_err(void);
|
|
|
+static i2c_status_t i2c_check_err(void);
|
|
|
+
|
|
|
+static inline void i2c_start(void) {
|
|
|
+ // Send 'Start' condition, and wait for acknowledge.
|
|
|
+ I2C1->CR2 |= (I2C_CR2_START);
|
|
|
+ while ((I2C1->CR2 & I2C_CR2_START)) {}
|
|
|
+}
|
|
|
+
|
|
|
+static inline void i2c_stop(void) {
|
|
|
+ // Send 'Stop' condition, and wait for acknowledge.
|
|
|
+ I2C1->CR2 |= (I2C_CR2_STOP);
|
|
|
+ while ((I2C1->CR2 & I2C_CR2_STOP)) {}
|
|
|
+ // Reset the ICR ('Interrupt Clear Register') event flag.
|
|
|
+ I2C1->ICR |= (I2C_ICR_STOPCF);
|
|
|
+ while ((I2C1->ICR & I2C_ICR_STOPCF)) {}
|
|
|
+}
|
|
|
+
|
|
|
+static void i2c_write_byte(uint8_t dat);
|
|
|
+static uint8_t i2c_read_byte(void);
|
|
|
+static uint8_t i2c_read_register(uint8_t reg_addr);
|
|
|
|
|
|
/**
|
|
|
* @brief Check I2C bus for errors.
|
|
|
* @retval I2C return code
|
|
|
*/
|
|
|
-i2c_status_t i2c_check_err(void) {
|
|
|
+static i2c_status_t i2c_check_err(void) {
|
|
|
i2c_status_t r = I2C_Ret_OK;
|
|
|
|
|
|
if ((I2C1->ISR & I2C_ISR_NACKF) != 0) {
|
|
@@ -49,7 +68,7 @@ i2c_status_t i2c_check_err(void) {
|
|
|
* @brief Read len bytes from I2C bus to data by reg_addr.
|
|
|
* @retval I2C return code
|
|
|
*/
|
|
|
-i2c_status_t user_i2c_read(const uint8_t id, const uint8_t reg_addr, uint8_t *data, const uint16_t len) {
|
|
|
+i2c_status_t user_i2c_read(const uint8_t id, const uint8_t reg_addr, uint8_t *data, uint16_t len) {
|
|
|
/* wait for i2c */
|
|
|
while ( I2C1->ISR & I2C_ISR_BUSY ) { __NOP(); };
|
|
|
|
|
@@ -61,16 +80,11 @@ i2c_status_t user_i2c_read(const uint8_t id, const uint8_t reg_addr, uint8_t *da
|
|
|
|
|
|
/* prepare i2c for sending reg addr */
|
|
|
I2C1->CR2 &= ~(I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
|
|
|
- I2C1->CR2 |= (id | 1 << I2C_CR2_NBYTES_Pos);
|
|
|
- /* gen START */
|
|
|
- I2C1->CR2 |= I2C_CR2_START;
|
|
|
+ I2C1->CR2 |= (id | (1 << I2C_CR2_NBYTES_Pos));
|
|
|
+ i2c_start();
|
|
|
|
|
|
/* wait for byte request or any error */
|
|
|
- //ENABLE_TIM;
|
|
|
while ((I2C1->ISR & (I2C_ISR_TIMEOUT | I2C_ISR_ARLO | I2C_ISR_BERR | I2C_ISR_NACKF | I2C_ISR_TXE)) == 0) {
|
|
|
- //if (TIM_CNT == 0) {
|
|
|
- // return I2C_Ret_Tout;
|
|
|
- //}
|
|
|
__NOP();
|
|
|
}
|
|
|
|
|
@@ -79,10 +93,9 @@ i2c_status_t user_i2c_read(const uint8_t id, const uint8_t reg_addr, uint8_t *da
|
|
|
I2C1->TXDR = reg_addr;
|
|
|
} else {
|
|
|
st_Read = i2c_check_err();
|
|
|
- if (st_Read != I2C_Ret_OK) {
|
|
|
- Flag.I2C_TX_Err = 1;
|
|
|
- return st_Read;
|
|
|
- }
|
|
|
+ Flag.I2C_TX_Err = 1;
|
|
|
+ Flag.I2C_RX_End = 1;
|
|
|
+ return st_Read;
|
|
|
}
|
|
|
|
|
|
/* wait for i2c or any error */
|
|
@@ -90,37 +103,32 @@ i2c_status_t user_i2c_read(const uint8_t id, const uint8_t reg_addr, uint8_t *da
|
|
|
st_Read = i2c_check_err();
|
|
|
if (st_Read != I2C_Ret_OK) {
|
|
|
Flag.I2C_TX_Err = 1;
|
|
|
+ Flag.I2C_RX_End = 1;
|
|
|
return st_Read;
|
|
|
}
|
|
|
|
|
|
- int cnt = 0;
|
|
|
- // Read data while no TC flag set.
|
|
|
- // Если взлетит NACK-флаг, приём прекращаем.
|
|
|
- //ENABLE_TIM;
|
|
|
- while ((((I2C1->ISR & I2C_ISR_TC)==0) && ((I2C1->ISR & I2C_ISR_NACKF)==0)) && (I2C1->ISR & I2C_ISR_BUSY)) {
|
|
|
+ /* prepare i2c for receiving data */
|
|
|
+ I2C1->CR2 &= ~(I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
|
|
|
+ I2C1->CR2 |= (id | (len << I2C_CR2_NBYTES_Pos) | I2C_CR2_RD_WRN);
|
|
|
+ /* launch receiving */
|
|
|
+ i2c_start();
|
|
|
+
|
|
|
+ /* receiving data */
|
|
|
+ while (len) {
|
|
|
+ while ((I2C1->ISR & (I2C_ISR_NACKF | I2C_ISR_RXNE))==0) { __NOP(); }
|
|
|
if (I2C1->ISR & I2C_ISR_RXNE) { // Reading data
|
|
|
*data = I2C1->RXDR;
|
|
|
data ++;
|
|
|
- cnt ++;
|
|
|
- if (cnt > len) {
|
|
|
- st_Read = I2C_Ret_Err;
|
|
|
- break;
|
|
|
- }
|
|
|
+ len --;
|
|
|
+ } else {
|
|
|
+ st_Read = i2c_check_err();
|
|
|
+ Flag.I2C_RX_Err = 1;
|
|
|
+ Flag.I2C_RX_End = 1;
|
|
|
+ return st_Read;
|
|
|
}
|
|
|
- //if (TIM_CNT == 0) {
|
|
|
- // st_Read = I2C_Ret_Tout;
|
|
|
- // break;
|
|
|
- //}
|
|
|
}
|
|
|
|
|
|
- /* wait for receiving data */
|
|
|
- //while ((Flag.I2C_RX_End == 0) && (Flag.I2C_RX_Err == 0)) { __NOP(); };
|
|
|
-
|
|
|
- /* Set STOP */
|
|
|
- //I2C1->CR2 |= I2C_CR2_STOP;
|
|
|
- /* Clear flags */
|
|
|
- //I2C1->ICR = (I2C_ICR_STOPCF | I2C_ICR_NACKCF | I2C_ICR_ARLOCF | I2C_ICR_BERRCF);
|
|
|
-
|
|
|
+ Flag.I2C_RX_End = 1;
|
|
|
return st_Read;
|
|
|
}
|
|
|
|
|
@@ -136,19 +144,11 @@ i2c_status_t user_i2c_write(const uint8_t id, const uint8_t reg_addr, uint8_t *d
|
|
|
Flag.I2C_TX_End = 0;
|
|
|
Flag.I2C_TX_Err = 0;
|
|
|
|
|
|
- DMA1_Channel2->CMAR = (uint32_t)data;
|
|
|
- DMA1_Channel2->CPAR = (uint32_t)&(I2C1->TXDR);
|
|
|
- DMA1_Channel2->CNDTR = len;
|
|
|
-
|
|
|
- I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
|
|
|
- I2C1->CR2 |= ( id | (len + 1) << I2C_CR2_NBYTES_Pos );
|
|
|
- I2C1->CR2 |= ( I2C_CR2_START );
|
|
|
+ I2C1->CR2 &= ~(I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
|
|
|
+ I2C1->CR2 |= (id | ((len + 1) << I2C_CR2_NBYTES_Pos ));
|
|
|
+ i2c_start();
|
|
|
|
|
|
- //ENABLE_TIM;
|
|
|
while ((I2C1->ISR & (I2C_ISR_ARLO | I2C_ISR_BERR | I2C_ISR_NACKF | I2C_ISR_TXE)) == 0) {
|
|
|
- //if (TIM_CNT == 0) {
|
|
|
- // return I2C_Ret_Tout;
|
|
|
- //}
|
|
|
__NOP();
|
|
|
}
|
|
|
|
|
@@ -156,28 +156,69 @@ i2c_status_t user_i2c_write(const uint8_t id, const uint8_t reg_addr, uint8_t *d
|
|
|
I2C1->TXDR = reg_addr;
|
|
|
} else {
|
|
|
r = i2c_check_err();
|
|
|
- if (r != I2C_Ret_OK) {
|
|
|
- Flag.I2C_TX_Err = 1;
|
|
|
- return r;
|
|
|
- }
|
|
|
+ Flag.I2C_TX_Err = 1;
|
|
|
+ Flag.I2C_TX_End = 1;
|
|
|
+ return r;
|
|
|
}
|
|
|
|
|
|
while (len) {
|
|
|
- while ((I2C1->ISR & (I2C_ISR_TC | I2C_ISR_BUSY | I2C_ISR_NACKF | I2C_ISR_TXE)) == 0) { __NOP(); }
|
|
|
- if (I2C1->ISR & I2C_ISR_TXE) {
|
|
|
+ while ((I2C1->ISR & (I2C_ISR_NACKF | I2C_ISR_TXE)) == 0) { __NOP(); }
|
|
|
+ if ((I2C1->ISR & I2C_ISR_TXE) != 0) {
|
|
|
I2C1->TXDR = *data;
|
|
|
data ++;
|
|
|
len --;
|
|
|
} else {
|
|
|
r = i2c_check_err();
|
|
|
- if (r != I2C_Ret_OK) {
|
|
|
- Flag.I2C_TX_Err = 1;
|
|
|
- return r;
|
|
|
- }
|
|
|
+ Flag.I2C_TX_Err = 1;
|
|
|
+ Flag.I2C_TX_End = 1;
|
|
|
+ return r;
|
|
|
}
|
|
|
}
|
|
|
-// DMA1_Channel2->CCR |= DMA_CCR_EN;
|
|
|
-// I2C1->CR1 |= I2C_CR1_TXDMAEN;
|
|
|
|
|
|
+ Flag.I2C_TX_End = 1;
|
|
|
return r;
|
|
|
}
|
|
|
+
|
|
|
+static void i2c_write_byte(uint8_t dat) {
|
|
|
+ I2C1->TXDR = (I2C1->TXDR & 0xFFFFFF00) | dat;
|
|
|
+ // Wait for one of these ISR bits:
|
|
|
+ // 'TXIS' ("ready for next byte")
|
|
|
+ // 'TC' ("transfer complete")
|
|
|
+ while (!(I2C1->ISR & (I2C_ISR_TXIS | I2C_ISR_TC))) {}
|
|
|
+ // (Also of interest: 'TXE' ("TXDR register is empty") and
|
|
|
+ // 'TCR' ("transfer complete, and 'RELOAD' is set."))
|
|
|
+}
|
|
|
+
|
|
|
+static uint8_t i2c_read_byte(void) {
|
|
|
+ // Wait for a byte of data to be available, then read it.
|
|
|
+ while (!(I2C1->ISR & I2C_ISR_RXNE)) {}
|
|
|
+ return (I2C1->RXDR & 0xFF);
|
|
|
+}
|
|
|
+
|
|
|
+static uint8_t i2c_read_register(uint8_t reg_addr) {
|
|
|
+ // Set '1 byte to send.'
|
|
|
+ I2C1->CR2 &= ~(I2C_CR2_NBYTES);
|
|
|
+ I2C1->CR2 |= (0x01 << I2C_CR2_NBYTES_Pos);
|
|
|
+ // Start the I2C write transmission.
|
|
|
+ i2c_start();
|
|
|
+ // Send the register address.
|
|
|
+ i2c_write_byte(reg_addr);
|
|
|
+ // Stop the I2C write transmission.
|
|
|
+ i2c_stop();
|
|
|
+ // Set '1 byte to receive.'
|
|
|
+ I2C1->CR2 &= ~(I2C_CR2_NBYTES);
|
|
|
+ I2C1->CR2 |= (0x01 << I2C_CR2_NBYTES_Pos);
|
|
|
+ // Set 'read' I2C direction.
|
|
|
+ I2C1->CR2 |= (I2C_CR2_RD_WRN);
|
|
|
+ // Start the I2C read transmission.
|
|
|
+ i2c_start();
|
|
|
+ // Read the transmitted data.
|
|
|
+ uint8_t read_result = i2c_read_byte();
|
|
|
+ // Stop the I2C read transmission.
|
|
|
+ i2c_stop();
|
|
|
+ // Set 'write' I2C direction again.
|
|
|
+ I2C1->CR2 &= ~(I2C_CR2_RD_WRN);
|
|
|
+
|
|
|
+ // Return the read value.
|
|
|
+ return read_result;
|
|
|
+}
|