This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Tool/software:
I develop a SW code on a MSPM0C1104 EVB.
Now, we need to read the register contents from the slave I2C device.
The spec. of this I2C device reading timing is
Reading flow of this device is:
I2C_START, Slave_Addr+W, Reg_Addr,
I2C_START, Slave_Addr+R, Data1, Data2, Data3, Data4, I2C_STOP.
I use and modify from the sample code "C:\ti\mspm0_sdk_2_03_00_07\examples\nortos\LP_MSPM0C1104\driverlib\i2c_controller_rw_multibyte_fifo_poll".
#include "ti_msp_dl_config.h" /* * Number of bytes to send from Controller to target. * This example uses FIFO with polling, and the maximum FIFO size is 4. * Refer to interrupt examples to handle larger packets */ #define I2C_TX_PACKET_SIZE (3) /* * Number of bytes to received from target. * This example uses FIFO with polling, and the maximum FIFO size is 4. * Refer to interrupt examples to handle larger packets */ #define I2C_RX_PACKET_SIZE (3) /* Data sent to the Target */ uint8_t gTxPacket[I2C_TX_PACKET_SIZE] = {0x00, 0x61, 0x00}; /* Read Register Address*/ uint8_t gRegisterAddr[2] = {0x10, 0x14}; /* Data received from Target */ volatile uint8_t gRxPacket[I2C_RX_PACKET_SIZE]; /* I2C Target address */ #define I2C_TARGET_ADDRESS (0x29) int main(void) { SYSCFG_DL_init(); /* Set LED to indicate start of transfer */ DL_GPIO_setPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN); /* * Fill FIFO with data. This example will send a MAX of 4 bytes since it * doesn't handle the case where FIFO is full */ DL_I2C_fillControllerTXFIFO(I2C_INST, &gTxPacket[0], I2C_TX_PACKET_SIZE); /* Wait for I2C to be Idle */ while (!( DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_IDLE)) ; /* Send the packet to the controller. * This function will send Start + Stop automatically. */ DL_I2C_startControllerTransfer(I2C_INST, I2C_TARGET_ADDRESS, DL_I2C_CONTROLLER_DIRECTION_TX, I2C_TX_PACKET_SIZE); /* Poll until the Controller writes all bytes */ while (DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS) ; /* Trap if there was an error */ if (DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_ERROR) { /* LED will remain high if there is an error */ __BKPT(0); } /* Wait for I2C to be Idle */ while (!( DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_IDLE)) ; /* Add delay between transfers */ delay_cycles(1000); /* Send a read request to Target */ DL_I2C_startControllerTransfer(I2C_INST, I2C_TARGET_ADDRESS, DL_I2C_CONTROLLER_DIRECTION_RX, I2C_RX_PACKET_SIZE); /* * Receive all bytes from target. LED will remain high if not all bytes * are received */ for (uint8_t i = 0; i < I2C_RX_PACKET_SIZE; i++) { while (DL_I2C_isControllerRXFIFOEmpty(I2C_INST)) ; gRxPacket[i] = DL_I2C_receiveControllerData(I2C_INST); } // Test: read target register data /* 1: Do Dummy Write */ DL_I2C_fillControllerTXFIFO(I2C_INST, &gRegisterAddr[0], 1); // Wait for I2C to be Idle */ while (!( DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_IDLE)) ; // Transfer register address w/o i2c_STOP DL_I2C_startControllerTransferAdvanced(I2C_INST, I2C_TARGET_ADDRESS, DL_I2C_CONTROLLER_DIRECTION_TX,\ 1, DL_I2C_CONTROLLER_START_ENABLE, DL_I2C_CONTROLLER_STOP_DISABLE, DL_I2C_CONTROLLER_ACK_ENABLE); // wait Poll until the Controller writes all bytes */ while (DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS) ; /* 2: Read data */ /* Wait for I2C to be Idle */ while (!( DL_I2C_getControllerStatus(I2C_INST) & DL_I2C_CONTROLLER_STATUS_IDLE)) ; /* Add delay between transfers */ delay_cycles(1000); /* Send a read request to Target */ //DL_I2C_startControllerTransfer(I2C_INST, I2C_TARGET_ADDRESS, // DL_I2C_CONTROLLER_DIRECTION_RX, I2C_RX_PACKET_SIZE); DL_I2C_startControllerTransferAdvanced(I2C_INST, I2C_TARGET_ADDRESS, DL_I2C_CONTROLLER_DIRECTION_RX,\ I2C_RX_PACKET_SIZE, DL_I2C_CONTROLLER_START_ENABLE, DL_I2C_CONTROLLER_STOP_ENABLE, DL_I2C_CONTROLLER_ACK_DISABLE); /* * Receive all bytes from target. LED will remain high if not all bytes * are received */ for (uint8_t i = 0; i < I2C_RX_PACKET_SIZE; i++) { while (DL_I2C_isControllerRXFIFOEmpty(I2C_INST)) ; gRxPacket[i] = DL_I2C_receiveControllerData(I2C_INST); } /* If write and read were successful, toggle LED */ while (1) { DL_GPIO_togglePins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN | GPIO_LEDS_USER_TEST_PIN); delay_cycles(12000000); } }
In ths main function, I add this read fucntion before the final while loop.
Unfortunately, the program is halt in I2C read because the SCK kept low
Could anyone has soltuion for this problem. Thanks
Hi, Eason
As your sugggestion, the number was modified to 2
>while (DL_I2C_getControllerStatus(I2C_INST) &
> DL_I2C_CONTROLLER_STATUS_BUSY_BUS)
BUSBSY will be set until the STOP, so it won't clear here. Try instead:
>while (DL_I2C_getControllerStatus(I2C_INST) &
> DL_I2C_CONTROLLER_STATUS_BUSY)
---------------
Or better yet: Use the RD_ON_TXEMPTY feature. Don't do the initial (TX) half-transaction, but instead call:
DL_I2C_resetControllerTransfer(I2C_INST); // Set MCTR=0 to avoid enableControllerReadOnTXEmpty hazard DL_I2C_enableControllerReadOnTXEmpty(I2C_INST); // Write then read
then do the RX part of the transaction. The I2C unit will write the bytes in the Tx FIFO, then perform the Rx transaction.