Other Parts Discussed in Thread: MSPM0G3507, SYSCONFIG
Tool/software:
Hi,
Can we transmit data from one I2C port to another I2C port within the same controller?
Launchpad which I am using is: MSPM0G3507
Thank you
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:
Hi,
Can we transmit data from one I2C port to another I2C port within the same controller?
Launchpad which I am using is: MSPM0G3507
Thank you
Hi Tejal,
Sure. You could set one I2C as controller and another as slave and just connect SCL and SDA pin together.
Do I also need to connect pull-up resistors for I2C communication? and could you provide a simple sample code for setting up I2C communication.
Thank you,
Tejal
Hi Tejal,
Yes, you could either use the internal pull-up resistors or external pull-up resistors.
As for example, you could merge the i2c controller and target example into one project for you application. The interrupt example could be used for i2c target.
Hi Pengfei,
I tried merging the I2C controller and target example, but I am not getting an acknowledgment from the target device. I am also attaching the output which I observed on the logic analyzer.
Thank you,
Tejal
Which examples did you merge? I expect you'd want to use an interrupt-driven model on the target side.
Did you change the target I2C address on both sides?
Yes I changed the I2C address on both side and also, I am using interrupt driven code on target side, and following 2 examples I merged:
1) i2c_controller_multibyte_fifo_poll and 2) i2c_target_multibyte_fifo_interrupt
Hi Tejal,
It is correct that you are using the interrupt example for I2C target.
There are some items you could check:
Best Regards,
Pengfei
Can you post your resulting (merged) code? Sometimes all it takes is a typo.
----------------
For the target side, the contents of main() should be suitable for a "target_init()" function, except for:
DL_SYSCTL_enableSleepOnExit();
This should be removed, since it has a global effect on the program. (It could produce the symptom you're seeing.)
while (1) { __WFI(); }
This should be removed. (I'm guessing you already did this one.)
Thank you for your feedback. I have made the necessary adjustments to the code as per your suggestions. I am attaching the updated code for your review. Could you please check the resulting (merged) code?
#include <ti/driverlib/m0p/dl_interrupt.h> #include "ti_msp_dl_config.h" #define I2C_TX_PACKET_SIZE (8) #define I2C_RX_PACKET_SIZE (5) #define I2C_TX_MAX_PACKET_SIZE (16) #define I2C_RX_MAX_PACKET_SIZE (16) uint8_t gTxPacket[I2C_TX_PACKET_SIZE] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; volatile uint8_t gRxPacket[I2C_RX_PACKET_SIZE]; uint32_t gTxLen, gTxCount; /* Data sent to Controller in response to Read transfer */ uint8_t gTxPacket1[I2C_TX_MAX_PACKET_SIZE] = {0x00}; volatile uint8_t gRxPacket1[I2C_RX_MAX_PACKET_SIZE]; uint32_t gRxLen, gRxCount; int main(void) { SYSCFG_DL_init(); gTxCount = 0; gTxLen = I2C_TX_MAX_PACKET_SIZE; DL_I2C_enableInterrupt(I2C_1_INST, DL_I2C_INTERRUPT_TARGET_TXFIFO_TRIGGER); /* Initialize variables to receive data inside RX ISR */ gRxCount = 0; gRxLen = I2C_RX_MAX_PACKET_SIZE; DL_I2C_fillControllerTXFIFO(I2C_0_INST, &gTxPacket[0], I2C_TX_PACKET_SIZE); /* Wait for I2C to be Idle */ while (!( DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_IDLE)) ; DL_I2C_startControllerTransfer(I2C_0_INST, I2C_1_TARGET_OWN_ADDR, DL_I2C_CONTROLLER_DIRECTION_TX, I2C_TX_PACKET_SIZE); /* Poll until the Controller writes all bytes */ while (DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS) ; /* Trap if there was an error */ if (DL_I2C_getControllerStatus(I2C_0_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_0_INST) & DL_I2C_CONTROLLER_STATUS_IDLE)) ; /* Add delay between transfers */ delay_cycles(1000); DL_I2C_startControllerTransfer(I2C_0_INST, I2C_1_TARGET_OWN_ADDR, DL_I2C_CONTROLLER_DIRECTION_RX, I2C_RX_PACKET_SIZE); for (uint8_t i = 0; i < I2C_RX_PACKET_SIZE; i++) { while (DL_I2C_isControllerRXFIFOEmpty(I2C_0_INST)); gRxPacket[i] = DL_I2C_receiveControllerData(I2C_0_INST); } while (1) { } } void I2C_1_INST_IRQHandler(void) { static bool dataRx = false; switch (DL_I2C_getPendingInterrupt(I2C_1_INST)) { case DL_I2C_IIDX_TARGET_START: /* Initialize RX or TX after Start condition is received */ gTxCount = 0; gRxCount = 0; dataRx = false; /* Flush TX FIFO to refill it */ DL_I2C_flushTargetTXFIFO(I2C_1_INST); break; case DL_I2C_IIDX_TARGET_RXFIFO_TRIGGER: /* Store received data in buffer */ dataRx = true; while (DL_I2C_isTargetRXFIFOEmpty(I2C_1_INST) != true) { if (gRxCount < gRxLen) { gRxPacket1[gRxCount++] = DL_I2C_receiveTargetData(I2C_1_INST); } else { /* Prevent overflow and just ignore data */ DL_I2C_receiveTargetData(I2C_1_INST); } } break; case DL_I2C_IIDX_TARGET_TXFIFO_TRIGGER: /* Fill TX FIFO if there are more bytes to send */ if (gTxCount < gTxLen) { gTxCount += DL_I2C_fillTargetTXFIFO( I2C_1_INST, &gTxPacket1[gTxCount], (gTxLen - gTxCount)); } else { while (DL_I2C_transmitTargetDataCheck(I2C_1_INST, 0x00) != false) ; } break; case DL_I2C_IIDX_TARGET_STOP: /* If data was received, echo to TX buffer */ if (dataRx == true) { for (uint16_t i = 0; (i < gRxCount) && (i < I2C_TX_MAX_PACKET_SIZE); i++) { gTxPacket1[i] = gRxPacket1[i]; DL_I2C_flushTargetTXFIFO(I2C_1_INST); } dataRx = false; } break; default: break; } }
> DL_I2C_enableInterrupt(I2C_1_INST, DL_I2C_INTERRUPT_TARGET_TXFIFO_TRIGGER);
After this, I think you need additionally (I'm guessing at the IRQN name):
> NVIC_EnableIRQ(I2C_1_IRQN); // Enable Target interrupt in NVIC
----------
But this wouldn't result in a NACK. I wonder if the I2C_1 (target) setup in ti_msp_dl_config.c is missing a call to:
> DL_I2C_setTargetOwnAddress(I2C_1_INST, I2C_1_TARGET_OWN_ADDR);
This is generated by sysconfig in the Example, but maybe it got lost in the merge?
----------
More generally, it seems that you're using the same Tx/Rx buffers for both sides. Maybe you've checked that it works OK, but it seems hazardous at first glance.