I2C-Hardcoremagistrale 150m entstoeren :-)

Hi,

Das ein anderer Slave dazwischen funkt und SDA auf low haelt, ist theoretisch denkbar. Nur wie kann man das herausfinden....

Widerstand in Reihe in die Leitung und an beiden Seiten die Spannung messen. Evtl den PullUp auf beide Seiten des Widerstandes aufteilen. An der Seite wo die Spannung am niedrigsten ist hält sie jemand nach GND.

also zB ...

SDA von Slaves ------ RPullUp*2 ---- RReihe ---- RPullUp*2 ----- SDA vom Master

Die beiden PullUps auf den Enden den RReihe bilden dann wieder ungefähr den vorherigen Wert (2 gleiche Werte parallel = halber Wert). Wenn du dann an beiden Seiten des RReihe die Spannung mißt, dann weißt du was Sache ist. Werden aber wohl nur wenige Millivolt sein.

Gruß
Dino
 
Hallo zusammen, hier die neueste Vermutung:

Ich war vorgestern bei einem anderen Kunden, wo ein Sensornetzwerk mit drei Slaves (Atmega8) und einem Master(Atmega32) die Heizung und Verteilerventile steuern soll. Beim Programmieren und Kalibrieren vor Ort konnten wir keine vernuenftige Kommunikation ueber I2C zwischen den uCs hinbekommen. Das sah in etwa so aus:
Der Master sprach den ersten Slave an und las die Daten aus. Bis hierhin ok. Beim zweiten Slave wurde grad noch die Adresse uebermittelt, danach nur noch Zacken und wirres Zeug (5x Start-/Stopkondition oder wilde Takte).
Gestern haben wir das Ganze hier im Buero nochmal nachgebaut auf dem Steckbrett mit dem gleichen Endeffekt. Ein paar Mal gehts gut, danach haengt sich alles auf. Im Netz kann ich nicht wirklich brauchbare Infos finden. Interessant ist, dass die Bascom ERR-Variable von Anfang an auf "1" ist, sogar wenn die Kommunikation am Anfang noch vernuenftig laeuft.

Hier koennte der Knackpunkt liegen. Wenn das Gleiche in der Halle passiert, dann hab ich schonmal die Erklaerung fuer die Haenger in der Kommunikation. Wir werden mal testweise die Bascombefehle fuer I2C rauswerfen und die TWI ueber die Register ansteuern. Mal sehen, was das Statusregister meldet und ob der Fehler weiterhin auftritt.
 
Hallo Jungs :) Ich hab den Fehler wahrscheinlich gefunden. Es koennte tatsaechlich an Bascom liegen. Nachdem ich gestern per Zufall gesehen habe, dass hier jemand das Gleiche Problem hat (Beitrag: Master - Slave - Slave hängt manchmal ), hab ich die Masterroutine fuers Steckbrett umgeschrieben und alles per Register gesteuert, ohne die Bascombefehle. Und es funktioniert.
Morgen fahren wir zur Halle und aendern das Masterprogramm auf Registerfahrt. Ehrlich gesagt bin ich ziemlich ueberrascht. Kann mir jemand hier erklaeren, warum der Bus mit den Bascombefehlen haengen bleibt? Mit I2C-Bausteinen laeuft das doch eigentlich immer einwandfrei. Warum mit Atmegas als Slaves nicht?
 
Habs jetzt nicht komplett mitverfolgt - hast Du bereits herausbekommen, ob bei Bascom der Master oder der Slave nicht richtig funktioniert? Dann könnte man mal ein minimalistisches Programm mit diesem reproduzierbaren Effekt reassemblieren...
Ich selbst habe mich mit TWI aber noch nicht wirklich beschäftigt.

Soweit ich das jetzt richtig in Erinnerung habe, sollte beim HW-TWI alle Nase lang 'n Interrupt auftreten, in dem das TWI-Statusregister (?) auf einen (zum derzeitigen Status passenden) Zustand auszuwerten ist (State Machine).
 
Ok, nochmal langsam zum mitschreiben :) JAAAAA, ich hab den Fehler gefunden. Es sind weder die Pullups, noch sonst irgendein physischer Fehler im Netzwerk. Es scheint an Bascom zu liegen. Freitag vor einer Woche wollten wir bei einem anderen Kunden eine neu entwickelte Heizungssteuerung in Betrieb nehmen. Dort sollen vier Atmegas miteinander Daten austauschen. Bei einem Testlauf funktionierte garnichts. Ein Blick auf den Logikanalysator zeigte, dass der erste Atmega seine Daten an den Master uebertrug, beim zweiten Slave stand dann nach dem Uebertragen der Slaveadresse bereits der Bus still. Stattdessen wurden irgendwelche nichtdefinierten Pulse uebertragen und dann nichts mehr. Nur ein kompletter Hardwarereset brachte den Bus wieder auf Null. Wir haben das Ganze mehrmals mit unterschiedlichen Bedingungen probiert, z.B. Slaves aus der Schaltung entfernt um zu schauen, ob nicht ein weiterer Slave den Bus stoert, etc. Aber es war stehts dasselbe: Eine Kommunikation ging durch, die zweite nicht mehr. Egal, in welcher Reihenfolge die Slave angesprochen wurden.

Daher kam die Idee, dass das gleiche Problem ebenfalls in der Halle sein koennte, da dort fast 20 Atmegas miteinander verbunden sind. Also haben wir eine Schaltung mit 4 Atmega-Slaves auf dem Steckbrett aufgebaut und mit minimalistischen Programmen getestet. Auch hier hing der Bus beim zweiten Slave sofort fest. Daraufhin haben wir statt den Atmegas vier I2C-EEPROMs genommen. Resultat: Funktioniert ohne Probleme. Keine Haenger, keine wirren Pulse. Nach dem Ausschlussverfahren beurteilt blieben dann nur noch zwei Moeglichkeiten:

-Hardwarebug im Atmega
-Softwarebug in Bascom

Den Atmega aufschrauben kann man ja leider nicht, also haben wir die Software auf manuelle Registersteuerung umgeschrieben. Sprich, statt:

Code:
'--- Messung starten---

I2cstart
 I2cwbyte Adress_w
  I2cwbyte &HCC
   I2cstop

Waitms 200

'--- Daten abrufen ---

I2cstart
 I2cwbyte Adress_r
  I2crbyte Access_code , Ack
   I2crbyte Data_t11_msb , Ack
    I2crbyte Data_t11_lsb , Ack
     I2crbyte Data_t12_msb , Ack
      I2crbyte Data_t12_lsb , Ack
       I2crbyte Data_t13_msb , Ack
        I2crbyte Data_t13_lsb , Nack
I2cstop


haben wir das so geschrieben:

Code:
'--- Messung starten ----

Twcr = &B10100100
    
 Gosub Twi_int_wait
  If Twi_status = &H08 Then
   Twdr = Adress_w
  Else
   .......
  End If


Twcr = &B10000100
 Gosub Twi_int_wait
  If Twi_status = &H18 Then
   Twdr = &HCC
  Else
   .....
  End If



Twcr = &B10000100
 Gosub Twi_int_wait
  If Twi_status = &H28 Then
   Twcr = &B10010100
   else
    .......
   End if

   Waitms 200

'--- Datenabruf ---

Twcr = &B10100100                                         

 Gosub Twi_int_wait
  If Twi_status = &H08 Then
   Twdr = &H13                                         
    Twcr = &B10000100
  Else
   .....
  End If

 Gosub Twi_int_wait

 If Twi_status = &H40 Then
  Twcr = &B11000100
 Else
  .....
 End If


 Gosub Twi_int_wait
  Statusregister_array(4) = Twi_status
   If Twi_status = &H50 Then
    Access_code = Twdr                                          
   Else
    .....
   End If


   For I = 1 To 6
    Select Case I
     Case 1 To 5 : Twcr = &B11000100                        
                      Gosub Twi_int_wait
                         If Twi_status = &H50 Then
                          Data_array(i) = Twdr
                         Else
                          .....
                         End If
     Case 6 : Twcr = &B10000100
                 Gosub Twi_int_wait                 
                   If Twi_status = &H58 Then
                    Data_array(i) = Twdr
                   Else
                    .....
                   End If
    End Select
   Next


  Twcr = &B10010100

Mit dem manuellen Code laeuft alles wie es sollte. Auf dem Steckbrett mehrere Stunden ohne Fehler. Seit gestern auch in der Halle. Um 23.00 haben wir das System mit neuer Software gestartet und eine Melderoutine fuer den Server geschrieben. Ab jetzt wird das Statusregister waehrend der Kommunikation schrittweise in einen zusaetzlichen Array kopiert und bei fehlerhafter Kommunikation ueber den Server zu mir gemailt. Heute um 0.05 trat ein einziger Fehler auf, ein Slave hat wohl ein Ack ueberhoert. Meine Error_isr hat daraufhin das System resetet und weiter gings bis jetzt ohne einen einzigen Fehler.

Fazit:
Bascom scheint ein Problem mit der Kommunikation zwischen uCs per I2C zu haben. Anders kann ich mir das Verhalten nicht erklaeren. Etwas seltsam ist das schon, ich hab vor einiger Zeit eine Hausautomatik gebaut, wo 10 Atmegas per I2C mit den Standardbefehlen kommunizieren und das klappt bis heute ohne (bisher sichtbare) Probleme. Interessant ist auch, dass wir gestern die Busgeschwindigkeit erheblich heraufsetzen konnten. Das System arbeitet jetzt mit 100kHz, was vorher unter den Bascombefehlen regelmaessig zu fehlerhaften Daten beim Auslesen fuehrte. Aus Spass haben wir gestern auch mal mit 400kHz getaktet. Das geht auch noch, ist aber laut Oszilloskop hart an der Schmerzgrenze :) Aber immerhin, ich freue mich, dass meine Berechnungen, was den Bus betrifft, richtig waren und die angegebenen 4000pF maximale Kabelkapazitaet im Datenblatt des P82B96 nicht die absolute Obergrenze darstellen. Laut Messung hab ich irgendwas um die 7500pF im Kabel :)
 
...Daraufhin haben wir statt den Atmegas vier I2C-EEPROMs genommen. Resultat: Funktioniert ohne Probleme. Keine Haenger, keine wirren Pulse. Nach dem Ausschlussverfahren beurteilt blieben dann nur noch zwei Moeglichkeiten:

-Hardwarebug im Atmega
-Softwarebug in Bascom...
Was spricht gegen einen Softwarebug im Slave?
(Ob von Bascom oder Dir erstmal außen vor)

Hast Du zum ersten Code noch die Init-Zeile? Dann schau ich mal rein...
(Controller und Takt? Welche Bascom-Version?)

Kann ich das Reassemblat hier posten, oder sieht da wer Probleme?
 
Was spricht gegen einen Softwarebug im Slave?
(Ob von Bascom oder Dir erstmal außen vor)

Die Slaveroutine hab ich fuer den Test extra aufs minimalste beschraenkt, also ohne irgendwelche weiteren Anweisungen ausser der Kommunikationsroutine.

Code:
 $regfile = "m8def.dat"
 $crystal = 8000000

 $swstack = 50
 $hwstack = 50
 $framesize = 50


 Config Sda = Portc.4
 Config Scl = Portc.5

 Twcr = &B01000100
 Twsr = 0
 Twbr = 32
 Twar = &H10

 I2cinit

'................................................

 Do


   Twi_control = Twcr And &H80

    If Twi_control = &H80 Then
     Twi_status = Twsr And &HF8
       Gosub Comstart
    End If


   Waitms 250



 Loop

 End

'===============================================================================

 Comstart:

  Do

     Twi_control = Twcr And &H80

      If Twi_control = &H80 Then

       Twi_status = Twsr And &HF8




        Select Case Twi_status
         Case &H60 : Twcr = &B11000100
         Case &H80 : Request = Twdr
                      Twcr = &B11000100
         Case &HA0 : Twcr = &B11000100
                      Exit do
         Case &HA8 : Twdr = &H11
                      Twcr = &B11000100
                       I = 1
         Case &HB8 : Select Case I
                      Case 1 : Twdr = &H01
                      Case 2 : Twdr = &H02
                      Case 3 : Twdr = &H03
                      Case 4 : Twdr = &H04
                      Case 5 : Twdr = &H05
                      Case 6 : Twdr = &H06
                      Case Else : Twdr = &H99
                     End Select

                      Twcr = &B11000100
                      Incr I

          Case Else : Twcr = &B11000100
                       I = 1
                        Exit do
        End Select

      End If

  Loop 

 Return

Hast Du zum ersten Code noch die Init-Zeile? Dann schau ich mal rein...
(Controller und Takt? Welche Bascom-Version?)

Sicher kannst Du die haben. Einmal:

Code:
 $regfile = "m32def.dat"
 $crystal = 16000000

 $swstack = 50
 $hwstack = 50
 $framesize = 50
 $lib "i2c_twi.lbx"


 Config Scl = Portc.0
 Config Sda = Portc.1
 Config Twi = 100000

 I2cinit

Zweimal:

Code:
 $regfile = "m32def.dat"
 $crystal = 4915200

 $baud = 9600
 $hwstack = 70
 $swstack = 70

'...............................................................................

 Config Scl = Portc.0
 Config Sda = Portc.1

 Config Twi = 100000

 I2cinit

Mit der Config hab ich auch schon experimentiert. Mit und ohne LIB, statt Config Twi mal TWBR = 72, kein Unterschied.

IDE-/Compilerversion 2.0.7.0.
 
Hallo,

wer sich wundert ... den anderen Thread habe ich zuerst gelesen. :rolleyes:

Also hast du nur Atmels als Master und Slaves am laufen. Soweit verstanden :D

Was spricht gegen einen Softwarebug im Slave?
(Ob von Bascom oder Dir erstmal außen vor)
Wäre logisch betrachtet auch mein Schluß.

Kann ich das Reassemblat hier posten, oder sieht da wer Probleme?
Also so wie ich es verstehe darf Uwe die LIB für I2C-Slaves (da kostenpflichtig) nicht mitliefern. Er dürfte dir aber eine compilierte brennbare Datei liefern oder den Quellcode des Slaves (ohne die Lib!). Aus der brennbaren Datei könntest du natürlich wieder ein Reassemblat machen. Das wäre reengineering. Theoretisch gesehen wäre das ja nicht mehr die ausgelieferte Lib. :rolleyes: :flute: ... Ui Ui ... heißes Eisen und Messers Schneide :p

Da müßte Dirk sich mal zu auslassen was er davon hält.

Gruß
Dino
 
Hallo,

Also so wie ich es verstehe darf Uwe die LIB für I2C-Slaves (da kostenpflichtig) nicht mitliefern. Er dürfte dir aber eine compilierte brennbare Datei liefern oder den Quellcode des Slaves (ohne die Lib!). Aus der brennbaren Datei könntest du natürlich wieder ein Reassemblat machen. Das wäre reengineering. Theoretisch gesehen wäre das ja nicht mehr die ausgelieferte Lib. :rolleyes: :flute: ... Ui Ui ... heißes Eisen und Messers Schneide :p

Kuck mal in meinen letzten Beitrag hier, ueber den Configs, da ist die Slave-Routine. Die darf man ruhig reassemblern, dort sind keine kostenpflichtigen Bibliotheken enthalten. Die paar Zeilen sind keine 10-15 Euronen wert, dass kann man selbst genausogut schreiben. Waere lustig, wenn die den Busterror verursachen wuerden und geaendert werden muesste weil eben diese Routine in etlichen Kundensystemen von mir programmiert ist und laeuft. Wenn ich die alle updaten muesste....ohje
Uebrigens erklaert sich damit, warum es ueber die Register laeuft. Hab mich grad nochmal in der Halle eingeloggt und die Logs betrachtet, weiterhin laeuft alles bereits seit 25 Stunden ohne jegliche Fehler. Wenn das Problem die Slaves waeren, dann wuerde das Problem ja weiterhin bestehen oder sich zumindest vereinzelt bemerkbar machen. Das gleiche Ergebnis hab ich auf dem Schreibtisch (Testaufbau). Zweiter Punkt, der dagegen spricht: Der Busterror beginnt mit dem ersten wbyte, nachdem der Slave seine Adresse geackt hat. Da die einfachste Moeglichkeit meist die richtige ist, faellt auch hier wieder die Vermutung auf den Master, weil er an der Reihe ist. Der Slave wartet, wie man in meiner Routine sehen kann, auf TWINT.
 
Hallo zusammen,
Da müßte Dirk sich mal zu auslassen was er davon hält.

ich habe das Thema nun nicht so genau verfolgt, aber ich würde hier einfach mal den Autor der Bascom-Lib kontaktieren, wenn man soweit alles andere als Fehlerquelle ausschließen kann ... erwähnen würde ich aber die Rahmenbedingungen, wie der Bus eingesetzt wird. :)

Dirk :ciao:
 
Hallo zusammen,


ich habe das Thema nun nicht so genau verfolgt, aber ich würde hier einfach mal den Autor der Bascom-Lib kontaktieren, wenn man soweit alles andere als Fehlerquelle ausschließen kann ... erwähnen würde ich aber die Rahmenbedingungen, wie der Bus eingesetzt wird. :)

Dirk :ciao:

Rahmenbedingunegn:

Steckboard, Buslaenge 10cm, 5k Pullups :)
 
Rahmenbedingunegn:

Steckboard, Buslaenge 10cm, 5k Pullups :)

Ja, das könntest du dann mitteilen. Eventuell ist die Betriebsspannung noch interessant und die Anzahl der Slaves und welche Mikrocontroller.

Helfen kann ich hier nicht besonders, da ich Bascom nicht einsetze und mich deswegen hier nicht so auskenne :)

Dirk :ciao:
 
Wenn ich Dir drei .hex-Dateien schicke, kannst Du die reassemblern?

Liegt die Lib als Quellcode vor? Wenn ja, wäre es doch gut, wenn hier mal jemand drüberschaut, der sich mit Bascom und Libs auskennt. Wenn es um disassemblieren geht, da denke ich, es hatte sich ja LotadaC angeboten. Vielleicht teste auch mal mit eigenen Bascom-Routinen, also ohne Lib.

Auch wenn du schon mit kurzen Leitungen getestet hast, verwende testweise vor dem SCL Eingang des Slaves einen kleinen Tiefpass (R*C = 200ns zB., C auf der Slave Seite nach GND). Dies unterdrückt ggf. auftretende Störungen, die der Slave möglicherweise als Clock interpretiert. Wäre zumindest mal ein Versuch wert :)

Dirk :ciao:
 
Also ich hab auch nur die Bascom-Vollversion, also ohne zusätzliche Kauf-Lib.
Reassemblieren könnte ich mit dem AVR-Studio 5 (howTo), ggf auch mit 4. (Ohne lib. Also ich würde das erst selbst compilieren)

Aber was? Die minimalistische Slave-Variante geht ja eigentlich bereits über die Register (mit TWINT-Polling)
Den Master-Code, der mit mehreren Eeprom-ICs geht, aber nicht mit mehreren AVR (also deinem Code)?

Schon mal versucht, Eeprom und einen AVR-Slave zusammen zu testen?
Oder ein und denselben Slave mit unterschiedlichen Adressen (also zwischendurch die Adresse zu ändern)?

Klar, mit dem selbstgestrickten Master-Code hast Du das Problem umgangen, und somit irgendwie gelöst, aber trotzdem wurmt es (mich), das eigentliche Problem nicht zu sehen...
Die Bascom-Routinen laufen ja mit dem Eeprom (von dem ich ausgehe, daß die sich an Normen halten), nicht aber mit Deinen Slave-Routinen. Deine Master-Routinen laufen mit beidem (oder?). Wo ist da der Unterschied? Also was ist in Deiner Masterimplementierung anders, was kann Deine Slave-Implementierung nicht (was Bascom als Master erwartet)?
 
Klar, mit dem selbstgestrickten Master-Code hast Du das Problem umgangen, und somit irgendwie gelöst, aber trotzdem wurmt es (mich), das eigentliche Problem nicht zu sehen...
Die Bascom-Routinen laufen ja mit dem Eeprom (von dem ich ausgehe, daß die sich an Normen halten), nicht aber mit Deinen Slave-Routinen. Deine Master-Routinen laufen mit beidem (oder?). Wo ist da der Unterschied? Also was ist in Deiner Masterimplementierung anders, was kann Deine Slave-Implementierung nicht (was Bascom als Master erwartet)?

Genau... das waere eben interessant herauszufinden. Ich wuerde gern mal das Masterprogramm per Bascom-I2C reassemblern und mit dem manuellen Master vergleichen. Irgendwo muss der Wurm drinstecken verd.... nochmal. Die Slaveadressen haben wir auch geaendert und getestet. Nur der Versuch mit zusaetzlichen I2C-Bausteinen fehlt noch. Vielleicht komme ich morgen dazu es mal zu testen.
 
Hatte mein kleines howTo zum reassemblieren ja bereits oben verlinkt - wie beschrieben kommt mein betagter Rechner da an seine Grenzen. Wenn Du das Studio installiert hast, kannst Du es auch selbst reassemblieren, und hier (wenn kein geschützter Code enthalten ist (Deiner oder die lib)) als Code-Block einstellen. Ich selbst habe dieses WE wegen Arbeit nicht viel Zeit, wie's nächste Woche aussieht, kann ich nicht sagen. Aber ich schau in den Pausen mit'm Handy hier mal rein...

Frage noch am Rande: Warum verwendest Du (zumindest in der selbst implementierten Slave-Variante (Case-Struktur mit der Abfrage der Register)) nicht den TWI-Interrupt?

Hast Du meinen Vorschlag, Eeprom-ICs und AVR-Slaves mal zusammen zu testen versucht? (Kann man nach einem erfolgten Eeprom-Zugriff auf den AVR wechseln? Und umgekehrt?)

War das Verhalten jetzt eigentlich (sicher) reproduzierbar? Also hängt sich irgendwas genau dann auf, wenn Du versuchst, etwas von einer 2ten Adresse zu lesen? Immer?
 
Hallo Uwe,

gib mal bescheid, ob und wie das jetzt hier weitergehen soll...

Wenn ich irgendwas (zulässiges) reassemblieren und analysieren soll, poste wenigstens den entsprechenden Bascom-Code.

Ausgehend von den letzten Beiträgen hatte ich dieses Bascom Programm zusammengesetzt:
Code:
$regfile = "m32def.dat"
 $crystal = 4915200

 $baud = 9600
 $hwstack = 70
 $swstack = 70
 Dim Adress_w As Byte
 Dim Adress_r As Byte
 Dim Access_code As Byte
 Dim Data_t11_msb As Byte
 Dim Data_t11_lsb As Byte
 Dim Data_t12_msb As Byte
 Dim Data_t12_lsb As Byte
 Dim Data_t13_msb As Byte
 Dim Data_t13_lsb As Byte
 Adress_r = 9
 Adress_w = 8

'...............................................................................

 Config Scl = Portc.0
 Config Sda = Portc.1

 Config Twi = 100000

 I2cinit

 '--- Messung starten---

I2cstart
 I2cwbyte Adress_w
  I2cwbyte &HCC
   I2cstop

Waitms 200

'--- Daten abrufen ---

I2cstart
 I2cwbyte Adress_r
  I2crbyte Access_code , Ack
   I2crbyte Data_t11_msb , Ack
    I2crbyte Data_t11_lsb , Ack
     I2crbyte Data_t12_msb , Ack
      I2crbyte Data_t12_lsb , Ack
       I2crbyte Data_t13_msb , Ack
        I2crbyte Data_t13_lsb , Nack
I2cstop
(Jaja, da fehlt das End. tut hier aber nichts zur Sache...)
Reassembliert ergiebt das folgendes:
Code:
     1: $regfile = "m32def.dat"
00000000  JMP 0x0000002A		Jump 
00000002  RETI 		Interrupt return 
00000003  NOP 		No operation 
00000004  RETI 		Interrupt return 
00000005  NOP 		No operation 
00000006  RETI 		Interrupt return 
00000007  NOP 		No operation 
00000008  RETI 		Interrupt return 
00000009  NOP 		No operation 
0000000A  RETI 		Interrupt return 
0000000B  NOP 		No operation 
0000000C  RETI 		Interrupt return 
0000000D  NOP 		No operation 
0000000E  RETI 		Interrupt return 
0000000F  NOP 		No operation 
00000010  RETI 		Interrupt return 
00000011  NOP 		No operation 
00000012  RETI 		Interrupt return 
00000013  NOP 		No operation 
00000014  RETI 		Interrupt return 
00000015  NOP 		No operation 
00000016  RETI 		Interrupt return 
00000017  NOP 		No operation 
00000018  RETI 		Interrupt return 
00000019  NOP 		No operation 
0000001A  RETI 		Interrupt return 
0000001B  NOP 		No operation      
0000001C  RETI 		Interrupt return 
0000001D  NOP 		No operation 
0000001E  RETI 		Interrupt return 
0000001F  NOP 		No operation 
00000020  RETI 		Interrupt return 
00000021  NOP 		No operation 
00000022  RETI 		Interrupt return 
00000023  NOP 		No operation 
00000024  RETI 		Interrupt return 
00000025  NOP 		No operation 
00000026  RETI 		Interrupt return 
00000027  NOP 		No operation 
00000028  RETI 		Interrupt return 
00000029  NOP 		No operation 
0000002A  LDI R24,0x5F		Load immediate 
0000002B  OUT 0x3D,R24		Out to I/O location 
0000002C  LDI R28,0x1A		Load immediate 
0000002D  LDI R30,0xD4		Load immediate 
0000002E  MOV R4,R30		Copy register 
0000002F  LDI R24,0x08		Load immediate 
00000030  OUT 0x3E,R24		Out to I/O location 
00000031  LDI R29,0x08		Load immediate 
00000032  LDI R31,0x07		Load immediate 
00000033  MOV R5,R31		Copy register 
00000034  WDR 		Watchdog reset 
00000035  IN R24,0x34		In from I/O location 
00000036  MOV R0,R24		Copy register 
00000037  ANDI R24,0xF7		Logical AND with immediate 
00000038  OUT 0x34,R24		Out to I/O location 
00000039  LDI R24,0x18		Load immediate 
0000003A  CLR R25		Clear Register 
0000003B  OUT 0x21,R24		Out to I/O location 
0000003C  OUT 0x21,R25		Out to I/O location 
0000003D  LDI R30,0xFE		Load immediate 
0000003E  LDI R31,0x07		Load immediate 
0000003F  LDI R26,0x60		Load immediate 
00000040  LDI R27,0x00		Load immediate 
00000041  CLR R24		Clear Register 
00000042  ST X+,R24		Store indirect and postincrement 
00000043  SBIW R30,0x01		Subtract immediate from word 
00000044  BRNE PC-0x02		Branch if not equal 
00000045  LDI R24,0x1F		Load immediate 
00000046  OUT 0x09,R24		Out to I/O location 
00000047  LDI R24,0x00		Load immediate 
00000048  OUT 0x20,R24		Out to I/O location 
00000049  LDI R24,0x18		Load immediate 
0000004A  OUT 0x0A,R24		Out to I/O location 
0000004B  CLR R6		Clear Register 
    16:  Adress_r = 9
0000004C  LDI R24,0x09		Load immediate 
0000004D  STS 0x0061,R24		Store direct to data space 
    17:  Adress_w = 8
0000004F  LDI R24,0x08		Load immediate 
00000050  STS 0x0060,R24		Store direct to data space 
    24:  Config Twi = 100000
00000052  LDI R23,0x00		Load immediate 
00000053  OUT 0x01,R23		Out to I/O location 
00000054  LDI R23,0x10		Load immediate 
00000055  OUT 0x00,R23		Out to I/O location 
    26:  I2cinit
00000056  CALL 0x000000AC		Call subroutine 
    30: I2cstart
00000058  CALL 0x000000B1		Call subroutine 
    31:  I2cwbyte Adress_w
0000005A  LDI R26,0x60		Load immediate 
0000005B  LDI R27,0x00		Load immediate 
0000005C  LD R17,X		Load indirect 
0000005D  CALL 0x000000C9		Call subroutine 
    32:   I2cwbyte &HCC
0000005F  LDI R17,0xCC		Load immediate 
00000060  CALL 0x000000C9		Call subroutine 
    33:    I2cstop
00000062  CALL 0x000000C0		Call subroutine 
    35: Waitms 200
00000064  LDI R24,0xC8		Load immediate 
00000065  LDI R25,0x00		Load immediate 
00000066  CALL 0x0000009D		Call subroutine 
    39: I2cstart
00000068  CALL 0x000000B1		Call subroutine 
    40:  I2cwbyte Adress_r
0000006A  LDI R26,0x61		Load immediate 
0000006B  LDI R27,0x00		Load immediate 
0000006C  LD R17,X		Load indirect 
0000006D  CALL 0x000000C9		Call subroutine 
    41:   I2crbyte Access_code , Ack
0000006F  CALL 0x000000E8		Call subroutine 
00000071  LDI R26,0x62		Load immediate 
00000072  LDI R27,0x00		Load immediate 
00000073  ST X,R17		Store indirect 
    42:    I2crbyte Data_t11_msb , Ack
00000074  CALL 0x000000E8		Call subroutine 
00000076  LDI R26,0x63		Load immediate 
00000077  LDI R27,0x00		Load immediate 
00000078  ST X,R17		Store indirect 
    43:     I2crbyte Data_t11_lsb , Ack
00000079  CALL 0x000000E8		Call subroutine 
0000007B  LDI R26,0x64		Load immediate 
0000007C  LDI R27,0x00		Load immediate 
0000007D  ST X,R17		Store indirect 
    44:      I2crbyte Data_t12_msb , Ack
0000007E  CALL 0x000000E8		Call subroutine 
00000080  LDI R26,0x65		Load immediate 
00000081  LDI R27,0x00		Load immediate 
00000082  ST X,R17		Store indirect 
    45:       I2crbyte Data_t12_lsb , Ack
00000083  CALL 0x000000E8		Call subroutine 
00000085  LDI R26,0x66		Load immediate 
00000086  LDI R27,0x00		Load immediate 
00000087  ST X,R17		Store indirect 
    46:        I2crbyte Data_t13_msb , Ack
00000088  CALL 0x000000E8		Call subroutine 
0000008A  LDI R26,0x67		Load immediate 
0000008B  LDI R27,0x00		Load immediate 
0000008C  ST X,R17		Store indirect 
    47:         I2crbyte Data_t13_lsb , Nack
0000008D  CALL 0x000000E6		Call subroutine 
0000008F  LDI R26,0x68		Load immediate 
00000090  LDI R27,0x00		Load immediate 
00000091  ST X,R17		Store indirect 
    48: I2cstop
00000092  CALL 0x000000C0		Call subroutine 
00000094  SBIW R30,0x01		Subtract immediate from word 
00000095  BRNE PC-0x01		Branch if not equal 
00000096  RET 		Subroutine return 
00000097  SET 		Set T in SREG 
00000098  BLD R6,2		Bit load from T to register 
00000099  RET 		Subroutine return 
0000009A  CLT 		Clear T in SREG 
0000009B  BLD R6,2		Bit load from T to register 
0000009C  RET 		Subroutine return 
0000009D  PUSH R30		Push register on stack 
0000009E  PUSH R31		Push register on stack 
0000009F  CLR R30		Clear Register 
000000A0  OR R30,R24		Logical OR 
000000A1  OR R30,R25		Logical OR 
000000A2  BREQ PC+0x07		Branch if equal 
000000A3  LDI R30,0xCD		Load immediate 
000000A4  LDI R31,0x04		Load immediate 
000000A5  SBIW R30,0x01		Subtract immediate from word 
000000A6  BRNE PC-0x01		Branch if not equal 
000000A7  SBIW R24,0x01		Subtract immediate from word 
000000A8  BRNE PC-0x05		Branch if not equal 
000000A9  POP R31		Pop register from stack 
000000AA  POP R30		Pop register from stack 
000000AB  RET 		Subroutine return 
000000AC  CBI 0x15,1		Clear bit in I/O register 
000000AD  CBI 0x15,0		Clear bit in I/O register 
000000AE  CBI 0x14,1		Clear bit in I/O register 
000000AF  CBI 0x14,0		Clear bit in I/O register 
000000B0  RET 		Subroutine return 
000000B1  SBI 0x14,0		Set bit in I/O register 
000000B2  CBI 0x14,1		Clear bit in I/O register 
000000B3  RCALL PC+0x0004		Relative call subroutine 
000000B4  CBI 0x14,0		Clear bit in I/O register 
000000B5  RCALL PC+0x0002		Relative call subroutine 
000000B6  SBI 0x14,1		Set bit in I/O register 
000000B7  PUSH R30		Push register on stack 
000000B8  PUSH R31		Push register on stack 
000000B9  LDI R30,0x02		Load immediate 
000000BA  LDI R31,0x00		Load immediate 
000000BB  CALL 0x00000094		Call subroutine 
000000BD  POP R31		Pop register from stack 
000000BE  POP R30		Pop register from stack 
000000BF  RET 		Subroutine return 
000000C0  SBI 0x14,0		Set bit in I/O register 
000000C1  SBI 0x14,1		Set bit in I/O register 
000000C2  RCALL PC-0x000B		Relative call subroutine 
000000C3  CBI 0x14,0		Clear bit in I/O register 
000000C4  SBIS 0x13,0		Skip if bit in I/O register set 
000000C5  RJMP PC-0x0001		Relative jump 
000000C6  RCALL PC-0x000F		Relative call subroutine 
000000C7  CBI 0x14,1		Clear bit in I/O register 
000000C8  RJMP PC-0x0011		Relative jump 
000000C9  SEC 		Set Carry 
000000CA  ROL R17		Rotate Left Through Carry 
000000CB  RJMP PC+0x0002		Relative jump 
000000CC  LSL R17		Logical Shift Left 
000000CD  BREQ PC+0x0E		Branch if equal 
000000CE  SBI 0x14,0		Set bit in I/O register 
000000CF  BRCC PC+0x04		Branch if carry cleared 
000000D0  NOP 		No operation 
000000D1  CBI 0x14,1		Clear bit in I/O register 
000000D2  RJMP PC+0x0003		Relative jump 
000000D3  SBI 0x14,1		Set bit in I/O register 
000000D4  RJMP PC+0x0001		Relative jump 
000000D5  RCALL PC-0x001E		Relative call subroutine 
000000D6  CBI 0x14,0		Clear bit in I/O register 
000000D7  SBIS 0x13,0		Skip if bit in I/O register set 
000000D8  RJMP PC-0x0001		Relative jump 
000000D9  RCALL PC-0x0022		Relative call subroutine 
000000DA  RJMP PC-0x000E		Relative jump 
000000DB  SBI 0x14,0		Set bit in I/O register 
000000DC  CBI 0x14,1		Clear bit in I/O register 
000000DD  RCALL PC-0x0026		Relative call subroutine 
000000DE  CBI 0x14,0		Clear bit in I/O register 
000000DF  SBIS 0x13,0		Skip if bit in I/O register set 
000000E0  RJMP PC-0x0001		Relative jump 
000000E1  CLT 		Clear T in SREG 
000000E2  SBIC 0x13,1		Skip if bit in I/O register cleared 
000000E3  SET 		Set T in SREG 
000000E4  BLD R6,2		Bit load from T to register 
000000E5  RJMP PC-0x002E		Relative jump 
000000E6  SEC 		Set Carry 
000000E7  RJMP PC+0x0002		Relative jump 
000000E8  CLC 		Clear Carry 
000000E9  ROL R19		Rotate Left Through Carry 
000000EA  LDI R17,0x01		Load immediate 
000000EB  SBI 0x14,0		Set bit in I/O register 
000000EC  CBI 0x14,1		Clear bit in I/O register 
000000ED  RCALL PC-0x0036		Relative call subroutine 
000000EE  CBI 0x14,0		Clear bit in I/O register 
000000EF  SBIS 0x13,0		Skip if bit in I/O register set 
000000F0  RJMP PC-0x0001		Relative jump 
000000F1  RCALL PC-0x003A		Relative call subroutine 
000000F2  CLC 		Clear Carry 
000000F3  SBIC 0x13,1		Skip if bit in I/O register cleared 
000000F4  SEC 		Set Carry 
000000F5  ROL R17		Rotate Left Through Carry 
000000F6  BRCC PC-0x0B		Branch if carry cleared 
000000F7  SBI 0x14,0		Set bit in I/O register 
000000F8  ROR R19		Rotate right through carry 
000000F9  BRCC PC+0x03		Branch if carry cleared 
000000FA  CBI 0x14,1		Clear bit in I/O register 
000000FB  RJMP PC+0x0002		Relative jump 
000000FC  SBI 0x14,1		Set bit in I/O register 
000000FD  RCALL PC-0x0046		Relative call subroutine 
000000FE  CBI 0x14,0		Clear bit in I/O register 
000000FF  SBIS 0x13,0		Skip if bit in I/O register set 
00000100  RJMP PC-0x0001		Relative jump 
00000101  RCALL PC-0x004A		Relative call subroutine 
00000102  RET 		Subroutine return
(hier fehlt die entsprechende Endlosschleife dann bei 0x00000094 (also hinter dem Call, und vor der Zeitschleifen-Subroutine)

Ich habe bereits gut ein drittel des Reassemblates dokumentiert gehabt, bis ich zum interessanten Teil gekommen bin - und da ist mir aufgefallen daß "Config TWI blablabla" und "I2cinit" die Hardware-TWI-Register entsprechend manipulieren, "I2cstart/stop/c/rbyte" aber in Software auf den C-Pins rummachen.

Das ist ja irgendwie Murks - also gib mir mal ne Minimalversion des Verfahrens, wie Du es wirklich machst...

(und nein, ich hab jetzt keinen Bock, mich mit der Bascom-Hilfe auseinander zu setzen)
 
Hi,

Ich habe bereits gut ein drittel des Reassemblates dokumentiert gehabt, bis ich zum interessanten Teil gekommen bin - und da ist mir aufgefallen daß "Config TWI blablabla" und "I2cinit" die Hardware-TWI-Register entsprechend manipulieren, "I2cstart/stop/c/rbyte" aber in Software auf den C-Pins rummachen.
:confused: Macht Bascom da etwa nen Mischmasch aus Software- und Hardware-TWI? Wär ja der Hammer :p

Gruß
Dino
 
Ich denke eher, daß ich den Mischmasch erzeugen lasse (wie gesagt ist mir nicht ganz klar, was Uwe als Bascom-Mastercode verwendet). Ob's bei den Einstellungen irgendwelche Defaults zum TWI gibt, hab ich nicht nachgesehen, wäre natürlich möglich.

Korrektur: "I2cinit" ist auch Software

"Config Twi" beschreibt das BitRateRegister und das Twi-StatusRegister (Status=0, Prescaler...) - hier wird also die Geschwindigkeit der Hardware eingestellt

"I2cinit" legt nur die beiden vorher zugewiesenen Pins auf Tristate (Config Scl/Sda erzeugt keinen Code) - Software

"I2start" usw schubsen diverse Bits/Bytes, die entsprechenden Bits (Config Scl/Sda) des entsprechenden Port-Registers werden direkt manipuliert (SBI/CBI). Software.

Die Software-Routinen verwenden 'ne Zeit(vernichtungs)Schleife fürs Timing.
Meiner Meinung nach sollte das Config Twi hier einfach keinen Effekt haben, aber auch nicht stören. Der Rest ist SW-Twi (wo wird das Tempo (für die Zeitschleifen) festgelegt?)
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)