cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L4 I2C Multi Slave Issue

abotha
Associate III

Good Day

I am having an issue with I2C and hope someone can point me in the right direction.

I have an I2C master and two I2C slaves on a bus. The master sends a message to the slave and then reads back the response from the slave, which works.

If I add the second slave to the bus, the Master can still talk successfully to the one slave, but with the second slave it can only transmit the message, when it tries to read the response the slave Acks its address, but then doesn't send back the data, keeping the clock low until a timeout is detected.

If I plug out the first slave, communication to the second one works without an issue.

I have set the Slave Addresses to 0x1A and 0x1B, which after left shifting equates to 0x34 and 0x36.

It seems like when wanting to communicate with second slave, the Write succeeds, then when wanting to read the response, the Address is Acked, but thereafter there is no clock being generated.

The master has the following code for transmitting and reading the response.

It transmits the message, reads back one byte which contains the message length, and then reads again the full message.

ubMasterTransferComplete is set by the DMA Tx Transfer Complete Callback, and masterI2CRxCallback is incremented by the DMA Rx Transfer Complete Callback.

executionCounter++;
i2cMaster = TRUE;			// Used as a check in the Interrupt Callbacks
ubNbDataToTransmit = i2cTxBuffer[0];
// Disable DMA to load new length to be tranmitted
LL_DMA_DisableChannel(DMA2, LL_DMA_CHANNEL_7); 
// Load number of bytes to be transmitted with DMA
LL_DMA_SetDataLength(DMA2, LL_DMA_CHANNEL_7, ubNbDataToTransmit);	
LL_DMA_ConfigAddresses(DMA2, LL_DMA_CHANNEL_7, (uint32_t)i2cTxBuffer, (uint32_t)LL_I2C_DMA_GetRegAddr(I2C1, LL_I2C_DMA_REG_DATA_TRANSMIT), LL_DMA_GetDataTransferDirection(DMA2, LL_DMA_CHANNEL_7)); // Configure the Addresses
 
// Ensure the callback variable is zero
ubMasterTransferComplete = FALSE;		
// Enable DMA again							
 LL_DMA_EnableChannel(DMA2, LL_DMA_CHANNEL_7);						
/* (2) Initiate a Start condition to the Slave device ***********************/
//Start the transfer to address contained in i2cTxBuffer[1] (0x34 or 0x36)
LL_I2C_HandleTransfer(I2C1, i2cTxBuffer[1], LL_I2C_ADDRSLAVE_7BIT, ubNbDataToTransmit, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);	
  /* (3) Loop until end of transfer completed (DMA TC raised) *****************/
tickVal = HAL_GetTick() + 5000;				// Configure a timeout
while(!ubMasterTransferComplete)			// Wait for DMA Transfer Complete flag
 {
	if (tickVal < HAL_GetTick())
	{
		debug("Master - No Transfer CPLT\r\n");
		tickVal = HAL_GetTick() + 5000;
		 reset_I2C();
		break;
	 }
  }
if ( ubMasterTransferComplete == TRUE)			
{
/* Loop until STOP flag is raised (master raises it automatically)  */
	tickVal = HAL_GetTick() + 5000;
	while(!LL_I2C_IsActiveFlag_STOP(I2C1))
	{
		 if (tickVal < HAL_GetTick())
		{
		debug("Master - Waiting for STOP Flag\r\n");
		tickVal = HAL_GetTick() + 5000;
		}
	}
/* (5) Clear pending flags, Data consistency are checking into Slave process */
	LL_I2C_ClearFlag_STOP(I2C1);
 
	char temp2[50];
	char CR[]="\r\n";
	sprintf(temp, "Master Txed# %d Bytes: ", i2cTxBuffer[0]); // Number of Bytes received
 
		for (uint8_t i = 0; i <  i2cTxBuffer[0]; i++)
		{
			sprintf(temp2, "%02X ",  i2cTxBuffer[i]);
			strcat(temp,temp2);
		}
		strcat(temp,CR);			// Attach a line-feed to the end*/
		debugString(DUSB, temp);	// Send out over DUSB
 
		HAL_Delay(3);
 
// Get ready to ask for a response
LL_DMA_DisableChannel(DMA2, LL_DMA_CHANNEL_6); 	
// Receive the first byte of the response so that we know how many bytes are in the response	
LL_DMA_SetDataLength(DMA2, LL_DMA_CHANNEL_6, 1);	
LL_DMA_ConfigAddresses(DMA2, LL_DMA_CHANNEL_6, (uint32_t)LL_I2C_DMA_GetRegAddr(I2C1, LL_I2C_DMA_REG_DATA_RECEIVE), (uint32_t)&(aReceiveBuffer), LL_DMA_GetDataTransferDirection(DMA2, LL_DMA_CHANNEL_6));
LL_I2C_SetTransferSize(I2C1, 1);
masterI2CRxCallback = 0;	// DMA Rx Transfer Complete Flag
 
LL_I2C_HandleTransfer(I2C1, i2cTxBuffer[1], LL_I2C_ADDRSLAVE_7BIT, 1, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_READ); // Start the Read by sending a start condition with read direction
LL_DMA_EnableChannel(DMA2, LL_DMA_CHANNEL_6);		//Enable DMA Rx
 
tickVal= HAL_GetTick() + 1000;		// Configure a Timeout
while (masterI2CRxCallback == 0)	// Wait for the DMA Rx Complete Flag
{
	if (tickVal < HAL_GetTick())
	 {
		debug("Master Timeout @ masterI2CRxClbk == 0\r\n");
		break;
	  }
}
 
HAL_Delay(3);
// Get ready to ask for a response
LL_DMA_DisableChannel(DMA2, LL_DMA_CHANNEL_6); 	
// Receive the first byte of the response so that we know how many bytes are in the respons	
LL_DMA_SetDataLength(DMA2, LL_DMA_CHANNEL_6, aReceiveBuffer[0]+2);e
LL_DMA_ConfigAddresses(DMA2, LL_DMA_CHANNEL_6, (uint32_t)LL_I2C_DMA_GetRegAddr(I2C1, LL_I2C_DMA_REG_DATA_RECEIVE), (uint32_t)&(aReceiveBuffer), LL_DMA_GetDataTransferDirection(DMA2, LL_DMA_CHANNEL_6));
LL_I2C_SetTransferSize(I2C1, aReceiveBuffer[0]+2);
 
// Start the Read by sending a start condition with read direction
LL_I2C_HandleTransfer(I2C1, i2cTxBuffer[1], LL_I2C_ADDRSLAVE_7BIT, aReceiveBuffer[0]+2, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_READ);
LL_DMA_EnableChannel(DMA2, LL_DMA_CHANNEL_6);		//Enable DMA Rx
 
tickVal= HAL_GetTick() + 1000;						// Configure a Timeout
while (masterI2CRxCallback == 1)					// Wait for the DMA Rx Complete Flag
	{
		if (tickVal < HAL_GetTick())
		{
			debug("Master Timeout @ masterI2CRxClbk == 0\r\n");
			 break;
		}
	}
 
//Insert CRC Check here for message validity
 
sprintf(temp, "Master Received# %d Bytes From Slave: ", aReceiveBuffer[0]); // Number of Bytes received
for (uint8_t i = 0; i <  aReceiveBuffer[0]; i++)
{
		sprintf(temp2, "%02X ",  aReceiveBuffer[i]);
		strcat(temp,temp2);
}
strcat(temp,CR);			// Attach a line-feed to the end*/
debugString(DUSB, temp);	// Send out over DUSB
 				
while(HAL_UART_Transmit_DMA(&huart1, (uint8_t*)aReceiveBuffer,aReceiveBuffer[0]) != HAL_OK){}
 
i2cMaster = FALSE;

1 REPLY 1
abotha
Associate III

I have resolved the issue, I have changed the second slaves' Address to something different (0x28<<1 = 0x50) and also changed to a Start - Restart rather than Start-Stop-Start sequence for reading.