int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) { I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c); I2cHandle.Instance = (I2C_TypeDef *)(obj->i2c); int timeout; int count; int value; i2c_start(obj); // Wait until SB flag is set timeout = FLAG_TIMEOUT; while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_SB) == RESET) { timeout--; if (timeout == 0) { return -1; } } i2c->DR = I2C_7BIT_ADD_READ(address); // Wait address is acknowledged timeout = FLAG_TIMEOUT; while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_ADDR) == RESET) { timeout--; if (timeout == 0) { return -1; } } __HAL_I2C_CLEAR_ADDRFLAG(&I2cHandle); // Read all bytes except last one for (count = 0; count < (length - 1); count++) { value = i2c_byte_read(obj, 0); data[count] = (char)value; } // If not repeated start, send stop. // Warning: must be done BEFORE the data is read. if (stop) { i2c_stop(obj); } // Read the last byte value = i2c_byte_read(obj, 1); data[count] = (char)value; return length; }
int I2C_Read(I2C_TypeDef* I2Cx, int address, char* data, int length, int stop){ uint16_t timeout; int count, value; I2C_Start(I2Cx); // Wait until SB flag is set timeout = FLAG_TIMEOUT; while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_SB) == RESET){ timeout--; if(timeout == 0){ return -1; } } I2Cx->DR = I2C_7BIT_ADD_READ(address); // Wait address is acknowledged timeout = FLAG_TIMEOUT; while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR) == RESET){ timeout--; if(timeout == 0){ return -1; } } __I2C_CLEAR_ADDRFLAG(I2Cx); // Read all bytes except last one for (count = 0; count < (length - 1); count++) { value = I2C_ByteRead(I2Cx, 0); data[count] = (char)value; } // If not repeated start, send stop. // Warning: must be done BEFORE the data is read. if (stop) { I2C_Stop(I2Cx); } // Read the last byte value = I2C_ByteRead(I2Cx, 1); data[count] = (char)value; return length; }
// this function is based on STM code int machine_hard_i2c_readfrom(mp_obj_base_t *self_in, uint16_t addr, uint8_t *dest, size_t len, bool stop) { machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t*)self_in; I2C_HandleTypeDef *hi2c = self->pyb->i2c; uint32_t Timeout = *self->timeout; /* Init tickstart for timeout management*/ uint32_t tickstart = HAL_GetTick(); #if 0 // TODO: for multi-master, here we could wait for the bus to be free // we'd need a flag to tell if we were in the middle of a set of transactions // (ie didn't send a stop bit in the last call) /* Wait until BUSY flag is reset */ if (!I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart)) { return -MP_EBUSY; } #endif /* Check if the I2C is already enabled */ if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) { /* Enable I2C peripheral */ __HAL_I2C_ENABLE(hi2c); } /* Disable Pos */ hi2c->Instance->CR1 &= ~I2C_CR1_POS; /* Enable Acknowledge */ hi2c->Instance->CR1 |= I2C_CR1_ACK; /* Send Slave Address */ int ret = send_addr_byte(hi2c, I2C_7BIT_ADD_READ(addr << 1), Timeout, tickstart); if (ret != 0) { return ret; } if (len == 0U) { /* Clear ADDR flag */ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); /* Generate Stop */ if (stop) { hi2c->Instance->CR1 |= I2C_CR1_STOP; } } else if (len == 1U) { /* Disable Acknowledge */ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; /* Clear ADDR flag */ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); /* Generate Stop */ if (stop) { hi2c->Instance->CR1 |= I2C_CR1_STOP; } } else if (len == 2U) { /* Disable Acknowledge */ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; /* Enable Pos */ hi2c->Instance->CR1 |= I2C_CR1_POS; /* Clear ADDR flag */ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); } else { /* Enable Acknowledge */ hi2c->Instance->CR1 |= I2C_CR1_ACK; /* Clear ADDR flag */ __HAL_I2C_CLEAR_ADDRFLAG(hi2c); } while (len > 0U) { if (len <= 3U) { if (len == 1U) { /* Wait until RXNE flag is set */ int ret = I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart); if (ret != 0) { return ret; } /* Read data from DR */ *dest++ = hi2c->Instance->DR; len--; } else if (len == 2U) { /* Wait until BTF flag is set */ if (!I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart)) { return -MP_ETIMEDOUT; } /* Generate Stop */ if (stop) { hi2c->Instance->CR1 |= I2C_CR1_STOP; } /* Read data from DR */ *dest++ = hi2c->Instance->DR; len--; /* Read data from DR */ *dest++ = hi2c->Instance->DR; len--; } else { /* Wait until BTF flag is set */ if (!I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart)) { return -MP_ETIMEDOUT; } /* Disable Acknowledge */ hi2c->Instance->CR1 &= ~I2C_CR1_ACK; /* Read data from DR */ *dest++ = hi2c->Instance->DR; len--; /* Wait until BTF flag is set */ if (!I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart)) { return -MP_ETIMEDOUT; } /* Generate Stop */ if (stop) { hi2c->Instance->CR1 |= I2C_CR1_STOP; } /* Read data from DR */ *dest++ = hi2c->Instance->DR; len--; /* Read data from DR */ *dest++ = hi2c->Instance->DR; len--; } } else { /* Wait until RXNE flag is set */ int ret = I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart); if (ret != 0) { return ret; } /* Read data from DR */ *dest++ = hi2c->Instance->DR; len--; if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) { /* Read data from DR */ *dest++ = hi2c->Instance->DR; len--; } } } return 0; }