STM32-Code geht nicht, Compilerproblem?

Gast #4243509
Lesenswert?

Hallo,

ich versuche nun schon eine ganze Weile eine I2C-Bibliothek für einen 
STM32F103C8 zum laufen zu bekommen.
Programmcode hab ich von hier:

http://diller-technologies.de/stm32.html#i2c

Und soweit zusammengekürzt, dass es eigentlich offensichtlich gehen 
müsste.
Hab den Fehler in Zeile 100 lokalisiert (Zeile mit if(1) ... ).
Wenn ich die Variable i2cDirectionWrite hier abfrage geht der Code 
nicht.
Schreibe ich eine "1" rein, gehts soweit (s.u.).
Ich versteh nur nicht warum, da i2cDirectionWrite permanent "1" ist.

Ich verwende CooCox Version 1.7.7 und  gcc-arm Version 4_8.
Code-Optimierung ist auf -O0 (None).

Es scheint wohl ein Compilerproblem zu sein. Weiß jemand Rat??

Schonmal Besten Dank!!
1
#include <stdint.h>
2
#include "stm32f10x_i2c.h"
3
#include "stm32f10x_rcc.h"
4
#include "stm32f10x_gpio.h"
5
#include "misc.h"
6
#include "i2c.h"
7

8

9
volatile uint8_t deviceAddress = 0;
10
volatile uint8_t dataByte1 = 0;
11
volatile uint8_t dataByte0 = 0;
12
volatile uint8_t receivedDataByte1 = 0;
13
volatile uint8_t receivedDataByte0 = 0;
14
volatile uint8_t i2cDirectionWrite = 1;
15
volatile uint8_t i2cByteCounter = 0;
16
volatile uint8_t i2cBusyFlag = 0;
17

18
volatile uint8_t test = 1;
19

20
volatile uint8_t temp = 1;
21

22

23
void i2c_init(void)
24
{
25
  GPIO_InitTypeDef GPIO_InitStructure;
26
  NVIC_InitTypeDef NVIC_InitStructure;
27
  I2C_InitTypeDef I2C_InitStructure;
28

29
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
30
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
31

32
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
33
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
34
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
35
  GPIO_Init(GPIOB, &GPIO_InitStructure);
36

37
  NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;
38
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
39
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
40
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
41
  NVIC_Init(&NVIC_InitStructure);
42

43
  NVIC_InitStructure.NVIC_IRQChannel = I2C1_ER_IRQn;
44
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
45
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
46
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
47
  NVIC_Init(&NVIC_InitStructure);
48

49
  I2C_DeInit(I2C1);
50

51
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
52
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
53
  I2C_InitStructure.I2C_ClockSpeed = 100000;
54
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
55
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
56
  I2C_InitStructure.I2C_OwnAddress1 = 0;
57
  I2C_Init(I2C1, &I2C_InitStructure);
58

59
  I2C_ITConfig(I2C1, I2C_IT_EVT, ENABLE);
60
  I2C_ITConfig(I2C1, I2C_IT_BUF, ENABLE);
61
  I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE);
62

63
  I2C_Cmd(I2C1, ENABLE);
64

65
  i2cBusyFlag = 0;
66
}
67

68
void i2c_writeByte(uint8_t address, uint8_t byte){
69
  while(i2cBusyFlag){}
70
  while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY)){}
71
  deviceAddress = address;
72
  dataByte0 = byte;
73
  i2cDirectionWrite = 1;
74
  i2cBusyFlag = 1;
75
  i2cByteCounter = 1;
76
  I2C_GenerateSTART(I2C1, ENABLE);
77
}
78

79
// ISR
80
void I2C1_EV_IRQHandler(void)
81
{
82

83
  if(I2C_GetFlagStatus(I2C1, I2C_FLAG_SB) == SET)
84
  {
85
    if(i2cDirectionWrite)
86
    {
87
         // STM32 Transmitter
88
         I2C_Send7bitAddress(I2C1, deviceAddress, I2C_Direction_Transmitter);
89
    }
90
    else
91
    {
92
         // STM32 Receiver
93
         I2C_Send7bitAddress(I2C1, deviceAddress, I2C_Direction_Receiver);
94
    }
95
  }
96
  else if(I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR) == SET || I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == SET){
97
    I2C_ReadRegister(I2C1, I2C_Register_SR1);
98
    I2C_ReadRegister(I2C1, I2C_Register_SR2);
99

100
    if(1) // hier soll eigentlich if(i2cDirectionWrite) stehen, geht nur nicht
101
    {
102

103
      // STM32 Transmitter
104
      if(i2cByteCounter == 2)
105
      {
106
        I2C_SendData(I2C1, dataByte1);
107
        i2cByteCounter--;
108
      }
109
      else if(i2cByteCounter == 1)
110
      {
111
        I2C_SendData(I2C1, dataByte0);
112
        i2cByteCounter--;
113
      }
114
      else
115
      {
116
        I2C_GenerateSTOP(I2C1, ENABLE);
117
        i2cBusyFlag = 0;
118
      }
119
    }
120
  }
121
}
122

123
// ISR
124
void I2C1_ER_IRQHandler(void)
125
{
126
  I2C_GenerateSTOP(I2C1, ENABLE);
127
  i2cBusyFlag = 0;
128

129
  I2C_ClearFlag(I2C1, I2C_FLAG_AF);
130
  I2C_ClearFlag(I2C1, I2C_FLAG_ARLO);
131
  I2C_ClearFlag(I2C1, I2C_FLAG_BERR);
132
}
Gast #4243532
Lesenswert?

Hallo,

das delay() ist einfach eine Schleife die Zeit totschlägt (s.u.), 
1000000 ist hier ca. eine halbe Sekunde.
Hardware ist in Ordnung, hab nen Portexpander am I2C dranhängen.
Das erste mal senden funktioniert. Nur das zweite mal nicht mehr.
Das funktioniert aber, wenn ich if(1) statt if(i2cDirectionWrite) 
schreibe.

1
void delay(uint32_t i)
2
{
3
    volatile uint32_t iZ = i;
4
    while (iZ--);
5
}
#4244530
Lesenswert?

I2C und STM32 haben sich nicht so gerne...

Ich hatte bis jetzt auch immer wieder Probleme damit. Man muss exakt die 
Schritte in den Qube-Beispielen einhalten, damit dies läuft. Und selbst 
dann kann es sein, dass es sporadische aussetzer gibt. Das ging soweit, 
dass ich mir für die STM32 eine eigene LIB geschrieben habe. Damit hatte 
ich dann nie Probleme.
#4246078
Lesenswert?

Ehm ja, diese meinte ich.
Fehler in der Lib gibts nicht, dafür ein paar in der Hardware (musst mal 
die Erratas lesen). ST hat hier über alle Versionen immer wieder 
Probleme.
Das schlimmste Problem ist, dass sie bei einem M4 den DMA nicht sauber 
gemacht haben (stürzt immer wieder ab, wenn zu viele Daten transferiert 
werden sollen).

Für Schreib- und Leseoperationen muss einfach der Ablauf wie in den 
Beispielen eingehalten werden. Dann klapts vielleicht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren