Forum: Mikrocontroller und Digitale Elektronik I2C-Bus MAster Read mit SAM7X8E AtmelStudio


von Andreas W. (andy_w)


Lesenswert?

Hallo,
ich habe ein seltsames Problem mit dem I2C-Bus für den Arduino Due im 
Atmel Studio. Initialisierung und Master Write funktioniert, d.h. der 
SLC ist richtig programmiert für 100kHz und die Master Write Routine 
nach dem Flußdiagramm im Datenblatt vom SAM3X8E funktioniert auch. Mit 
dem Skop kann ich die Signale SDA und SCL sehen und es sieht alles 
korrekt aus. Aber meine Master Read Routine funktioniert nicht, obwohl 
ich mich auch genau an das Flußdiagramm im Datenblatt halte. Hier der 
Code für meine Master Read Funktion, ich rufe die auf mit

aw_twi_master_receive(TWI0, 0x44, 1, data); // 0x44 is slave address
1
////////////////////////////////////////////////////////////////////////////////
2
//
3
//  TWI master mode: receive data
4
//
5
//  parameters:
6
// Twi*           p_twi             TWI0, TWI1
7
// uint32_t       adr               slave address 0x00-0x7f
8
// uint32_t       no_data           number of data bytes after slave address
9
// uint8_t*       data              data array
10
//
11
// return:
12
// uint32_t       error
13
//
14
////////////////////////////////////////////////////////////////////////////////
15
uint32_t aw_twi_master_receive(Twi *p_twi, uint32_t adr, uint32_t no_data, uint8_t *data)
16
{
17
   uint32_t    status, timeout, i;
18
19
   if (adr > 0x7f)
20
      return 1;
21
   if (no_data < 1)
22
      return 1;
23
   p_twi->TWI_CR = 0x00000024;                                                // disable slave, enable master
24
   p_twi->TWI_MMR = (adr << 16) | 0x00001000;                                 // slave adr, read
25
   if (no_data == 1)                                                          // one data byte
26
   {
27
      p_twi->TWI_CR = 0x00000003;                                             // write START | STOP
28
      timeout = 20000000;
29
      do                                                                      // wait for RXRDY = 1
30
      {
31
         status = p_twi->TWI_SR;
32
         timeout -= 1;
33
      } while (((status & 0x00000002) == 0) && (timeout > 0));
34
      if (timeout == 0)
35
         return 2;
36
      data[0] = (uint8_t)(p_twi->TWI_RHR & 0x000000ff);                       // read data
37
      timeout = 20000000;
38
      do                                                                      // wait for TXCOMP = 1
39
      {
40
         status = p_twi->TWI_SR;
41
         timeout -= 1;
42
      } while (((status & 0x00000001) == 0) && (timeout > 0));
43
      if (timeout == 0)
44
         return 3;
45
   }
46
   else
47
   {
48
      p_twi->TWI_CR = 0x00000001;                                             // write START
49
      i = 0;
50
      while (i < no_data)
51
      {
52
         timeout = 20000000;
53
         do                                                                   // wait for RXRDY = 1
54
         {
55
            status = p_twi->TWI_SR;
56
            timeout -= 1;
57
         } while (((status & 0x00000002) == 0) && (timeout > 0));
58
         if (timeout == 0)
59
            return 4;
60
         data[i] = (uint8_t)(p_twi->TWI_RHR & 0x000000ff);                    // read data
61
         i += 1;
62
         if (i >= (no_data - 1))
63
            p_twi->TWI_CR = 0x00000002;                                       // write STOP
64
      }
65
      timeout = 20000000;
66
      do                                                                      // wait for RXRDY = 1
67
      {
68
         status = p_twi->TWI_SR;
69
         timeout -= 1;
70
      } while (((status & 0x00000002) == 0) && (timeout > 0));
71
      if (timeout == 0)
72
         return 5;
73
      data[i] = (uint8_t)(p_twi->TWI_RHR & 0x000000ff);                       // read data
74
      timeout = 20000000;
75
      do                                                                      // wait for TXCOMP = 1
76
      {
77
         status = p_twi->TWI_SR;
78
         timeout -= 1;
79
      } while (((status & 0x00000001) == 0) && (timeout > 0));
80
      if (timeout == 0)
81
         return 6;
82
   }
83
   return 0;
84
}

Knackpunkt ist die Abfrage von RXRDY in TWI_SR, das wird nie auf 1 
gesetzt. Somit schlägt mein rudimentärer Timeout, den ich für Testzwecke 
eingebaut habe, zu und die Funktion endet mit dem Fehlercode 2, d.h. 
Timeout beim Warten auf RXRDY im Zweig für Master Read mit einem 
Datenbyte. Das gleiche passiert auch beim Master Read mit mehreren 
Datenbytes.

Ist das Datenblatt da fehlerhaft oder unvollständig? Der I2C-Slave ist 
hardwaremäßig angeschlossen und beim Master Write kommt von dem auch ein 
Ackknowledge.

Gruß
Andy

von Andreas W. (andy_w)


Lesenswert?

Hallo,
dieses Problem hat sich ausnahmsweise ganz einfach selbst gelöst: Durch 
Copy&Paste war war in der übergeordneten Routine, die das I2C-Device 
ansprach, die Slaveadresse in den Master Read Funktionsaufrufen falsch 
angegeben, in den Master Write Funktionsaufrufen dagegen richtig... Kaum 
ist das korrigiert worden, läuft auch der Master Read. Die obige 
Funktion funktioniert also doch.

So etwas kann schon mal vorkommen, wenn das Gesamtprojekt richtig groß 
ist, es ist eine Fernbedienung für einen Audio Mehrkanalvorverstärker, 
die auch alle anderen Geräte bedienen soll. Die hat ein 7" LCD mit 
resistivem Touchscreen, einen optischen Drehgeber (für Lautstärke usw.), 
einen Lichtsensor (I2C, um die LCD-Hintergrundbeleutung automatisch zu 
dimmen, wichtig für ein Heimkino), einen Beschleunigungssensor (um die 
Fernbedienung automatisch aus dem Standby aufzuwecken, wenn man die 
bewegt oder in die Hand nimmt), das Interface für den Touchscreen (I2C), 
einen HF-Transceiver (SPI, Kommikation muß per Funk erfolgen, da der 
Vorverstärker einen IR-Sender ansteuert, um alle anderen Geräte zu 
bedienen) und noch eine SD-Karte... Ebenso auch noch das Powermanagement 
für die Akkus. Der Vorverstärker selber ist noch eine ganze Ecke 
aufwendiger. Leider gibt es keine Fertiggeräte, die meine Anforderungen 
alle erfüllen, daher der Selbstbau.

Gruß
Andy

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.