Forum: Mikrocontroller und Digitale Elektronik I2C Probleme im STM8L


von Owen S. (senmeis)


Lesenswert?

Hi,

ich möchte einen STM8L mit einem CO2 Sensor über I2C kommunizieren 
lassen. Als Muster wird ein Beispielcode von ST genommen. Die 
Beschreibung lautet:

•Phase 1: In master board I2C peripheral is configured in Master 
Transmitter with Interrupt, where in Slave board I2C peripheral is 
configured in Slave Receiver with Interrupt. The master will send Data 
to Slave according to the defined buffer size.

•Phase 2: In master board I2C peripheral is configured in Master 
Receiver with Polling, where in Slave board I2C peripheral is configured 
in Slave Transmitter with Interrupt. Once the master has initiated the 
communication (Start condition), the slave will send back the previously 
received data to the master

Ich beschäftige mich zur Zeit mit der ersten Phase. Der Codeabschnitt 
von Main() und ISR stehen unten.

Problem: Mit Debuggen erkennt man dass nur das erste Case in der ISR 
ausgeführt wird, also:
1
I2C_Send7bitAddress(I2C1, SLAVE_ADDRESS, I2C_Direction_Transmitter);
Die anderen werden nie erreicht. Der ganze Code hängt an der Stelle:
1
while (NumOfBytes);
Hat jemand ähnliche Probleme?

Das ist interessant dass der Master nur den Start generiert. Müssen 
Daten anhand
1
I2C_SendData()
von Hand gesendet werden?

Code:
1
/* TXBuffer initialization */
2
  TxBuffer[0] = 0x22;
3
  TxBuffer[1] = 0x00;
4
  TxBuffer[2] = 0x08;
5
  TxBuffer[3] = 0x2A;
6
  
7
  Delay((uint32_t)0xFFFF);
8
  
9
  /* Send START condition */
10
  I2C_GenerateSTART(I2C1, ENABLE);
11
    
12
  while (NumOfBytes);
13
  while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
14
15
  /* Add a delay to be sure that communication is finished */
16
  Delay(0xFFFF);
17
18
INTERRUPT_HANDLER(I2C1_SPI2_IRQHandler, 29)
19
{
20
  switch (I2C_GetLastEvent(I2C1))
21
  {
22
      /* EV5 */
23
    case I2C_EVENT_MASTER_MODE_SELECT :
24
      /* Send slave Address for write */
25
      I2C_Send7bitAddress(I2C1, SLAVE_ADDRESS, I2C_Direction_Transmitter);
26
      break;
27
28
      /* EV6 */
29
    case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
30
      if (NumOfBytes != 0)
31
      {
32
        /* Send the first Data */
33
        I2C_SendData(I2C1, TxBuffer[Tx_Idx++]);
34
35
        /* Decrement number of bytes */
36
        NumOfBytes--;
37
      }
38
      if (NumOfBytes == 0)
39
      {
40
        I2C_ITConfig(I2C1, I2C_IT_BUF, DISABLE);
41
      }
42
      break;
43
44
      /* EV8 */
45
    case I2C_EVENT_MASTER_BYTE_TRANSMITTING:
46
      /* Transmit Data */
47
      I2C_SendData(I2C1, TxBuffer[Tx_Idx++]);
48
49
      /* Decrement number of bytes */
50
      NumOfBytes--;
51
52
      if (NumOfBytes == 0)
53
      {
54
        I2C_ITConfig(I2C1, I2C_IT_BUF, DISABLE);
55
      }
56
      break;
57
58
      /* EV8_2 */
59
    case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
60
      /* Send STOP condition */
61
      I2C_GenerateSTOP(I2C1, ENABLE);
62
63
      I2C_ITConfig(I2C1, I2C_IT_EVT, DISABLE);
64
      break;
65
66
    default:
67
      break;
68
  }
69
}

MfG
Owen

von Jörg S. (joerg-s)


Lesenswert?

Ich vermute mal das dein Sensor kein ACK sendet. Ist die Adresse für den 
Sensor korrekt?

von Reinhard B. (brainstorm)


Lesenswert?

Owen Senmeis schrieb:
> Das ist interessant dass der Master nur den Start generiert. Müssen
> Daten anhandI2C_SendData()
> von Hand gesendet werden?

Nein, das geschieht im Interrupt Handler.

> Die anderen werden nie erreicht. Der ganze Code hängt an der Stelle:while 
(NumOfBytes);

Springt der Controller dann noch in den I2C Handler? Falls vom Slave das 
ACK nicht kommt: dieser Fall wird in der ISR nicht bearbeitet. Kenne 
aber die I2C Peripheral vom STM8L nicht und weiß nicht ob und wie das 
ACK ausgewertet wird.

mfg
Reinhard

von (prx) A. K. (prx)


Lesenswert?

Sieht schwer danach aus als ob der Slave sich nicht angesprochen fühlt, 
also beispielsweise die Slave-Adresse falsch ist.

Obacht, da gibts zwei Konventionen. Manchmal muss eine Slave-Adresse 
0100000X als 0x20 abgegeben werden, manchmal als 0x40.

von Das_Warzenschwein (Gast)


Lesenswert?

Ich würde an deiner Stelle die Slave-Adresse im Register "Own address 
register LSB (I2C_OARL)" nochmals anschauen:

Laut I2C-Protokoll: MSB (7:1) Adresse, LSB(R/W)
1
void I2C_Send7bitAddress(uint8_t Address, I2C_Direction_TypeDef Direction)
2
{
3
  /* Check function parameters */
4
  assert_param(IS_I2C_ADDRESS_OK(Address));
5
  assert_param(IS_I2C_DIRECTION_OK(Direction));
6
7
  /* !!!! hier fehlt die Zeile !!*/
8
  Address = ((uint8_t)(Address << 1); 
9
  /* Clear bit0 (direction) just in case */
10
  Address &= (uint8_t)0xFE;
11
12
  /* Send the Address + Direction */
13
  I2C->DR = (uint8_t)(Address | (uint8_t)Direction);

Ich wette, dass bei der Initialisierung des I2C auch ein Fehler 
enthalten ist
stm8s_i2c.c:
void I2C_Init(...)
1
/*--------------------------- I2C OAR Configuration ------------------------*/
2
  /* alt: I2C->OARL = (uint8_t)(OwnAddress); */ 
3
  /* neu */ I2C->OARL = (u8)(OwnAddress << 1);

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.