AnsweredAssumed Answered

STM32F051 as i2c slave - not 100% successful

Question asked by pechacek.jakub on Jul 4, 2017
Latest reply on Jul 6, 2017 by waclawek.jan

Hi,

in my implementation, i2c slave address recognition on STM32F051 is not 100%. Following communication works well. I'm using DMA. When I set HCLK frequency to 8MHz (from HSI source), probability of address ACK and establishing i2c communication is about 10-20%. When I set HCLK frequency to 1 or 2 MHz, probability is nearly 100%. I have no explanation of this behaviour. This isn't dependent on i2c bus speed. Same on 20kHz and 400kHz. When address is missed on bus, no interrupt is generated.

 

I've read errata, but without luck. Increasing SYSCLK to 16MHz by PLL and selecting it as i2c clock source, didn't helped too. Shape of i2c signal is good. i2c timing configuration is from STM32CubeMX but project use StdPeriph drivers.

 

Tested on two discovery boards and on custom PCBs. Same behaviour.

 

Initialization of i2c

void init_I2C_DMA(I2C_TypeDef* I2Cx, uint8_t i2c_address)
{
I2C_InitTypeDef I2C_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
/*========================== Init I2C RCC =================================*/
/* I2C Periph clock enable */
if(I2Cx == I2C1)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
else
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);
/* DeInit I2C */
I2C_DeInit(I2Cx);
I2C_SlaveByteControlCmd(I2Cx, ENABLE);
I2C_ReloadCmd(I2Cx,ENABLE);
I2C_NumberOfBytesConfig(I2Cx, 0xFF);
I2C_StopModeCmd(I2Cx, ENABLE);

/* I2C configuration -------------------------------------------------------*/
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStructure.I2C_DigitalFilter = 0x00;
I2C_InitStructure.I2C_OwnAddress1 = i2c_address << 1;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
//I2C_InitStructure.I2C_Timing = 0x00108EFB; //standart mode 20kHz
//I2C_InitStructure.I2C_Timing = 0x00101D7C; //standart mode 50kHz
//I2C_InitStructure.I2C_Timing = 0x2000090E; //standart mode 100kHz
I2C_InitStructure.I2C_Timing = 0x0000020B; //fast mode 400kHz
//I2C_InitStructure.I2C_Timing = 0x00000001; //fast mode plus 1MHz
I2C_Init(I2Cx, &I2C_InitStructure);

I2C_ITConfig(I2Cx, I2C_IT_TCI, ENABLE);
I2C_ITConfig(I2Cx, I2C_IT_ERRI, ENABLE);
I2C_ITConfig(I2Cx, I2C_IT_STOPI, ENABLE);
I2C_ITConfig(I2Cx, I2C_IT_NACKI, ENABLE);
I2C_ITConfig(I2Cx, I2C_IT_ADDRI, ENABLE);
/* DMA TRANSMITTER Configuration */
/* DMA1 Channel2 Config */
DMA_DeInit(DMA1_Channel2);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)I2C_TXDR_ADDRESS;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)i2c_transfering_data;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 0xFF;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel2, &DMA_InitStructure);
/* DMA RECEIVER Configuration */
/* DMA1 Channel3 Config */
DMA_DeInit(DMA1_Channel3);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)I2C_RXDR_ADDRESS;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)i2c_transfering_data;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 0xFF;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel3, &DMA_InitStructure);
/* DMA1 Channel2 enable */
DMA_Cmd(DMA1_Channel2, ENABLE);
/* DMA1 Channel3 enable */
DMA_Cmd(DMA1_Channel3, ENABLE);
I2C_DMACmd(I2Cx,I2C_DMAReq_Tx,ENABLE);
I2C_DMACmd(I2Cx,I2C_DMAReq_Rx,ENABLE);
/* Configure the I2C interrupt priority */
#ifdef I2C2_IRQn
if(I2Cx == I2C1)
NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;
else
NVIC_InitStructure.NVIC_IRQChannel = I2C2_IRQn
#else
NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;
#endif
NVIC_InitStructure.NVIC_IRQChannelPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable I2C1 */
I2C_Cmd(I2Cx, ENABLE);
}

 

Thanks for any advice. What should i try??

Outcomes