EmbDev.net

Forum: ARM programming with GCC/GNU tools STM32F051 I2C slave problem


Author: klaus (Guest)
Posted on:

Rate this post
0 useful
not useful
Hi,

I have in a STM32F051k project a problem with the I2C as Slave.

I send from an AVR:
Start/address Wr/command/repStart/address RD/ ... read information /
Stop)
The read information is command/count/data.

Exact once everything is ok but then I come
Seldom times to the point for sending the count, but never again to 
sending the data.

Most comments are in German, sorry.
#define OUT_STATE_NC       0
#define OUT_STATE_CMD      1
#define OUT_STATE_LENGTH   2
#define OUT_STATE_DATA     3


unsigned char Info[128]; 
unsigned char State[64]; 

__IO unsigned char InputCounter;
__IO unsigned char OutputCounter;
__IO unsigned char Output_State;
__IO unsigned char Data_Out_Max;

__IO unsigned char data_in[MAXBYTES+1]; 
unsigned char *pData_Out;   /* Pointer auf die Ausgabe Daten */

unsigned char Data_Cmd;

TBOOL bRecStart;

volatile TBOOL new_data; /* 1 = neue daten */

__IO uint16_t IIC_Direction;


void I2C1_IRQHandler(void)
{
   if (I2C_GetITStatus(I2C1,I2C_IT_ADDR)) //  meine Adresse erkannt?
   {
      I2C_ClearITPendingBit (I2C1,I2C_IT_ADDR);

      // Start
      IIC_Direction = I2C_GetTransferDirection(I2C1);
      if (IIC_Direction == I2C_Direction_Transmitter) // IIC Write ?   AVR -> ARM
      {
         InputCounter = 0;
         OutputCounter = 0;
         Data_Out_Max = 0;
         Output_State = OUT_STATE_NC;
         bRecStart = TRUE; /* setze flag; System ist am empfangen */
      }
      else // IIC Read ARM -> AVR
      {
         if (InputCounter == 1) /* nur die Register Adresse vorher empfangen?*/
         {
            Output_State = OUT_STATE_CMD;
            Data_Cmd = data_in[0];
            switch (data_in[0])
            {
            case B_GET_INFO:
               pData_Out = (unsigned char *)&Info;
               Data_Out_Max = sizeof (Info);
               break;
            case B_GET_STATUS:
               pData_Out = (unsigned char *)&State;
               Data_Out_Max = sizeof (State);
               break;
            default :
               Data_Out_Max = 0;
               break;
            }
         }
         else
         {
            Output_State = OUT_STATE_NC;
         }
         OutputCounter = 0;
         InputCounter = 0;
      }
   }
   else if (I2C_GetITStatus(I2C1,I2C_IT_STOPF)) // Stopp erkannt?
   {
      I2C_ClearITPendingBit (I2C1,I2C_IT_STOPF);

      // Stop
      Data_Out_Max = 0;
      OutputCounter = 0;
      Output_State = OUT_STATE_NC;

      if (bRecStart != FALSE)
      {
         if (InputCounter == MAXBYTES) /*   alle daten empfangen ?*/
         {
            new_data = TRUE;
         }
      } /* else ->> komme aus nicht def. zustand */

      bRecStart = FALSE; /* loesche flag, Daten Empfang laeuft */
   }
   else  if (I2C_GetITStatus(I2C1,I2C_IT_RXNE)) //  was empfangen?
   {
      uint8_t In_Datum;

      In_Datum = I2C_ReceiveData(I2C1);

      if (InputCounter >= MAXBYTES) /* zu viele Daten empfangen ? */
      {
         bRecStart = FALSE; /* loesche flag, Daten Empfang laeuft */
      }
      else /* Kann noch Daten empfangen ! */
      {
         if (bRecStart == TRUE) /* laeuft Daten Empfang ? */
         {
            data_in[InputCounter] = In_Datum; // das sind die Daten -> also speichern
            InputCounter++;
         }
      }
      Data_Out_Max = 0;
      Output_State = OUT_STATE_NC;

      //I2C_ClearITPendingBit (I2C1,I2C_IT_RXNE); // macht das auslesen schon
   }   
   else   if (I2C_GetITStatus(I2C1,I2C_IT_TXIS)) //  gesendet ?
   {
      I2C_ClearITPendingBit (I2C1,I2C_IT_TXIS);

      switch(Output_State)
      {
      case OUT_STATE_CMD:
         I2C_SendData(I2C1, Data_Cmd);    // 1. Byte ist der Befehl zu dem die Daten passen
         Output_State = OUT_STATE_LENGTH;
         break;
      case OUT_STATE_LENGTH:
         I2C_SendData(I2C1, Data_Out_Max); // 2. Byte ist die Laenge
         Output_State = OUT_STATE_DATA;
         break;
      case OUT_STATE_DATA:
         if (OutputCounter < Data_Out_Max)  // Kann ich noch Daten senden?
         {
            I2C_SendData(I2C1, (*pData_Out));
            pData_Out++;
            OutputCounter++;

            if (OutputCounter >= Data_Out_Max)  // Kann ich noch Daten senden?
            {
                Output_State = OUT_STATE_NC;
            }
         }
         else
         {
            Output_State = OUT_STATE_NC;
            I2C_SendData(I2C1, 0); // sende NULL -> es wird zu viel abgefragt!
         }
         break;
      case OUT_STATE_NC:
      default:
          I2C_SendData(I2C1, 0); // sende NULL -> es wird mist abgefragt!
         break;
      }
   }
    else  if (I2C_GetITStatus(I2C1,I2C_IT_NACKF)) //  erkannt?
   {
      I2C_ClearITPendingBit (I2C1,I2C_IT_NACKF);
   }
   else   if (  (I2C_GetITStatus(I2C1,I2C_IT_BERR)) //  Fehler erkannt?
      || (I2C_GetITStatus(I2C1,I2C_IT_ARLO)) //  Fehler erkannt?
      )
   {
      // Sollte nicht passieren
      InputCounter = 0;
      OutputCounter = 0;
      Data_Out_Max = 0;

      I2C_ClearITPendingBit (I2C1,I2C_IT_BERR);
      I2C_ClearITPendingBit (I2C1,I2C_IT_ARLO);
   }
}



void Twi_Init(void)
{
   I2C_InitTypeDef  I2C_InitStructure;
   NVIC_InitTypeDef NVIC_InitStructure;
   GPIO_InitTypeDef  GPIO_InitStructure;

   InputCounter = 0x00;
   Data_Cmd = B_GET_NC;
   bRecStart = FALSE; /* loesche flag, daten empfang laeuft */

   // Ausgabe blockieren
   Data_Out_Max = 0;
   OutputCounter = 0;
   Output_State = OUT_STATE_NC;

   I2C_DeInit(I2C1);
   
  /*!< I2C Periph clock enable */
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

   /*!<  GPIO clock enable */
   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

   RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);

   GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_1);
   GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_1);

     /* Configure I2C pins:  SDA & SCL  ----------------------------*/
   GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
   GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
   GPIO_Init(GPIOB, &GPIO_InitStructure);

   /*!< I2C Init */
   I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
   I2C_InitStructure.I2C_Timing = 100000;
   I2C_InitStructure.I2C_DigitalFilter = 0;
   I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
   I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
   I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
   I2C_InitStructure.I2C_OwnAddress1 = MYADDR;
   I2C_Init(I2C1, &I2C_InitStructure);

   /* Enable I2C event interrupt */
   I2C_ITConfig(I2C1, (I2C_IT_ERRI | I2C_IT_STOPI | I2C_IT_ADDRI | I2C_IT_RXI  | I2C_IT_TXI), ENABLE); // I2C_IT_NACKI 

  /* Configure the I2C event priority */
   NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);

  I2C_Cmd(I2C1, ENABLE);/* I2C ENABLE */
}

Regards,
Klaus

Author: klaus (Guest)
Posted on:

Rate this post
0 useful
not useful
Is there really nobody who can help me?

Author: klaus (Guest)
Posted on:

Rate this post
0 useful
not useful
OK I found that the first communication is activating 2 times the TX int 
after the address + Wr and than just once.

Maybe this information can help to solve my problem.

Author: klaus (Guest)
Posted on:

Rate this post
0 useful
not useful
Just add a I2C_SoftwareResetCmd(I2C1); at the end of the stop part and 
it is working.

A I2C_ClearFlag(I2C1, I2C_FLAG_TXE); at the beginnig of the address 
match didn't work.

klaus

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.