I2C Probleme im STM8L

OP #2600029
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
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
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.
Gast
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);

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.