Forum: Mikrocontroller und Digitale Elektronik I2C Interrupt Handler bei Fehler


von Sebastian T. (sebastian_tsch)


Lesenswert?

Hi,

Ich versuche schon seit einiger Zeit meinen I2C "sicher" zu machen. Das 
Problem ist, dass es nach einiger Zeit (von Sekunden bis Minuten) zu 
einem Fehler kommt und daher das ganze Programm freezed. Der 
Interrupthandler für den I2C Event wird dann dauernd aufgerufen und 
landet im default (Fehler). Nun sollte ich doch dort einfach den 
Interrupt deaktivieren können, doch so wie ich es momentan mache scheint 
es nicht zu klappen:
1
void I2C2_EV_IRQHandler(void)
2
{
3
    switch(I2C_GetLastEvent(I2C2))
4
    {
5
    case I2C_EVENT_MASTER_MODE_SELECT :
6
      if(!tx_finish) {
7
        I2C_Send7bitAddress(I2Cx, MPU6050_ADDRESS_1, I2C_Direction_Transmitter);
8
        I2C_DMACmd(I2Cx, ENABLE);
9
      } else {
10
        I2C_Send7bitAddress(I2Cx, MPU6050_ADDRESS_1, I2C_Direction_Receiver);
11
        I2C_DMACmd(I2Cx, ENABLE);
12
      }
13
      interrupt_error=0;
14
      break;
15
    case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
16
        DMA_Cmd(MPU6050_DMA_STREAM_TX, ENABLE);
17
      break;
18
    case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED:
19
        DMA_Cmd(MPU6050_DMA_STREAM_RX, ENABLE);
20
        I2C_ITConfig(I2C2, I2C_IT_EVT, DISABLE);
21
      break;
22
    case I2C_EVENT_SLAVE_STOP_DETECTED :
23
      break;
24
    case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED:
25
      break;
26
    case I2C_EVENT_SLAVE_BYTE_TRANSMITTED:
27
      break;
28
    case I2C_EVENT_SLAVE_ACK_FAILURE:
29
      break;
30
    case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
31
      break;
32
    case I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED:
33
      break;
34
    case I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED:
35
      break;
36
    case I2C_EVENT_SLAVE_BYTE_RECEIVED:
37
      break;
38
    case I2C_EVENT_MASTER_BYTE_RECEIVED:
39
      break;
40
    case I2C_EVENT_MASTER_BYTE_TRANSMITTING:
41
      break;
42
    case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
43
      break;
44
    case I2C_EVENT_MASTER_MODE_ADDRESS10:
45
      break;
46
    case I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED:
47
      break;
48
    default:
49
      interrupt_error++;
50
      if(interrupt_error>10) {
51
        i2c_hard_failure=1;
52
        I2C_ITConfig(I2C2, I2C_IT_EVT, DISABLE);
53
        I2C_Cmd(I2C2, DISABLE);
54
      }
55
      break;
56
    }
57
}

Jemand eine Idee wie ich das Aufrufen von dieser Routine unterbrechen 
kann um den I2C wiederherzustellen?

von Peter D. (peda)


Lesenswert?

Da sind mal wieder die Hellseher gefragt.
Welches Target, welche Lib?

von Sebastian T. (sebastian_tsch)


Lesenswert?

Hallo, Ich verwende einen STM32F407 zusammen mit der Standard Peripheral 
Library von ST. Wenn ich I2C_ITConfig(I2C2, I2C_IT_EVT, DISABLE); 
aufrufe müssten doch die Interrupts aufhören? Kann ich sonst irgendwie 
alle Interrupts deinitialisieren und neu initialisieren?

von Sebastian T. (sebastian_tsch)


Lesenswert?

Wie genau kann ich NVIC reinitialisieren? Das muss doch möglich sein im 
Fehlerfall?

von Sebastian T. (sebastian_tsch)


Lesenswert?

Ich habe hier mal den ganzen Code für den I2C. Es scheint schon, dass 
der Interrupt Handler abgeschaltet wird, doch die Neuinitialisierung 
funktioniert noch nicht. Der I2C scheint nicht verklemmt zu sein, 
zumindest wenn ich die Funktion unlockI2C() aufrufe, ist SDA immer auf 
1. Wenn ich z.B NVIC_SystemReset(); aufrufe, kann ich den I2C wieder 
funktionsfähig machen, aber der Overhead ist immens und daher frage ich 
euch, wie ihr das machen würdet. Ohne Interrupt Handler kann ich den I2C 
nur mit der Funktion restartMPU6050() funktionsfähig machen, aber was 
muss ich bei der reinitialisierung der Interruptroutine beachten?

Noch was: nach dem restartMPU6050() werden dann nur noch Fehlerhafte 
Events ausgelöst. Wenn ich also die Befehle I2C_ITConfig(I2C2, 
I2C_IT_EVT, ENABLE); I2C_GenerateSTART(I2Cx, ENABLE); aktiviere, dann 
wird der Event I2C_EVENT_MASTER_MODE_SELECT nie ausgewählt.
1
#include "I2C_DMA_INTERRUPT.h"
2
3
/*
4
 * private variables
5
 */
6
7
uint8_t MPU6050_RX_BUFF[MPU6050_BUFF_SIZE_RX];
8
uint8_t MPU6050_TX_BUFF[MPU6050_BUFF_SIZE_TX]; // We need only to write the register value for ACC -> 0x3B
9
10
uint8_t isNewData = 0; //For initialization
11
uint8_t dmaStarted=0;
12
uint8_t dataReadyMPU=0;
13
uint8_t tx_finish;
14
uint8_t interrupt_error=0;
15
uint8_t i2c_hard_failure=0;
16
17
/*
18
 * global functions
19
 */
20
21
uint8_t startMPU6050() {
22
  Fill_Buffer(MPU6050_RX_BUFF,MPU6050_BUFF_SIZE_RX);
23
  MPU6050_TX_BUFF[0]=(uint8_t)ACCEL_ADDR;
24
  uint8_t fail_flag=0;
25
26
  I2C_I2C_init();
27
  I2C_GPIO_init();
28
  I2C_DMA_init();
29
30
  //Power ON
31
  fail_flag|=writeI2C(MPU6050_ADDRESS_1,MPU6050_PWR,0x00); //Power up MPU6050_1
32
33
  //Gyro Mode
34
  fail_flag|=writeI2C(MPU6050_ADDRESS_1,0x1B,MPU6050_GYRO_MODE); //Gyro Mode: 1000°/s
35
36
  //Set Sampling mode filtered
37
  fail_flag|=writeI2C(MPU6050_ADDRESS_1,0x1A,MPU6050_DLPF);
38
39
40
  return fail_flag;
41
}
42
43
uint8_t restartMPU6050() {
44
  uint8_t fail_flag=0;
45
  dmaStarted=0;
46
  isNewData =0;
47
  i2c_hard_failure=0;
48
49
  //First solve problems:
50
  unlockI2C();
51
52
  I2C_I2C_init();
53
  I2C_GPIO_init();
54
  I2C_DMA_init();
55
56
  //Power ON
57
  fail_flag|=writeI2C(MPU6050_ADDRESS_1,MPU6050_PWR,0x00); //Power up MPU6050_1
58
59
  //Gyro Mode
60
  fail_flag|=writeI2C(MPU6050_ADDRESS_1,0x1B,MPU6050_GYRO_MODE); //Gyro Mode: 1000°/s
61
62
  //Set Sampling mode filtered
63
  fail_flag|=writeI2C(MPU6050_ADDRESS_1,0x1A,MPU6050_DLPF);
64
65
66
  return fail_flag;
67
}
68
69
void unlockI2C() {
70
  GPIO_InitTypeDef gpioInit;
71
  gpioInit.GPIO_Pin = I2Cx_SCL_PIN;
72
  gpioInit.GPIO_Mode = GPIO_Mode_OUT;
73
  gpioInit.GPIO_Speed = GPIO_Speed_100MHz;
74
  gpioInit.GPIO_OType = GPIO_OType_OD;
75
  gpioInit.GPIO_PuPd  = GPIO_PuPd_NOPULL;
76
  GPIO_Init(I2Cx_SCL_GPIO_PORT, &gpioInit);
77
78
  gpioInit.GPIO_Pin = I2Cx_SDA_PIN;
79
  gpioInit.GPIO_Mode = GPIO_Mode_IN;
80
  GPIO_Init(I2Cx_SCL_GPIO_PORT, &gpioInit);
81
82
  uint8_t j=GPIO_ReadInputDataBit(GPIOB, I2Cx_SDA_PIN);
83
84
  while(j==0) {
85
    GPIO_ToggleBits(GPIOB, I2Cx_SCL_PIN);
86
    j=GPIO_ReadInputDataBit(GPIOB, I2Cx_SDA_PIN);
87
  }
88
}
89
90
void I2C_I2C_init(void) {
91
92
  I2C_Cmd(I2C2, DISABLE);
93
  I2C_InitTypeDef i2cInit;
94
95
  clearAllI2CFlags();
96
97
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
98
  RCC_APB1PeriphClockCmd(I2Cx_CLK, ENABLE);
99
  RCC_AHB1PeriphClockCmd(I2Cx_SDA_GPIO_CLK, ENABLE);
100
  RCC_AHB1PeriphClockCmd(I2Cx_SCL_GPIO_CLK, ENABLE);
101
  RCC_APB1PeriphResetCmd(I2Cx_CLK, ENABLE);
102
  RCC_APB1PeriphResetCmd(I2Cx_CLK, DISABLE);
103
  RCC_AHB1PeriphClockCmd(DMAx_CLK, ENABLE);
104
105
  // configure I2C2
106
  i2cInit.I2C_ClockSpeed = 400000;
107
  i2cInit.I2C_Mode = I2C_Mode_I2C;
108
  i2cInit.I2C_DutyCycle = I2C_DutyCycle_2;  // 50% duty cycle
109
  i2cInit.I2C_OwnAddress1 = 0x00;      // own address
110
  i2cInit.I2C_Ack = I2C_Ack_Enable;
111
  i2cInit.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // set address length to 7 bit addresses
112
  I2C_Init(I2C2, &i2cInit);
113
114
  // enable I2C2
115
  I2C_Cmd(I2C2, ENABLE);
116
117
  //I2C Interrupt Routine -> For events
118
  NVIC_InitTypeDef NVIC_InitStructure;
119
  NVIC_InitStructure.NVIC_IRQChannel                   = I2C2_EV_IRQn;
120
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //GIVE HIGHEST PRIORITY FOR ALL INTERRUPTS
121
  NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;
122
  NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
123
  NVIC_Init(&NVIC_InitStructure);
124
}
125
126
void I2C_GPIO_init() {
127
  GPIO_InitTypeDef gpioInit;
128
129
  gpioInit.GPIO_Pin = I2Cx_SCL_PIN;
130
  gpioInit.GPIO_Mode = GPIO_Mode_AF;
131
  gpioInit.GPIO_Speed = GPIO_Speed_50MHz;
132
  gpioInit.GPIO_OType = GPIO_OType_OD;
133
  gpioInit.GPIO_PuPd  = GPIO_PuPd_NOPULL;
134
  GPIO_Init(I2Cx_SCL_GPIO_PORT, &gpioInit);
135
136
  gpioInit.GPIO_Pin = I2Cx_SDA_PIN;
137
  GPIO_Init(I2Cx_SDA_GPIO_PORT, &gpioInit);
138
  GPIO_PinAFConfig(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_SOURCE, I2Cx_SCL_AF);
139
  GPIO_PinAFConfig(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_SOURCE, I2Cx_SDA_AF);
140
}
141
142
143
void I2C_DMA_init() { // From the ST Standard Peripheral Library Example for I2C
144
  NVIC_InitTypeDef nvicInit;
145
  DMA_InitTypeDef  dmaInit;
146
147
  //Clear all flags and deinit before initialization
148
  DMA_ClearFlag(MPU6050_DMA_STREAM_RX, I2Cx_RX_DMA_TCFLAG | I2Cx_RX_DMA_FEIFLAG | I2Cx_RX_DMA_DMEIFLAG | \
149
                     I2Cx_RX_DMA_TEIFLAG | I2Cx_RX_DMA_HTIFLAG);
150
  DMA_ClearFlag(MPU6050_DMA_STREAM_TX, I2Cx_TX_DMA_TCFLAG | I2Cx_TX_DMA_FEIFLAG | I2Cx_TX_DMA_DMEIFLAG | \
151
                                         I2Cx_TX_DMA_TEIFLAG | I2Cx_TX_DMA_HTIFLAG);
152
153
  DMA_Cmd(MPU6050_DMA_STREAM_RX, DISABLE);
154
  DMA_Cmd(MPU6050_DMA_STREAM_TX, DISABLE);
155
  DMA_DeInit(MPU6050_DMA_STREAM_RX);
156
  DMA_DeInit(MPU6050_DMA_STREAM_TX);
157
158
  // Initialization DMA
159
  dmaInit.DMA_Channel = MPU6050_DMA_CHANNEL;
160
  dmaInit.DMA_PeripheralBaseAddr = (uint32_t)MPU6050_DR_ADDRESS;
161
  dmaInit.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
162
  dmaInit.DMA_MemoryInc = DMA_MemoryInc_Enable;
163
  dmaInit.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
164
  dmaInit.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
165
  dmaInit.DMA_Mode = DMA_Mode_Normal;
166
  dmaInit.DMA_Priority = DMA_Priority_VeryHigh;
167
  dmaInit.DMA_FIFOMode = DMA_FIFOMode_Enable;
168
  dmaInit.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
169
  dmaInit.DMA_MemoryBurst = DMA_MemoryBurst_Single;
170
  dmaInit.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
171
172
  //Init DMA Receiver
173
  dmaInit.DMA_DIR = DMA_DIR_PeripheralToMemory;
174
  dmaInit.DMA_Memory0BaseAddr = (uint32_t)MPU6050_RX_BUFF;
175
  dmaInit.DMA_BufferSize = MPU6050_BUFF_SIZE_RX;
176
  DMA_DeInit(MPU6050_DMA_STREAM_RX);
177
  DMA_Init(MPU6050_DMA_STREAM_RX, &dmaInit);
178
  DMA_ITConfig(MPU6050_DMA_STREAM_RX, DMA_IT_TC, ENABLE);
179
180
  //Init DMA transmitter
181
  dmaInit.DMA_DIR = DMA_DIR_MemoryToPeripheral;
182
  dmaInit.DMA_Memory0BaseAddr = (uint32_t)MPU6050_TX_BUFF;
183
  dmaInit.DMA_BufferSize = MPU6050_BUFF_SIZE_TX;
184
  DMA_DeInit(MPU6050_DMA_STREAM_TX);
185
  DMA_Init(MPU6050_DMA_STREAM_TX, &dmaInit);
186
  DMA_ITConfig(MPU6050_DMA_STREAM_TX, DMA_IT_TC, ENABLE);
187
188
  // DMA Interrupt initialization
189
  nvicInit.NVIC_IRQChannel = DMA1_Stream2_IRQn;  //RX Interrupt
190
  nvicInit.NVIC_IRQChannelPreemptionPriority = 1;
191
  nvicInit.NVIC_IRQChannelSubPriority = 1;
192
  nvicInit.NVIC_IRQChannelCmd = ENABLE;
193
  NVIC_Init(&nvicInit);
194
195
  nvicInit.NVIC_IRQChannel = DMA1_Stream7_IRQn;  //TX Interrupt
196
  NVIC_Init(&nvicInit);
197
198
  DMA_ClearFlag(DMA1_Stream2, DMA_FLAG_FEIF2|DMA_FLAG_DMEIF2|DMA_FLAG_TEIF2|DMA_FLAG_HTIF2|DMA_FLAG_TCIF2);
199
  DMA_Cmd(DMA1_Stream2, ENABLE);
200
201
  DMA_ClearFlag(DMA1_Stream7, DMA_FLAG_FEIF2|DMA_FLAG_DMEIF2|DMA_FLAG_TEIF2|DMA_FLAG_HTIF2|DMA_FLAG_TCIF2);
202
  DMA_Cmd(DMA1_Stream7, ENABLE);
203
204
}
205
206
void Fill_Buffer(uint8_t *pBuffer, uint16_t BufferLength) {
207
  uint16_t index = 0;
208
  for (index = 0; index < BufferLength; index++ )
209
  {
210
    pBuffer[index] = 0x00;
211
  }
212
}
213
214
void DMA1_Stream2_IRQHandler(void) {
215
  if (DMA_GetFlagStatus(MPU6050_DMA_CHANNEL,DMA_FLAG_TCIF2)) {
216
    DMA_ClearITPendingBit(MPU6050_DMA_CHANNEL, DMA_FLAG_TCIF2);
217
218
    I2C_ITConfig(I2C2, I2C_IT_EVT, DISABLE);
219
    I2C_GenerateSTOP(I2Cx, ENABLE);
220
    DMA_Cmd(MPU6050_DMA_STREAM_RX, DISABLE);
221
    I2C_DMACmd(I2Cx,DISABLE);
222
    DMA_ClearFlag(MPU6050_DMA_STREAM_RX, I2Cx_RX_DMA_TCFLAG | I2Cx_RX_DMA_FEIFLAG | I2Cx_RX_DMA_DMEIFLAG | \
223
                                           I2Cx_RX_DMA_TEIFLAG | I2Cx_RX_DMA_HTIFLAG);
224
225
    isNewData=1;
226
    dmaStarted=0;
227
  }
228
}
229
230
void DMA1_Stream7_IRQHandler(void) {
231
  if (DMA_GetFlagStatus(MPU6050_DMA_CHANNEL,DMA_FLAG_TCIF7)) {
232
    DMA_ClearITPendingBit(MPU6050_DMA_CHANNEL, DMA_FLAG_TCIF7);
233
234
    I2C_DMACmd(I2Cx, DISABLE);
235
    I2C_GenerateSTOP(I2Cx, ENABLE);
236
    DMA_Cmd(MPU6050_DMA_STREAM_TX, DISABLE);
237
    DMA_ClearFlag(MPU6050_DMA_STREAM_TX, I2Cx_TX_DMA_TCFLAG | I2Cx_TX_DMA_FEIFLAG | I2Cx_TX_DMA_DMEIFLAG | \
238
                                           I2Cx_TX_DMA_TEIFLAG | I2Cx_TX_DMA_HTIFLAG);
239
240
    DMARead(); //Activate Read after successfully transfered register read command
241
  }
242
}
243
244
void clearAllI2CFlags() {
245
  I2C_ClearITPendingBit(I2C2,I2C_IT_SMBALERT);
246
  I2C_ClearITPendingBit(I2C2,I2C_IT_TIMEOUT);
247
  I2C_ClearITPendingBit(I2C2,I2C_IT_PECERR);
248
  I2C_ClearITPendingBit(I2C2,I2C_IT_OVR);
249
  I2C_ClearITPendingBit(I2C2,I2C_IT_AF);
250
  I2C_ClearITPendingBit(I2C2,I2C_IT_ARLO);
251
  I2C_ClearITPendingBit(I2C2,I2C_IT_BERR);
252
  I2C_ClearITPendingBit(I2C2,I2C_IT_TXE);
253
  I2C_ClearITPendingBit(I2C2,I2C_IT_RXNE);
254
  I2C_ClearITPendingBit(I2C2,I2C_IT_STOPF);
255
  I2C_ClearITPendingBit(I2C2,I2C_IT_ADD10);
256
  I2C_ClearITPendingBit(I2C2,I2C_IT_BTF);
257
  I2C_ClearITPendingBit(I2C2,I2C_IT_ADDR);
258
  I2C_ClearITPendingBit(I2C2,I2C_IT_SB);
259
260
  I2C_ClearFlag(I2C2,I2C_FLAG_SMBALERT);
261
  I2C_ClearFlag(I2C2,I2C_FLAG_TIMEOUT);
262
  I2C_ClearFlag(I2C2,I2C_FLAG_PECERR);
263
  I2C_ClearFlag(I2C2,I2C_FLAG_OVR);
264
  I2C_ClearFlag(I2C2,I2C_FLAG_AF);
265
  I2C_ClearFlag(I2C2,I2C_FLAG_ARLO);
266
  I2C_ClearFlag(I2C2,I2C_FLAG_BERR);
267
  I2C_ClearFlag(I2C2,I2C_FLAG_TXE);
268
  I2C_ClearFlag(I2C2,I2C_FLAG_RXNE);
269
  I2C_ClearFlag(I2C2,I2C_FLAG_STOPF);
270
  I2C_ClearFlag(I2C2,I2C_FLAG_ADD10);
271
  I2C_ClearFlag(I2C2,I2C_FLAG_BTF);
272
  I2C_ClearFlag(I2C2,I2C_FLAG_ADDR);
273
  I2C_ClearFlag(I2C2,I2C_FLAG_SB);
274
275
  I2C_ClearFlag(I2C2,I2C_FLAG_DUALF);
276
  I2C_ClearFlag(I2C2,I2C_FLAG_SMBHOST);
277
  I2C_ClearFlag(I2C2,I2C_FLAG_SMBDEFAULT);
278
  I2C_ClearFlag(I2C2,I2C_FLAG_GENCALL);
279
  I2C_ClearFlag(I2C2,I2C_FLAG_TRA);
280
  I2C_ClearFlag(I2C2,I2C_FLAG_BUSY);
281
  I2C_ClearFlag(I2C2,I2C_FLAG_MSL);
282
}
283
284
void I2C2_EV_IRQHandler(void)
285
{
286
    switch(I2C_GetLastEvent(I2C2))
287
    {
288
    case I2C_EVENT_MASTER_MODE_SELECT :
289
      if(!tx_finish) {
290
        I2C_Send7bitAddress(I2Cx, MPU6050_ADDRESS_1, I2C_Direction_Transmitter);
291
        I2C_DMACmd(I2Cx, ENABLE);
292
      } else {
293
        I2C_Send7bitAddress(I2Cx, MPU6050_ADDRESS_1, I2C_Direction_Receiver);
294
        I2C_DMACmd(I2Cx, ENABLE);
295
      }
296
      interrupt_error=0;
297
      break;
298
    case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
299
        DMA_Cmd(MPU6050_DMA_STREAM_TX, ENABLE);
300
      break;
301
    case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED:
302
        DMA_Cmd(MPU6050_DMA_STREAM_RX, ENABLE);
303
        I2C_ITConfig(I2C2, I2C_IT_EVT, DISABLE);
304
      break;
305
    case I2C_EVENT_SLAVE_STOP_DETECTED :
306
      break;
307
    case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED:
308
      break;
309
    case I2C_EVENT_SLAVE_BYTE_TRANSMITTED:
310
      break;
311
    case I2C_EVENT_SLAVE_ACK_FAILURE:
312
      break;
313
    case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
314
      break;
315
    case I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED:
316
      break;
317
    case I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED:
318
      break;
319
    case I2C_EVENT_SLAVE_BYTE_RECEIVED:
320
      break;
321
    case I2C_EVENT_MASTER_BYTE_RECEIVED:
322
      break;
323
    case I2C_EVENT_MASTER_BYTE_TRANSMITTING:
324
      break;
325
    case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
326
      break;
327
    case I2C_EVENT_MASTER_MODE_ADDRESS10:
328
      break;
329
    case I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED:
330
      break;
331
    default:
332
      interrupt_error++;
333
      if(interrupt_error>10) {
334
        i2c_hard_failure=1;
335
        I2C_ITConfig(I2C2, I2C_IT_EVT, DISABLE);
336
        I2C_Cmd(I2C2, DISABLE);
337
        interrupt_error=0;
338
      }
339
      break;
340
    }
341
}
342
343
344
uint8_t copyNewAccData(MPU6050Data *dataStruct, MPU6050DataOffset *offset, uint8_t sensor_numb) {
345
  if(isNewData) {
346
    int accX=(MPU6050_RX_BUFF[0]<<8) | MPU6050_RX_BUFF[1];
347
    int accY=(MPU6050_RX_BUFF[2]<<8) | MPU6050_RX_BUFF[3];
348
    int accZ=(MPU6050_RX_BUFF[4]<<8) | MPU6050_RX_BUFF[5];
349
    int temp=(MPU6050_RX_BUFF[6]<<8) | MPU6050_RX_BUFF[7];
350
    int gyroX=(MPU6050_RX_BUFF[8]<<8) | MPU6050_RX_BUFF[9];
351
    int gyroY=(MPU6050_RX_BUFF[10]<<8) | MPU6050_RX_BUFF[11];
352
    //int gyroZ=(MPU6050_RX_BUFF[12]<<8) | MPU6050_RX_BUFF[13];
353
354
    if(accX>32768)
355
      accX=accX-65546;
356
    if(accY>32768)
357
      accY=accY-65546;
358
    if(accZ>32768)
359
      accZ=accZ-65546;
360
361
    if(gyroX>=32768)
362
        gyroX=gyroX-65546;
363
    if(gyroY>=32768)
364
        gyroY=gyroY-65546;
365
    /*if(gyroZ>32768)
366
        gyroZ=gyroZ-65546;*/
367
368
    dataStruct->dataAccX = accX - offset->dataAccXOffset; //- offset->dataAccXOffset;
369
    dataStruct->dataAccY = accY - offset->dataAccYOffset; //- offset->dataAccYOffset;
370
    dataStruct->dataAccZ = accZ - offset->dataAccZOffset;
371
372
    dataStruct->dataGyroX= gyroX - offset->dataGyroXOffset; // - offset->dataGyroXOffset;
373
    dataStruct->dataGyroY= gyroY - offset->dataGyroYOffset; //- offset->dataGyroYOffset;
374
    //dataStruct->dataGyroZ=gyroZ;
375
376
    isNewData=0;
377
    return 0;
378
  } else {
379
    return 2;
380
  }
381
}
382
383
uint8_t DMAInitRead() {
384
  if(i2c_hard_failure)
385
    return 1;
386
387
  if(!isNewData && !dmaStarted) {
388
    dmaStarted=1;
389
    tx_finish=0;
390
391
    I2C_ITConfig(I2C2, I2C_IT_EVT, ENABLE);
392
    I2C_GenerateSTART(I2Cx, ENABLE);
393
394
    return 0;
395
  }
396
  return 0;
397
398
}
399
400
uint8_t DMARead() {
401
402
  //Start DMA Read process:
403
  I2C_DMALastTransferCmd(I2Cx, ENABLE); //Enable automatic NACK
404
  I2C_GenerateSTART(I2Cx, ENABLE);
405
406
  tx_finish=1;
407
408
  return 0;
409
410
}
411
412
//FUNCTIONS WITHOUT DMA: USE ONLY FOR INITIALIZATION
413
414
uint8_t writeI2C(uint8_t addr, uint8_t reg, uint8_t data) {
415
  uint8_t fail_flag=0;
416
417
  fail_flag|=I2C_start(addr, 0, 0); //dir==0 is transmitter, no ack since only one write
418
  fail_flag|=I2C_write(reg);
419
  fail_flag|=I2C_write(data);
420
  I2C_stop();
421
422
  return fail_flag;
423
}
424
425
426
427
uint8_t I2C_start(uint8_t address, uint8_t direction, uint8_t ack) { //direction transmitter==0
428
  uint16_t timeout = TIMEOUT; //Wait maximum 20000 cycles
429
430
  while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY)) {
431
    if (--timeout == 0) {
432
      return 1;
433
    }
434
  }
435
436
  I2C_GenerateSTART(I2C2, ENABLE);
437
438
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)) {
439
    if (--timeout == 0) {
440
      return 1;
441
    }
442
  }
443
444
  //Ack enable
445
  if(ack)
446
    I2C2->CR1 |= I2C_CR1_ACK;
447
448
  //Send Adress
449
  I2C_Send7bitAddress(I2C2, address, direction);
450
  while (!(I2C2->SR1 & I2C_SR1_ADDR)) { //Wait until Address is received by slave
451
    if (--timeout == 0) {
452
      return 1;
453
    }
454
  }
455
456
  if(direction == I2C_Direction_Transmitter){
457
    while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) {
458
      if (--timeout == 0) {
459
        return 1;
460
      }
461
    }
462
  }
463
  else if(direction == I2C_Direction_Receiver){
464
    while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) {
465
      if (--timeout == 0) {
466
        return 1;
467
      }
468
    }
469
  }
470
471
  /* Read status register to clear ADDR flag */
472
  I2C2->SR2;
473
474
  return 0;
475
}
476
477
478
uint8_t I2C_write(uint8_t data) {
479
  uint16_t timeout = TIMEOUT; //Wait maximum 20000 cycles
480
481
  I2C_SendData(I2C2, data);
482
483
  while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))  {
484
    if (--timeout == 0) {
485
      return 1;
486
    }
487
  }
488
489
  return 0;
490
}
491
492
void I2C_stop() {
493
  I2C_GenerateSTOP(I2C2, ENABLE);
494
}
495
496
void initOffset(MPU6050DataOffset *offset) {
497
  offset->dataAccXOffset=0;
498
  offset->dataAccYOffset=0;
499
  offset->dataAccZOffset=0;
500
  offset->dataGyroXOffset=0;
501
  offset->dataGyroYOffset=0;
502
  offset->dataGyroZOffset=0;
503
}
504
505
void setOffset(MPU6050Data *MPU1, MPU6050DataOffset *MPU1_Offset) {
506
  MPU1_Offset->dataAccXOffset=MPU1->dataAccX;
507
  MPU1_Offset->dataAccYOffset=MPU1->dataAccY;
508
  MPU1_Offset->dataAccZOffset=MPU1->dataAccZ;
509
  MPU1_Offset->dataGyroXOffset=MPU1->dataGyroX;
510
  MPU1_Offset->dataGyroYOffset=MPU1->dataGyroY;
511
}

: Bearbeitet durch User
von Sebastian T. (sebastian_tsch)


Lesenswert?

Ich habe mal alles mit dem debugger abgefahren und die Reinitialisierung 
scheint zu gehen, zumindest bekomme ich bei normalem schreiben/lesen die 
Daten über und der I2C ist nicht verklemmt, aber die Interrupt Routine 
sendet mir nur noch Fehler Events. Hat Jemand eine Idee, wie man diese 
Interruptroutine zurücksetzt so dass wieder ordentliche Events kommen?

von Forist (Gast)


Lesenswert?

Sebastian T. schrieb:
> Ich habe hier mal den ganzen Code für den I2C.

Ist dir hier im Forum schon mal die Funktion Dateianhang aufgefallen. 
Nicht jeder hat Lust, sich beim Scollen durch den Thread wunde Finger zu 
holen.

Statt an den Symptomen rum zu doktern und den Interrupt abzuwürgen oder 
irgendwelche Systemteile neu zu initialisieren, ist es wahrscheinlich 
zielführender, zu klären, was da hängt.

von Sebastian T. (sebastian_tsch)


Lesenswert?

Forist schrieb:
> was da hängt.

Hallo Forist,

Zu einem Fehler kann es durch die starke EMV der BLDC Motoren in der 
Nähe kommen. Dann geht ein CLK Takt verloren und der I2C hängt und somit 
auch der DMA etc.

von Forist (Gast)


Lesenswert?

Sebastian T. schrieb:
> ... starke EMV ...
Die sollte eher zu problemlosem Zusammenspiel der Komponenten führen ;-)

Wenn du das hängen deiner Schnittstelle auf Störungen durch BLDC Motoren 
in der Nähe zurück führst, vermute ich mal, dass es bei deinem Aufbau 
mit der elektromagnetischen Verträglichkeit nicht allzuweit her ist und 
du dir Gedanken über einen vernünftigen Aufbau machen solltest.

von Sebastian T. (sebastian_tsch)


Lesenswert?

Da es nur etwa alle Minuten zu einem Fehler kommt, spielt das keine 
Rolle wenn man im Fehlerfall den I2C wieder lauffähig macht.

von Forist (Gast)


Lesenswert?

Sebastian T. schrieb:
> Da es nur etwa alle Minuten zu einem Fehler kommt, spielt das keine
> Rolle wenn man im Fehlerfall den I2C wieder lauffähig macht.

Stimmt, Fallschirme auf dem Mars mit pendelnden Lasten kommen noch viel 
seltener vor, auch in der Simulation. Trotzdem ist es oft besser die 
Ursachen zu beseitigen als mit Smoothy Weichwasch in der Software über 
die Fehler rüber zu bügeln.

Hast du dir deine Bussignale überhaupt schon mal angeguckt oder merkst 
du nur, dass deine SW ab und zu mal hängt?

von Sebastian T. (sebastian_tsch)


Lesenswert?

Forist schrieb:
> Hast du dir deine Bussignale überhaupt schon mal angeguckt oder merkst
> du nur, dass deine SW ab und zu mal hängt?

Ja, die Bussignale sind in Ordnung und ich kann auch normal mit 
write/read auf den I2C zugreifen nach dem Aufruf von restartMPU6050(). 
Aber sobald ich dann bei initialisieren mit DMA und der Interruptroutine
I2C_ITConfig(I2C2, I2C_IT_EVT, ENABLE); setze, dann pollt es mir nur 
noch die Routine mit fehlerhaften Events. Irgendwie wurde also die 
Interruptroutine nicht ordentlich neuinitialisiert.

Forist schrieb:
> Stimmt, Fallschirme auf dem Mars mit pendelnden Lasten kommen noch viel
> seltener vor, auch in der Simulation. Trotzdem ist es oft besser die
> Ursachen zu beseitigen als mit Smoothy Weichwasch in der Software über
> die Fehler rüber zu bügeln.

Das stimmt schon, aber die Ursache in diesem Fall zu beheben ist fast 
unmöglich und es ist immer sicherer den Fehlerfall zu behandeln als 
einfach zu hoffen, dass nie ein Fehler auftritt.

: Bearbeitet durch User
von Noch nicht Rentner (Gast)


Lesenswert?

Auf einem I2C Bus, der ja nur auf eine Leiterplatte laeuft habe ich noch 
nie einen Fehler gehabt. Es geht nicht um hoffen, sondern ist Tatsache. 
Die Moeglichkeit ein Bit, oder eine Flanke zu verpassen existiert 
eigentlich gar nicht. Ich steuere I2C eigentlich nur mit Bitbang an, nie 
mit Interrupts, die bringen gar nichts.

Wir haben bisher noch nichts vom Aufbau gehoert. Auf Lochraster ?

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.