EmbDev.net

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


von klaus (Guest)


Rate this post
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.
1
#define OUT_STATE_NC       0
2
#define OUT_STATE_CMD      1
3
#define OUT_STATE_LENGTH   2
4
#define OUT_STATE_DATA     3
5
6
7
unsigned char Info[128]; 
8
unsigned char State[64]; 
9
10
__IO unsigned char InputCounter;
11
__IO unsigned char OutputCounter;
12
__IO unsigned char Output_State;
13
__IO unsigned char Data_Out_Max;
14
15
__IO unsigned char data_in[MAXBYTES+1]; 
16
unsigned char *pData_Out;   /* Pointer auf die Ausgabe Daten */
17
18
unsigned char Data_Cmd;
19
20
TBOOL bRecStart;
21
22
volatile TBOOL new_data; /* 1 = neue daten */
23
24
__IO uint16_t IIC_Direction;
25
26
27
void I2C1_IRQHandler(void)
28
{
29
   if (I2C_GetITStatus(I2C1,I2C_IT_ADDR)) //  meine Adresse erkannt?
30
   {
31
      I2C_ClearITPendingBit (I2C1,I2C_IT_ADDR);
32
33
      // Start
34
      IIC_Direction = I2C_GetTransferDirection(I2C1);
35
      if (IIC_Direction == I2C_Direction_Transmitter) // IIC Write ?   AVR -> ARM
36
      {
37
         InputCounter = 0;
38
         OutputCounter = 0;
39
         Data_Out_Max = 0;
40
         Output_State = OUT_STATE_NC;
41
         bRecStart = TRUE; /* setze flag; System ist am empfangen */
42
      }
43
      else // IIC Read ARM -> AVR
44
      {
45
         if (InputCounter == 1) /* nur die Register Adresse vorher empfangen?*/
46
         {
47
            Output_State = OUT_STATE_CMD;
48
            Data_Cmd = data_in[0];
49
            switch (data_in[0])
50
            {
51
            case B_GET_INFO:
52
               pData_Out = (unsigned char *)&Info;
53
               Data_Out_Max = sizeof (Info);
54
               break;
55
            case B_GET_STATUS:
56
               pData_Out = (unsigned char *)&State;
57
               Data_Out_Max = sizeof (State);
58
               break;
59
            default :
60
               Data_Out_Max = 0;
61
               break;
62
            }
63
         }
64
         else
65
         {
66
            Output_State = OUT_STATE_NC;
67
         }
68
         OutputCounter = 0;
69
         InputCounter = 0;
70
      }
71
   }
72
   else if (I2C_GetITStatus(I2C1,I2C_IT_STOPF)) // Stopp erkannt?
73
   {
74
      I2C_ClearITPendingBit (I2C1,I2C_IT_STOPF);
75
76
      // Stop
77
      Data_Out_Max = 0;
78
      OutputCounter = 0;
79
      Output_State = OUT_STATE_NC;
80
81
      if (bRecStart != FALSE)
82
      {
83
         if (InputCounter == MAXBYTES) /*   alle daten empfangen ?*/
84
         {
85
            new_data = TRUE;
86
         }
87
      } /* else ->> komme aus nicht def. zustand */
88
89
      bRecStart = FALSE; /* loesche flag, Daten Empfang laeuft */
90
   }
91
   else  if (I2C_GetITStatus(I2C1,I2C_IT_RXNE)) //  was empfangen?
92
   {
93
      uint8_t In_Datum;
94
95
      In_Datum = I2C_ReceiveData(I2C1);
96
97
      if (InputCounter >= MAXBYTES) /* zu viele Daten empfangen ? */
98
      {
99
         bRecStart = FALSE; /* loesche flag, Daten Empfang laeuft */
100
      }
101
      else /* Kann noch Daten empfangen ! */
102
      {
103
         if (bRecStart == TRUE) /* laeuft Daten Empfang ? */
104
         {
105
            data_in[InputCounter] = In_Datum; // das sind die Daten -> also speichern
106
            InputCounter++;
107
         }
108
      }
109
      Data_Out_Max = 0;
110
      Output_State = OUT_STATE_NC;
111
112
      //I2C_ClearITPendingBit (I2C1,I2C_IT_RXNE); // macht das auslesen schon
113
   }   
114
   else   if (I2C_GetITStatus(I2C1,I2C_IT_TXIS)) //  gesendet ?
115
   {
116
      I2C_ClearITPendingBit (I2C1,I2C_IT_TXIS);
117
118
      switch(Output_State)
119
      {
120
      case OUT_STATE_CMD:
121
         I2C_SendData(I2C1, Data_Cmd);    // 1. Byte ist der Befehl zu dem die Daten passen
122
         Output_State = OUT_STATE_LENGTH;
123
         break;
124
      case OUT_STATE_LENGTH:
125
         I2C_SendData(I2C1, Data_Out_Max); // 2. Byte ist die Laenge
126
         Output_State = OUT_STATE_DATA;
127
         break;
128
      case OUT_STATE_DATA:
129
         if (OutputCounter < Data_Out_Max)  // Kann ich noch Daten senden?
130
         {
131
            I2C_SendData(I2C1, (*pData_Out));
132
            pData_Out++;
133
            OutputCounter++;
134
135
            if (OutputCounter >= Data_Out_Max)  // Kann ich noch Daten senden?
136
            {
137
                Output_State = OUT_STATE_NC;
138
            }
139
         }
140
         else
141
         {
142
            Output_State = OUT_STATE_NC;
143
            I2C_SendData(I2C1, 0); // sende NULL -> es wird zu viel abgefragt!
144
         }
145
         break;
146
      case OUT_STATE_NC:
147
      default:
148
          I2C_SendData(I2C1, 0); // sende NULL -> es wird mist abgefragt!
149
         break;
150
      }
151
   }
152
    else  if (I2C_GetITStatus(I2C1,I2C_IT_NACKF)) //  erkannt?
153
   {
154
      I2C_ClearITPendingBit (I2C1,I2C_IT_NACKF);
155
   }
156
   else   if (  (I2C_GetITStatus(I2C1,I2C_IT_BERR)) //  Fehler erkannt?
157
      || (I2C_GetITStatus(I2C1,I2C_IT_ARLO)) //  Fehler erkannt?
158
      )
159
   {
160
      // Sollte nicht passieren
161
      InputCounter = 0;
162
      OutputCounter = 0;
163
      Data_Out_Max = 0;
164
165
      I2C_ClearITPendingBit (I2C1,I2C_IT_BERR);
166
      I2C_ClearITPendingBit (I2C1,I2C_IT_ARLO);
167
   }
168
}
169
170
171
172
void Twi_Init(void)
173
{
174
   I2C_InitTypeDef  I2C_InitStructure;
175
   NVIC_InitTypeDef NVIC_InitStructure;
176
   GPIO_InitTypeDef  GPIO_InitStructure;
177
178
   InputCounter = 0x00;
179
   Data_Cmd = B_GET_NC;
180
   bRecStart = FALSE; /* loesche flag, daten empfang laeuft */
181
182
   // Ausgabe blockieren
183
   Data_Out_Max = 0;
184
   OutputCounter = 0;
185
   Output_State = OUT_STATE_NC;
186
187
   I2C_DeInit(I2C1);
188
   
189
  /*!< I2C Periph clock enable */
190
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
191
192
   /*!<  GPIO clock enable */
193
   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
194
195
   RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
196
197
   GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_1);
198
   GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_1);
199
200
     /* Configure I2C pins:  SDA & SCL  ----------------------------*/
201
   GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
202
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
203
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
204
   GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
205
   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
206
   GPIO_Init(GPIOB, &GPIO_InitStructure);
207
208
   /*!< I2C Init */
209
   I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
210
   I2C_InitStructure.I2C_Timing = 100000;
211
   I2C_InitStructure.I2C_DigitalFilter = 0;
212
   I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
213
   I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
214
   I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
215
   I2C_InitStructure.I2C_OwnAddress1 = MYADDR;
216
   I2C_Init(I2C1, &I2C_InitStructure);
217
218
   /* Enable I2C event interrupt */
219
   I2C_ITConfig(I2C1, (I2C_IT_ERRI | I2C_IT_STOPI | I2C_IT_ADDRI | I2C_IT_RXI  | I2C_IT_TXI), ENABLE); // I2C_IT_NACKI 
220
221
  /* Configure the I2C event priority */
222
   NVIC_InitStructure.NVIC_IRQChannel = I2C1_IRQn;
223
   NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
224
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
225
   NVIC_Init(&NVIC_InitStructure);
226
227
  I2C_Cmd(I2C1, ENABLE);/* I2C ENABLE */
228
}

Regards,
Klaus

von klaus (Guest)


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

von klaus (Guest)


Rate this post
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.

von klaus (Guest)


Rate this post
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

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.