cancel
Showing results for 
Search instead for 
Did you mean: 

stm32F746 and I2C

Franzi.Edo
Senior
Posted on December 07, 2015 at 22:40

Hi,

Just need some help with the I2C peripheral of the 32f7. I would like to read 2 bytes from an imager Aptina. The i2c sequence is composed of 1 write cycle followed by 2 read cycles. After the write, the stop has not to be sent and a new start sequence has to take place: in a short, the sequence should be this one:

Start

Send the address

write the register number (1 byte)

Start

Send the address

Read the register content (2 byte)

Stop

Here is my test code that of course, it does not work. Any idea of how to implement this sequence? Any simple code example?

Thank you

  Regards, Edo

void i2c2_init(void) {

RCC->APB1ENR |= RCC_APB1ENR_I2C2EN;

// Initialize the I2C Master, default speed 100-KHz 0x4 0 9 1 27 32

I2C2->TIMINGR = (4<<28) // Timing prescaler

 | (9<<20) // Data setup time

 | (1<<16) // Data hold time

 | (27<<8) // SCL high period

 | (32<<0); // SCL Low period

I2C2->CR1  = (1<<12); // Analog filter off

}

void i2c2_read(uint8_t address, uint8_t *buffer) {

uint16_t i;

// Write: Send the register number

I2C2->CR2 = (1<<16) // 1 bytes to write

 | (address<<0); // The slave address

I2C2->CR2 |= (1<<13); // START

while (!(I2C2->ISR & I2C_ISR_TXE));

I2C2->TXDR = 0x23; // Register 23

// Read: Read the register 23 content

I2C2->CR2 = (1<<25) // Automatic end mode

 | (2<<16) // 2 bytes to read

 | (1<<10) // Read transfer

 | (address<<0); // The slave address

I2C2->CR2 |= (1<<13); // START

for (i = 0; i < size; i++) {

while (!(I2C2->ISR & I2C_ISR_RXNE));

// !!!!!! never reach this point

*buffer++ = I2C2->RXDR;

}

// Wait until the stop condition was automatically sent

while (!(I2C2->ISR & I2C_ISR_STOPF));

I2C2->ISR &= ~I2C_ISR_STOPF;

}

3 REPLIES 3
Amel NASRI
ST Employee
Posted on December 09, 2015 at 15:29

Hi franzi.edo,

What are you using as library? 

Have a look to the I2C examples in the STM32CubeF7 package. The possible limitation with HAL I2C APIs is that repeated start is not supported.

-Mayla-

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

megahercas6
Senior
Posted on December 10, 2015 at 20:18

Any examples how to implement restart with no stop ? Because i facing same problem, spend weekend trying to written code, disassembled library, get restart working, but somehow it data was not clocking not working, it just hangs. (on STM32L4) with STM32F4 and SPL, did that in few minutes.

Please make SPL for all new MCU, because HAL is killing us. And stop using systick even if we don't need it ! it should be user selectable, not mandatory

megahercas6
Senior
Posted on December 10, 2015 at 21:40

Just to pruve point, made this in few minutes, it works very well fist time

#include <
stm32f4xx.h
>
#include <
stm32f4xx_i2c.h
>
void Delay(uint32_t nTime);
void init_I2C1(void);
void I2C_write(I2C_TypeDef* I2Cx, uint8_t data);
void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction);
void I1C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction);
uint8_t I2C_read_ack(I2C_TypeDef* I2Cx);
uint8_t I2C_read_nack(I2C_TypeDef* I2Cx);
void I2C_stop(I2C_TypeDef* I2Cx);
volatile uint8_t a = 0, b =0, c = 0;
int main(void)
{
Delay(0xFFFFF);
init_I2C1();
while (1)
{
I2C_start(I2C1, 0xB4,I2C_Direction_Transmitter);
I2C_write(I2C1, 0x07);
I1C_start(I2C1, 0xB4,I2C_Direction_Receiver);
a= I2C_read_ack(I2C1);
b= I2C_read_ack(I2C1);
c= I2C_read_nack(I2C1);
Delay(a+b+c);
Delay(0xFFFFF);
}
}
void I2C_write(I2C_TypeDef* I2Cx, uint8_t data)
{
I2C_SendData(I2Cx, data);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}
void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction)
{
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
I2C_GenerateSTART(I2Cx, ENABLE);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2Cx, address, direction);
if(direction == I2C_Direction_Transmitter)
{
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
}
else if(direction == I2C_Direction_Receiver)
{
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
}
}
void I1C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction)
{
I2C_GenerateSTART(I2Cx, ENABLE);
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2Cx, address, direction);
if(direction == I2C_Direction_Transmitter)
{
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
}
else if(direction == I2C_Direction_Receiver)
{
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
}
}
uint8_t I2C_read_ack(I2C_TypeDef* I2Cx){
I2C_AcknowledgeConfig(I2Cx, ENABLE);
while( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) );
return I2C_ReceiveData(I2Cx);
}
uint8_t I2C_read_nack(I2C_TypeDef* I2Cx){
I2C_AcknowledgeConfig(I2Cx, DISABLE);
I2C_GenerateSTOP(I2Cx, ENABLE);
while( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) );
uint8_t data = I2C_ReceiveData(I2Cx);
return data;
}
void I2C_stop(I2C_TypeDef* I2Cx)
{
I2C_GenerateSTOP(I2Cx, ENABLE);
}
void Delay(uint32_t nTime)
{ 
while(nTime != 0)
{
nTime--;
__asm(''nop'');
}
}
void init_I2C1(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
I2C_InitTypeDef I2C_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; //SCL|SDA
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; 
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; 
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD; 
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; 
GPIO_Init(GPIOB, &GPIO_InitStruct); 
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1);// SCl
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1);// SDA
// configure I2C1 
I2C_InitStruct.I2C_ClockSpeed = 100000; 
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C; 
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; 
I2C_InitStruct.I2C_OwnAddress1 = 0x00; 
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable; 
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; 
I2C_Init(I2C1, &I2C_InitStruct); 
I2C_Cmd(I2C1, ENABLE);
}