AnsweredAssumed Answered

I2C on STM32F4, missing TX after sending Address, Data

Question asked by uli stone on Dec 14, 2017
Latest reply on Dec 14, 2017 by Clive One

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

#include "stm32f4xx.h"

 

#define WORKING   GPIOD->ODR ^= 1<<15

#define ACTION    GPIOD->ODR |= 1<<11

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

#define ADDRESS    GPIOD->ODR |= 1<<12

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

#define WRITE    GPIOD->ODR |= 1<<13

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

#define READ    GPIOD->ODR |= 1<<14

#define 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="#linkSR">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="#linkcontrol"> 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="#linkSR">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

Outcomes