cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F0, I2C sends wrong data.

hotek
Associate II
Posted on December 18, 2013 at 21:57

Hello.

I have a problem to cinfigure I2C.

This is my code:

&sharpdefine    PRESC    0x0B

&sharpdefine    SCLL    0x13

&sharpdefine    SCLH    0x0F

&sharpdefine    SDADEL    0x02

&sharpdefine    SCLDEL    0x04

 

void I2C_PCF_init()

{

    RCC->AHBENR|=RCC_AHBENR_GPIOBEN;

    GPIOB->MODER|= GPIO_MODER_MODER6_1|GPIO_MODER_MODER7_1; 

    GPIOB->OSPEEDR|=GPIO_OSPEEDER_OSPEEDR6|GPIO_OSPEEDER_OSPEEDR7;//predkosc 50MHZ

    GPIOB->AFR[0]|=0x11000000;    //AF1

 

    RCC->APB1ENR|=RCC_APB1ENR_I2C1EN ;        //enable clock for I2C1

 

    I2C1->CR1|=I2C_CR1_PE;                    //set PE

    I2C1->CR1&=~I2C_CR1_PE;                    //reset PE

    while(I2C1->CR1&I2C_CR1_PE);            //while PE ==1

 

    I2C1->TIMINGR|=(PRESC << 28)|(SCLL<<0)|(SCLH<<8)|(SCLDEL<<20)|(SDADEL<<16); //configure for 48Mhz clock

 

    I2C1->CR1|=I2C_CR1_PE;                    //set PE

}

void I2C_PCF_send(int adress, int lenght)

{

    I2C1->CR2|=(adress<<0)|(lenght<<16)|I2C_CR2_ADD10;    //addres SLAVE 10bits

    I2C1->CR2 &=~ I2C_CR2_RD_WRN;                        //write

    I2C1->CR2 |= I2C_CR2_START;

 

    I2C1->TXDR=0xff;

    while(I2C1->ISR&I2C_ISR_TXIS);            //wait for TXDR will be empty and data was send.

 

    I2C1->CR2|=I2C_CR2_STOP;

}

No matter what i write after this part:

I2C1->CR2 |= I2C_CR2_START;

I2C sending data like this:

0690X00000603GuQAI.jpg

Can somebody tell me what im doing wrong, and why data from buffer TXDR are not sent?

#problem #stm32f0-i2c
2 REPLIES 2
chen
Associate II
Posted on December 19, 2013 at 11:30

Hi

I think

    I2C1->CR2|=(adress<<0)|(lenght<<16)|I2C_CR2_ADD10;    //addres SLAVE 10bits

    I2C1->CR2 &=~ I2C_CR2_RD_WRN;                        //write

    I2C1->CR2 |= I2C_CR2_START;

Tells the I2C controller to send the start bit and the device address.

BUT then you immediately do

   I2C1->TXDR=0xff;

Then try to wait for the data to be transmitted.

      while(I2C1->ISR&I2C_ISR_TXIS);

You need to wait for the start bit and the device address to complete before trying to send the data. You need to add another ''while(I2C1->ISR&I2C_ISR_TXIS);'' or something before the ''I2C1->TXDR=0xff;''

Some points to consider :

1. READ THE MANUAL/DATA SHEET! Understand the I2C controller.

2. The while loops do not have any timeout/escape conditions - your program could get stuck at the while loops.

hotek
Associate II
Posted on December 19, 2013 at 19:28

Thank you for response.

The problem was here:

 I2C1->CR2|=(adress<<0)|(lenght<<16)|I2C_CR2_ADD10;    //address SLAVE 10bits

I was try to send 8 bits address, but that was send only 2 MSBs on 10bits mode, and slave dont send ACK, so master try to send again that 2 bits. This is working ''write'' code:

void I2C_PCF_send(int address, int length)

{

    while ((I2C1->ISR & I2C_ISR_TXE)==0);    //while TXE ==0, buffer is full

    I2C1->CR2|=(address<<0)|(length<<16)| I2C_CR2_AUTOEND ;    //address SLAVE 7bits

    I2C1->CR2 &=~ I2C_CR2_RD_WRN;                        //write

    I2C1->CR2 |= I2C_CR2_START;

    while ((I2C1->ISR & I2C_ISR_TXE)==0);    //while TXE ==0, buffer is full

    I2C1->TXDR=0xff;

}