cancel
Showing results for 
Search instead for 
Did you mean: 

I2C on STM32F4, missing TX after sending Address, Data

uli stone
Associate II
Posted on December 14, 2017 at 22:21

Hi,

I'm using a STM32F429l-DISC1 Board and trying to get I2C working.

Somehow my code fails, and I come back to the code from:

https://sites.google.com/site/johnkneenmicrocontrollers/18b-i2c/i2c_stm32f407

Now I want to send the adress 0x66, then the Data 0x24 and 0x04. This is working perfectly,

but then I want to send the Address 0x67 which still works, then 0x24 and 0x04 which does not work, because the I2C TX Resgister is missing the correct falue!

Strangely I get on the I2C Bus a 0xBE after the 0x67 address!

See logic analyser: ?

Logic analyser Data

Time [s], Analyzer Name, Decoded Protocol Result

2.639135875000000,I2C,Setup Write to [0x66] + ACK

2.639227250000000,I2C,0x24 + ACK

2.639317562500000,I2C,0x04 + ACK

2.639424625000000,I2C,Setup Read to [0x67] + ACK

2.639514875000000,I2C,0xBE + NAK

?

My Full code is here

&sharpinclude 'stm32f4xx.h'

&sharpdefine WORKING   GPIOD->ODR ^= 1<<15

&sharpdefine ACTION    GPIOD->ODR |= 1<<11

&sharpdefine ACTION_E  GPIOD->ODR &= ~(1<<11)

&sharpdefine ADDRESS    GPIOD->ODR |= 1<<12

&sharpdefine ADDRESS_E  GPIOD->ODR &= ~(1<<12)

&sharpdefine WRITE    GPIOD->ODR |= 1<<13

&sharpdefine WRITE_E  GPIOD->ODR &= ~(1<<13)

&sharpdefine READ    GPIOD->ODR |= 1<<14

&sharpdefine READ_E  GPIOD->ODR &= ~(1<<14)

void I2C_Start() {

      ACTION;//To highlight start on MSO

      I2C1->CR1 |= 1<<8;                        //I2C Start

          while (!(I2C1->SR1 & 0x0001));//wait for start bit

}//subsequent access of data register will clear start bit

void I2C_Stop (void) {

   I2C1->CR1 |= 0x0200;

          while (I2C1->SR2 & 0x0002);   //wait for BUSY set

    ACTION_E; //Highlight stop on MSO

}//I2C Transfer now complete

void I2C_Write (unsigned char c) {

      WRITE;//Indicate write on MSO

    I2C1->DR = c;

          while (!(I2C1->SR1 & (1<<7)));   // Wait TxE bit set - <A HREF='&sharplinkSR'>see status register</A>

      WRITE_E;

}//Could also wait until BTF (Byte Transfer Complete)

unsigned char I2C_Read (int ack) {

  READ; //Indicate read on MSO

    if (ack) I2C1->CR1 |=  0x0400;    //multiple bytes - set acknowledge bit in<A HREF='&sharplinkcontrol'> I2C_CR1</A>

      else     I2C1->CR1 &= ~0x0400;    //single or last byte clear ack bit

//      while (!(I2C1->SR1 & 0x00000040));    // Wait until RxNE bit set - <A HREF='&sharplinkSR'>see status register</A>

    READ_E;

    return (I2C1->DR);

}

void I2C_Address (unsigned char adr) {

char res;

    ADDRESS; //Signal for MSO

    I2C1->DR = adr | 0;                //Write to I2C Address register

        while (!(I2C1->SR1 & 0x0002));    //wait until address sent

    res = (I2C1->SR2);       //dummy read to clear

    ADDRESS_E;

}

void Delay( ) {

    int i;

    for (i=0; i<400000; i++);

}

int main ( ) {

    RCC->AHB1ENR |= 1<<3;     //Clocks for GPIOD

  GPIOD->MODER |= 0x55400000; //Bits 11..15 are output

    GPIOD->MODER  |= 1<<8;      //PB4 reset to CS43L22

  GPIOD->ODR    |= 1<<4;      //set high

//configure the AF

  RCC->AHB1ENR |= 1<<1;        //Clock for  GPIOB

  RCC->APB1ENR |= 1 <<21; //clock to I2C1

    GPIOB->AFR[0] |= (4<< 24);  //enable SCK to PB6

  GPIOB->AFR[1] |= (4<< 4);  //enable SDA to PB9

  GPIOB->MODER &= ~(3 << 12); //clear bits 12 & 13 (PB6)

  GPIOB->MODER |= 2 << 12; //MODER6[1:0] = 10 bin

  GPIOB->MODER &= ~(3 << 18); //clear bits 18 & 19 (PB9)

  GPIOB->MODER |= 2 << 18; //MODER9[1:0] = 10 bin

    GPIOB->OTYPER |= 1 <<6; //PB6 open drain

  GPIOB->OTYPER |= 1<<9; //PB9 open drain

    GPIOB->PUPDR &= ~(3 << 12);//clear bits 12 & 13 (PB6)

  GPIOB->PUPDR &= ~(3 << 18);//clear bits 18 & 19 (PB9)

    //Configure the I2C

    I2C1->CR2     = 0x0010; //16MHz HSI

    I2C1->CCR     = 0x0050; //100kHz Bit rate

    I2C1->TRISE   = 0x0011; //1000 ns / 62.5 ns = 16 + 1

    I2C1->CR1    = 0x0001;      //enable peripheral

    char res;

    while (1){

            I2C_Start();

            I2C_Address(0x66);     //Write address of slave

            I2C_Write (0x24);

            I2C_Write (0x04);

            I2C_Start();

            I2C_Address(0x67);

            I2C_Write (0x24);

            I2C_Write (0x04);

            I2C_Stop();

          Delay();

          WORKING;              //visible indication that I2C didn't stall

    }

}

Does anyone know how to fix my problem? any advice?

Thank you

##i2c ##stm32f4
1 REPLY 1
Posted on December 14, 2017 at 23:56

Look, the low order bit of the I2C address defines the direction of the transaction (high order 7-bit slave address, low order R/W bit). Writing a ONE indicates you're READING, so you can't jam data back at the Slave.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..