// Used by the read_register and write_register functions // data_array is read data for WRITE_READ and tx2 data for WRITE_WRITE void i2c_transfer(uint16_t device_addr, uint8_t cmd_array[], uint8_t data_array[], uint16_t cmd_len, uint16_t data_len, uint8_t flag) { // Transfer structure I2C_TransferSeq_TypeDef i2cTransfer; // Initialize I2C transfer I2C_TransferReturn_TypeDef result; i2cTransfer.addr = device_addr; i2cTransfer.flags = flag; i2cTransfer.buf[0].data = cmd_array; i2cTransfer.buf[0].len = cmd_len; // Note that WRITE_WRITE this is tx2 data i2cTransfer.buf[1].data = data_array; i2cTransfer.buf[1].len = data_len; // Set up the transfer result = I2C_TransferInit(I2C0, &i2cTransfer); // Do it until the transfer is done while (result != i2cTransferDone) { if (result != i2cTransferInProgress) { DEBUG_BREAK; } result = I2C_Transfer(I2C0); } }
//0.95s内完成 uint8_t drv_R8025T_read(uint8_t addr, uint8_t* data, uint8_t len) { uint8_t result = 0; // uint8_t idx; // uint8_t try_count = 0; // uint32_t star_tick; /* Transfer structure */ I2C_TransferSeq_TypeDef i2cTransfer;// /* Initializing I2C transfer */ i2cTransfer.addr = R8025T_SLAVE_ADDRESS; i2cTransfer.flags = I2C_FLAG_WRITE_READ;//I2C_FLAG_WRITE_READ - data written from buf[0].data and read into buf[1].data i2cTransfer.buf[0].data = (&addr); i2cTransfer.buf[0].len = 1; i2cTransfer.buf[1].data = data; i2cTransfer.buf[1].len = len; I2C_TransferInit(I2C0, &i2cTransfer); /* Sending data */ while (I2C_Transfer(I2C0) == i2cTransferInProgress){;} result = (sizeof(data)/sizeof(uint8_t)); return result; }
/***************************************************************************//** * @brief * Write to sensor register. * * @param[in] i2c * Pointer to I2C peripheral register block. * * @param[in] addr * I2C address for temperature sensor, in 8 bit format, where LSB is reserved * for R/W bit. * * @param[in] reg * Register to write (temperature register cannot be written). * * @param[in] val * Value used when writing to register. * * @return * Returns 0 if register written, <0 if unable to write to register. ******************************************************************************/ int I2C_RegisterSet(I2C_TypeDef *i2c, uint8_t addr, uint8_t reg, uint8_t val) { I2C_TransferSeq_TypeDef seq; uint8_t data[1]; uint8_t data2[1]; seq.addr = addr; seq.flags = I2C_FLAG_WRITE_WRITE; /* Select register to be written */ data[0] = reg; seq.buf[0].data = data; /* Only 1 byte reg */ data2[0] = val; seq.buf[0].len = 1; seq.buf[1].data = data2; seq.buf[1].len = 1; /* Do a polled transfer */ I2C_Status = I2C_TransferInit(i2c, &seq); /* Sending data */ while (I2C_Transfer(I2C0) != i2cTransferDone){;} // // while (I2C_Status != i2cTransferDone) // { // /* Enter EM1 while waiting for I2C interrupt */ // EMU_EnterEM1(); // /* Could do a timeout function here. */ // } return(0); }
/**************************************************************************//** * @brief I2C Interrupt Handler. * The interrupt table is in assembly startup file startup_efm32.s *****************************************************************************/ void I2C0_IRQHandler(void) { /* Just run the I2C_Transfer function that checks interrupts flags and returns */ /* the appropriate status */ // I2C_IntClear(I2C0, I2C_IFC_TXC); I2C_Status = I2C_Transfer(I2C0); }
/***************************************************************************//** * @brief * Read sensor register content. * * @details * If reading the temperature register, when a measurement is completed inside * the sensor device, the new measurement may not be stored. For this reason, * the temperature should not be polled with a higher frequency than the * measurement conversion time for a given resolution configuration. Please * refer to sensor device datasheet. * * @param[in] i2c * Pointer to I2C peripheral register block. * * @param[in] addr * I2C address for temperature sensor, in 8 bit format, where LSB is reserved * for R/W bit. * * @param[in] reg * Register to read. * * @param[out] val * Reference to place register read. * * @return * Returns 0 if register read, <0 if unable to read register. ******************************************************************************/ int I2C_RegisterGet(I2C_TypeDef *i2c, uint8_t addr, uint8_t reg, uint8_t *val, uint32_t len) { I2C_TransferSeq_TypeDef seq; uint8_t regid[1]; uint8_t data[1]; seq.addr = addr; seq.flags = I2C_FLAG_WRITE_READ; /* Select register to be read */ regid[0] = ((uint8_t)reg); seq.buf[0].data = regid; seq.buf[0].len = 1; /* Only 1 byte reg*/ seq.buf[1].data = data; seq.buf[1].len = 1; /* Do a polled transfer */ I2C_Status = I2C_TransferInit(i2c, &seq); /* Sending data */ while (I2C_Transfer(I2C0) != i2cTransferDone){;} //if (I2C_Status != i2cTransferDone) //{ //return((int)I2C_Status); //} *val = data[0]; return(0); }
/*---------------------------------------------------------------------------*/ int i2c1_transfer(struct i2c_msg *msg) { I2C_TransferSeq_TypeDef seq; I2C_TransferReturn_TypeDef ret; uint32_t timeout = 3000; memset(&seq,0,sizeof(seq)); seq.addr = msg->address << 1; seq.flags = 0; if(msg->mode & I2C_WRITE) { seq.flags |= I2C_FLAG_WRITE; seq.buf[0].data = msg->buf; seq.buf[0].len = msg->len; } if(msg->mode & I2C_READ) { seq.flags |= I2C_FLAG_READ; seq.buf[1].data = msg->buf; seq.buf[1].len = msg->len; } ret = I2C_TransferInit(I2C1, &seq); while (ret == i2cTransferInProgress && timeout--) { ret = I2C_Transfer(I2C1); } if(ret != 0) return -EIO; return 1; }
/***************************************************************************//** * @brief * Perform I2C transfer * * @details * This driver only supports master mode, single bus-master. It does not * return until the transfer is complete, polling for completion. * * @param[in] i2c * Pointer to the peripheral port * * @param[in] seq * Pointer to sequence structure defining the I2C transfer to take place. The * referenced structure must exist until the transfer has fully completed. ******************************************************************************/ I2C_TransferReturn_TypeDef I2CSPM_Transfer(I2C_TypeDef *i2c, I2C_TransferSeq_TypeDef *seq) { I2C_TransferReturn_TypeDef ret; uint32_t timeout = I2CSPM_TRANSFER_TIMEOUT; /* Do a polled transfer */ ret = I2C_TransferInit(i2c, seq); while (ret == i2cTransferInProgress && timeout--) { ret = I2C_Transfer(i2c); } return ret; }
/***************************************************************************//** * @brief * Perform I2C transfer. * * @details * This driver only supports master mode, single bus-master. It does not * return until the transfer is complete, polling for completion. * * @param[in] seq * Pointer to sequence structure defining the I2C transfer to take place. The * referenced structure must exist until the transfer has fully completed. ******************************************************************************/ I2C_TransferReturn_TypeDef I2CDRV_Transfer(I2C_TransferSeq_TypeDef *seq) { I2C_TransferReturn_TypeDef ret; /* Do a polled transfer */ ret = I2C_TransferInit(I2C0, seq); while (ret == i2cTransferInProgress) { ret = I2C_Transfer(I2C0); } return(ret); }
/***************************************************************************//** * @brief * Perform I2C transfer. * * @details * This driver only supports master mode, single bus-master. It does not * return until the transfer is complete, polling for completion. * * @param[in] seq * Pointer to sequence structure defining the I2C transfer to take place. The * referenced structure must exist until the transfer has fully completed. ******************************************************************************/ I2C_TransferReturn_TypeDef I2CDRV_Transfer(I2C_TransferSeq_TypeDef *seq) { I2C_TransferReturn_TypeDef ret; uint32_t timeout = 300000; /* Do a polled transfer */ ret = I2C_TransferInit(I2C0, seq); while (ret == i2cTransferInProgress && timeout--) { ret = I2C_Transfer(I2C0); } return(ret); }
/** The asynchronous IRQ handler * @param obj The I2C object which holds the transfer information * @return Returns event flags if a transfer termination condition was met or 0 otherwise. */ uint32_t i2c_irq_handler_asynch(i2c_t *obj) { // For now, we are assuming a solely interrupt-driven implementation. I2C_TransferReturn_TypeDef status = I2C_Transfer(obj->i2c.i2c); switch(status) { case i2cTransferInProgress: // Still busy transferring, so let it. return 0; case i2cTransferDone: // Transfer has completed // Disable interrupt i2c_enable_interrupt(obj, 0, false); unblockSleepMode(EM1); return I2C_EVENT_TRANSFER_COMPLETE & obj->i2c.events; case i2cTransferNack: // A NACK has been received while an ACK was expected. This is usually because the slave did not respond to the address. // Disable interrupt i2c_enable_interrupt(obj, 0, false); unblockSleepMode(EM1); return I2C_EVENT_ERROR_NO_SLAVE & obj->i2c.events; default: // An error situation has arisen. // Disable interrupt i2c_enable_interrupt(obj, 0, false); unblockSleepMode(EM1); // return error return I2C_EVENT_ERROR & obj->i2c.events; } }
/********************************************************************** * 8025T向寄存器写数据驱动函数 **********************************************************************/ uint8_t drv_R8025T_write(uint8_t addr, uint8_t* data, uint8_t len) { // bool result = false; // uint8_t idx; // uint8_t try_count; // uint32_t star_tick; /* Transfer structure */ I2C_TransferSeq_TypeDef i2cTransfer;// /* Initializing I2C transfer */ i2cTransfer.addr = R8025T_SLAVE_ADDRESS; i2cTransfer.flags = I2C_FLAG_WRITE_WRITE; i2cTransfer.buf[0].data = (&addr); i2cTransfer.buf[0].len = 1; i2cTransfer.buf[1].data = data; i2cTransfer.buf[1].len = len; I2C_TransferInit(I2C0, &i2cTransfer); /* Sending data */ while (I2C_Transfer(I2C0) == i2cTransferInProgress){;} return 0; }
uint8_t US_ReadByte(uint8_t port){ US_Array[0] = US_DATA_REG; if(I2C_Transfer(port, US_ADDR, US_I2C_WAIT, 1, 1, US_Array, 1, US_Array)); return US_Array[0]; return 0; }
void I2C_1_ISR(void) { i2c_progress[1] = I2C_Transfer(i2c_config[1].dev); }
void I2C_0_ISR(void) { i2c_progress[0] = I2C_Transfer(i2c_config[0].dev); }
uint8_t US_ReadArray(uint8_t port, uint8_t * array){ US_Array[0] = US_DATA_REG; if(I2C_Transfer(port, US_ADDR, US_I2C_WAIT, 1, 1, US_Array, 8, array)); return 1; return 0; }
void I2C_2_ISR(void) { i2c_progress[2] = I2C_Transfer(i2c_config[2].dev); cortexm_isr_end(); }
/***************************************************************************//** * @brief * Read from IIC device * * @details * * @note * * @param[in] dev * Pointer to device descriptor * * @param[in] pos * Slave address * * @param[in] buffer * Poniter to the buffer * * @param[in] size * Buffer size in byte * * @return * Error code ******************************************************************************/ static rt_size_t rt_iic_read ( rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) { rt_err_t err_code; rt_size_t read_size; struct efm32_iic_device_t* iic; I2C_TransferSeq_TypeDef seq; I2C_TransferReturn_TypeDef ret; if (!size) { return 0; } err_code = RT_EOK; read_size = 0; iic = (struct efm32_iic_device_t*)dev->user_data; /* Lock device */ if (rt_hw_interrupt_check()) { ret = rt_sem_take(iic->lock, RT_WAITING_NO); } else { ret = rt_sem_take(iic->lock, RT_WAITING_FOREVER); } if (ret != RT_EOK) { return ret; } if (iic->state & IIC_STATE_MASTER) { seq.addr = (rt_uint16_t)pos << 1; if (*(rt_uint8_t *)buffer == IIC_OP_READ_ONLY) { seq.flags = I2C_FLAG_READ; /* Set read buffer pointer and size */ seq.buf[0].data = (rt_uint8_t *)buffer; seq.buf[0].len = size; } else { seq.flags = I2C_FLAG_WRITE_READ; /* Set register to be read */ seq.buf[0].data = (rt_uint8_t *)buffer; seq.buf[0].len = 1; /* Set read buffer pointer and size */ seq.buf[1].data = (rt_uint8_t *)buffer; seq.buf[1].len = size; } /* Do a polled transfer */ iic->timeout = false; rt_timer_stop(iic->timer); rt_timer_start(iic->timer); ret = I2C_TransferInit(iic->iic_device, &seq); while ((ret == i2cTransferInProgress) && !iic->timeout) { ret = I2C_Transfer(iic->iic_device); } if (ret != i2cTransferDone) { iic_debug("IIC: read error %x\n", ret); iic_debug("IIC: read address %x\n", seq.addr); iic_debug("IIC: read data0 %x -> %x\n", seq.buf[0].data, *seq.buf[0].data); iic_debug("IIC: read len0 %x\n", seq.buf[0].len); iic_debug("IIC: read data1 %x -> %x\n", seq.buf[1].data, *seq.buf[1].data); iic_debug("IIC: read len1 %x\n", seq.buf[1].len); err_code = (rt_err_t)ret; } else { read_size = size; iic_debug("IIC: read size %d\n", read_size); } } else { rt_uint8_t* ptr; ptr = buffer; /* interrupt mode Rx */ while (size) { rt_base_t level; struct efm32_iic_int_mode_t *int_rx; int_rx = iic->rx_buffer; /* disable interrupt */ level = rt_hw_interrupt_disable(); if (int_rx->read_index != int_rx->save_index) { /* read a character */ *ptr++ = int_rx->data_ptr[int_rx->read_index]; size--; /* move to next position */ int_rx->read_index ++; if (int_rx->read_index >= IIC_RX_BUFFER_SIZE) { int_rx->read_index = 0; } } else { /* set error code */ err_code = -RT_EEMPTY; /* enable interrupt */ rt_hw_interrupt_enable(level); break; } /* enable interrupt */ rt_hw_interrupt_enable(level); } read_size = (rt_uint32_t)ptr - (rt_uint32_t)buffer; iic_debug("IIC: slave read size %d\n", read_size); } /* Unlock device */ rt_sem_release(iic->lock); /* set error code */ rt_set_errno(err_code); return read_size; }
/***************************************************************************//** * @brief * Write to IIC device * * @details * * @note * * @param[in] dev * Pointer to device descriptor * * @param[in] pos * Slave address * * @param[in] buffer * Poniter to the buffer * * @param[in] size * Buffer size in byte * * @return * Error code ******************************************************************************/ static rt_size_t rt_iic_write ( rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) { rt_err_t err_code; rt_size_t write_size; struct efm32_iic_device_t* iic; I2C_TransferSeq_TypeDef seq; I2C_TransferReturn_TypeDef ret; if (!size) { return 0; } err_code = RT_EOK; write_size = 0; iic = (struct efm32_iic_device_t*)dev->user_data; /* Lock device */ if (rt_hw_interrupt_check()) { ret = rt_sem_take(iic->lock, RT_WAITING_NO); } else { ret = rt_sem_take(iic->lock, RT_WAITING_FOREVER); } if (ret != RT_EOK) { return ret; } if (iic->state & IIC_STATE_MASTER) { seq.addr = (rt_uint16_t)pos << 1; seq.flags = I2C_FLAG_WRITE; /* Set write buffer pointer and size */ seq.buf[0].data = (rt_uint8_t *)buffer; seq.buf[0].len = size; } else { // TODO: Slave mode TX } /* Do a polled transfer */ iic->timeout = false; rt_timer_stop(iic->timer); rt_timer_start(iic->timer); ret = I2C_TransferInit(iic->iic_device, &seq); while ((ret == i2cTransferInProgress) && !iic->timeout) { ret = I2C_Transfer(iic->iic_device); } if (ret != i2cTransferDone) { err_code = (rt_err_t)ret; } else { write_size = size; } /* Unlock device */ rt_sem_release(iic->lock); /* set error code */ rt_set_errno(err_code); return write_size; }