Forum: Mikrocontroller und Digitale Elektronik STM32F051 I2C slave Problem


von Klaus (Gast)


Lesenswert?

Hallo,

ich habe in einem STM32F051k Projekt ein Problem mit dem I2C als Slave.

Ich sende von einem AVR:
Start/Adresse Wr/Befehl/repStart/Adresse RD/ ... lese Informationen / 
Stop)
Wobei die zu lesenden Informationen immer aus Befehl/Anzahl/Daten 
besteht.

Komischerweise wird genau einmal alles sauber gemacht und dann komme ich 
selten mal zum senden der Anzahl, aber nie wieder zum senden der Daten.
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
}
Ich hoffe mir kann jemand helfen,
Klaus

von Peter (Gast)


Lesenswert?

Kann mir wirklich keiner Helfen?

von Dennis (Gast)


Lesenswert?

Du glaubst jetzt nicht ernsthaft, dass einer jetzt deinen Code nimmt, 
deine Hardware nachbaut, den Fehler nachstellt, die Lösung debuggt und 
zum Schluss dir alles auf den Präsentierteller legt..... ODER???

Es ist eher so, wie im normalen Programmieralltag: Breakpoints setzen, 
Registerinhalte analysieren, LA anschliessen, Hirn in Gang setzen und 
selber den Fehler eingrenzen. Dazu braucht man übrigens auch nicht in 
einem Forum zu Fragen....

Natürlich könnte ich dir jetzt mindestens 20 mögliche Fehlerursachen 
nennen, aber weder habe ich dazu die Zeit, noch ist es erkennbar dass du 
dich mit dem Problem intensiv beschäftigt hast. Sorry, aber das ist 
nicht der Grundgedanke dieses Forums - zumindest nicht in meinen Augen.

von Klaus (Gast)


Lesenswert?

Immer diese trolle.

Ist kein Code dabei wird gemeckert und ist mal was dabei wird auch 
gleich dumm herrum Gelaber.

Kannst mir ja mal ein Beispiel Code oder eine top doku zeigen, ich habe 
bis jetzt nichts gefunden.
Für die anderen stm gibt es was aber für die f0 Serie nichts.

Der Debugger hilft hier übrigens nicht viel. Den habe ich schon bis zum 
Unfällen benutzt.

von Klaus-Peter (Gast)


Lesenswert?

Trolle?

Erst Klaus, dann Peter, dann wieder Klaus. Offensichtlich heißt du 
anders. Vielleicht nennst du deinen Namen nicht, damit niemand deine 
Fähigkeiten mit dir assoziiert.

Und wenn du es mit einem Debugger nicht hinkriegst, lass jemand mit 
einem höheren IQ ran. Debugger, Oszi und LA dürften erfolgsversprechend 
sein.

von Klaus (Gast)


Lesenswert?

Mein Name spielt keine rolle.

Da du ja anscheinend intelligenter bist kannst du ja mal eine gute tat 
vollbringen und einem dummen mal helfen.

Übrigens ist der Fehler nicht im ankommenden Signal. Vor dem f0 hatte 
ich einen avr dran der lief perfekt. Auch alle anderen ic's arbeiten.
nur der stm32f051 will nicht.
Und weder die Doku noch im www finde ich eine Erklärung.

von Klaus (Gast)


Lesenswert?

So jetzt trolle ich mal.

Wie sieht es aus?
Keine Antwort?
Ist wohl doch zu kompliziert für Dich oder?
Versteckst Dich dann auch unter einem Gast Post.

Immer diese Nörgler die einem dann doch nicht helfen.
Ist echt Schade.

Bei solchen Antworten fragt man sich dann doch, warum helfe ich, wenn 
ich kann, eigentlich immer wieder.
Ist wohl mein Verständnis für ein Forum, man hilft einander.

von Dennis (Gast)


Lesenswert?

Klaus schrieb:
> Wie sieht es aus?
> Keine Antwort?

Doch, siehe in meinem vorherigen Post:

Dennis schrieb:
> Es ist eher so, wie im normalen Programmieralltag: Breakpoints setzen,
> Registerinhalte analysieren, LA anschliessen, Hirn in Gang setzen und
> selber den Fehler eingrenzen. Dazu braucht man übrigens auch nicht in
> einem Forum zu Fragen....

den selben Tipp hast du auch von Klaus-Peter bekommen:

Klaus-Peter schrieb:
> Debugger, Oszi und LA dürften erfolgsversprechend
> sein.

Klaus schrieb:
> Ist wohl doch zu kompliziert für Dich oder?

Wenn ich es auf dem Tisch habe, so vermutlich nicht :-) So aus der Ferne 
mit einem beratungsresistenten Fragesteller: ja!

Klaus schrieb:
> Immer diese Nörgler die einem dann doch nicht helfen.

Mehr kann man (sinnvoll) auch nicht helfen. Programmieren heisst nun mal 
auch Debuggen. Ein guter Programmierer kann daher
a) Code schreiben (idealerweise so, dass es schon an sich fehlerarm ist)
b) vollständig debuggen bis der Code EXAKT das macht, was der 
Programmierer will. Nicht mehr, nicht weniger.

Das kann dir kein Forum abnehmen. Bei spezifischen Problemen wird man 
hier auch geholfen, aber bei einem "Hier ist mein Gesamtcode, findet mal 
den Fehler" darfst du vermutlich lange auf die Lösung warten. Da hilft 
auch nicht das Rumgemeckere mit "hier sind alle so böse und keiner 
hilft".

Übrigens: Es ist wesentlich einfacher den Fehler zu finden, wenn man 
direkt in alt bewährter Weise die Register beschreibt. Da verschleiert 
einem kein Peripheal-Lib die Sicht...

von klaus (Gast)


Lesenswert?

Mal abgesehen davon das ich den Fehler längst gefunden habe.
Schon vor meinem vorletzten post.
Aber wenn man mich so reizt dann werde ich immer etwas genervt 
Antworten.

Der Fehler ist nicht mit einem Debugger zu finden.
Man musste schon mit 2 ran und von beiden Seiten debuggen.
Nur wenn der Sender (AVR) das Schritt für Schritt sendet kann man 
erkennen wo der F0 sich verhaspelt. Da würde man mit einem OSZI oder LA 
absolut nichts erkennen, wie auch der Sender ist ja nicht das Problem 
gewesen.

Wenn man die Lösung hat ist auch das eine oder andere, in der DOKU 
schlecht beschriebene, besser verständlich. Aber das was da drin steht 
funktioniert bei mir SO übrigens nicht richtig.
Aber auch hier gibt es wie so oft mehr als eine Lösung.

Verraten werde ich die Lösung nicht, steht alles in der DOKU und wie 
haben hier schlaue Leute gesagt "Debugger benutzen und Hirn an".
Es fehlt nur eine Zeile Code!


Klaus

von Klaus-Peter (Gast)


Lesenswert?

Jetzt zerlegst du dich aber selbst.

Klaus schrieb:
> Der Debugger hilft hier übrigens nicht viel. Den habe ich schon bis zum
> Unfällen benutzt.

Klaus schrieb:
> Man musste schon mit 2 ran und von beiden Seiten debuggen.

Da hast du also das gemacht, was dir zwei mal geraten wurde.

Und

> Ich hoffe mir kann jemand helfen.
vs.
> Verraten werde ich die Lösung nicht.

Bei mir fällst du in die Rubrik asoziales Bastelkiddie. Das du die 
Lösung nicht nennst, stört echte Ingenieure wenig. Aber die Googler in 
einen halben Jahr werden sich fühlen, wie es Gunnery Sgt. Hartman 
beschreibt:

"Sie sind doch garantiert diese Art von Typ, der f**kt jemand in den 
Arsch und hat dann nicht mal das bisschen Anstand, dem wenigstens auch 
einen runterzuholen. Sie merk ich mir vor!"

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.