2015-12-07 01:40 PM
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:StartSend the addresswrite the register number (1 byte)StartSend the addressRead the register content (2 byte)StopHere 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, Edovoid 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;}2015-12-09 06:29 AM
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.
2015-12-10 11:18 AM
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 mandatory2015-12-10 12:40 PM
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);
}