- 12V Akku mit 280 Ah bauen         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 14

Thema: ATMega2560 und I2C... geht nicht?

  1. #1
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    42
    Beiträge
    2.009

    ATMega2560 und I2C... geht nicht?

    Anzeige

    Praxistest und DIY Projekte
    Hiho.

    Mal wieder ein Problem.
    Ich hab mir mal ein (preislich gesehen) billiges 40x4-LCD (DisplayTech 404B Series) besorgt. Um dieses universell und ohne viel Verkabelungsaufwand verwenden zu können, hab ich auf eine kleine Zusatzplatine nen ATMega8 draufgepackt, der sich wie ein I2C-Slave verhält, die empfangenen Daten umsetzt und auf dem Display darstellt. Mit nem RS232-I2C-Adapter klappt die Ansteuerung auch problemlos.

    Nun wollte ich das Teilchen an nem ATMega2560 per I2C ansprechen: Es passiert garnichts. Häng ich statt dem Display das RNKeyLCD hin, rührt sich ebenfalls nix. Mit LED-Überwachung zeigt sich, dass beide Leitungen (SCL/SDA) ständig High sind. Lass ich in dem Code unten den "I2CINIT" weg, so ist SDA = Hi, SCL = Lo.

    Verbindungstechnisch hängt die ganze Sache an nem Flachbandkabel mit 3 Steckern; Die Geräte werden alle auch über den Bus mit Strom versorgt.
    Stecker 1: Stromversorgung für Bus + 10k-Pullups für SDA/SCL; Zuschaltbarer RS232-I2C-Adapter.
    Stecker 2: ATMega2560 (Keine Pullups)
    Stecker 3: RNKeyLCD oder 404B (bei letzterem keine Pullups)

    Hier mal der bisherige Code:
    Die Sub ist noch ein überbleibsel und wird später noch "wegoptimiert".
    In der Mainloop soll nur Testweise der Buchstabe X bzw. Y mit 2 verschiedenen Möglichkeiten gesendet werden.

    Code:
    ' Wait for I2C-LCD to be ready
    Wait 2
    
    $lib "i2c.lbx"
    $lib "i2c_twi.lbx"
    
    '-------------------------------------------------------------------------------
    ' Declarations - SUBs
    '-------------------------------------------------------------------------------
      Declare SUB I2CLCD_Send
    
    
    '-------------------------------------------------------------------------------
    ' Declarations - Ports & Pins
    '-------------------------------------------------------------------------------
      CONFIG PIND.0 = OUTPUT      'SCL
      CONFIG PIND.1 = OUTPUT      'SDA
      CONFIG PIND.5 = OUTPUT : LED ALIAS PORTD.5       'Onboard-LED
    
    
    '-------------------------------------------------------------------------------
    ' Declarations - Constants
    '-------------------------------------------------------------------------------
      CONST Timer1Preload = 100
      CONST SID_RNKeyLCD = &H40   ' RNKeyLCD
      CONST SID_I2CLCD = &H42     ' 404B-Series
      CONST SID_Nokia6100 = &H44  ' Nokia 6100 Color LCD
      CONST SID_ServoBoard = &H46 ' MicroServo-Board
      CONST SID_GeneralCall = &H00       ' General Call
    
    
    '-------------------------------------------------------------------------------
    ' Declarations - Variables
    '-------------------------------------------------------------------------------
    
      'Counting Variables
      DIM i as Byte
      DIM i2 as Byte
    
      'Temporary Variables
      DIM tmpByte as Byte
      DIM tmpString as String * 1
    
      'LCD Text
      DIM LCDString(4) AS String * 40
      DIM LCDStringOld(4) AS String * 40
    
    
    '-------------------------------------------------------------------------------
    ' Configs
    '-------------------------------------------------------------------------------
      CONFIG SCL = PORTD.0
      CONFIG SDA = PORTD.1
      CONFIG TIMER1 = TIMER , Prescale = 1024
      Config Twi = 100000         '100 kHz Bus Frequency
    
    
    '-------------------------------------------------------------------------------
    ' Initialisations
    '-------------------------------------------------------------------------------
      I2CINIT
      TIMER1 = Timer1Preload
      On Timer1 ISR_Timer1
    
      ENABLE Timer1
      ENABLE Interrupts
    
    
    
    
    '*******************************************************************************
    ' MAIN LOOP START
    '*******************************************************************************
    DO
    
    I2cstart
    I2cwbyte SID_RNKeyLCD
    I2cwbyte 88                   'Send "X"
    I2cstop
    
    I2CSend SID_RNKeyLCD , 89     'Send "Y"
    
    Toggle LED
    WAITms 500
    
    LOOP
    END
    '*******************************************************************************
    ' MAIN LOOP END
    '*******************************************************************************
    
    
    
    '-------------------------------------------------------------------------------
    ' SUBs
    '-------------------------------------------------------------------------------
    SUB I2CLCD_Send
      For i = 1 to 4
        If LCDString(i) <> LCDStringOld(i) Then
          tmpByte = LEN(LCDString(i))       ' Get length of String
          tmpByte = 40 - tmpByte  ' Chars Needed to 40
          if tmpByte > 0 Then LCDString(i) = LCDString(i) + SPACE(tmpByte)
          I2CStart                'Set Cursor to Line i
          I2CWByte SID_I2CLCD
          I2CWByte 027            'Send System-Command
          I2CWByte 079            'Set Cursor
          I2CWByte 001            'Column 1
          I2CWByte i              'Line i
          I2CStop
          I2CStart                'Transfer selected Line
          I2CWByte SID_I2CLCD
          I2CWByte 001            'Send Text-Command
          I2CWByte 040            'Length: 40 Bytes
          For i2 = 1 to 40        'Send Text-Bytes
            Toggle LED
            tmpString = mid(LCDString(i) , i2 , 1)
            tmpByte = ASC(tmpString)
            I2CWByte tmpByte
          Next
          I2cstop
          LCDStringOld(i) = LCDString(i)
        End If
      Next i
    
    END SUB
    
    
    '-------------------------------------------------------------------------------
    ' Jump Labels / ISR
    '-------------------------------------------------------------------------------
    ISR_Timer1:
      Timer1 = Timer1Preload
      Return

    Hab ich mit der Ansteuerung per I2C was übersehen?
    Muss jedes Gerät selbst nochmal Pullups haben oder reichen die beiden bei der Versorgung?


    MfG
    S.C

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    22.05.2005
    Ort
    12°29´ O, 48°38´ N
    Beiträge
    2.731
    Hallo,

    probier mal die Testprogramme, die ich im Wiki unter "Bascom-I2c-Master" gebaut habe. Aber für eins entscheiden, nicht Software und Hardware-TWI mischen, so wie in deinem Beispiel, immer nur eine lib einbinden !

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    42
    Beiträge
    2.009
    Also bei den Testprogrammen rührt sich leider auch nichts.

    Ich hab dann mal aus dem TWI-Multimasterbeispiel den Code verwendet und hab mittlerweile rausgefunden, dass bei diesem Code TWINT nicht gesetzt wird...
    Jetzt halt die Frage: Warum wird TWINT nicht gesetzt?
    Im Beispiel ist das letzte Bit (TWIE, Interrupt Enable) immer 0; muss dieses aber nicht 1 sein, damit TWINT (Interrupt) überhaupt gesetzt werden kann?


    Ausschnitt:
    Code:
    Sub Twi_send_byte(byval slave As Byte , byval Zeichen As Byte)
      Print #4 , "Sub Started"
        Error = 0                 ' Fehler zurücksetzen
    
        ' Startbedingung
        Twcr = &B10100100         ' TWINT
      Print #4 , "Set Start Cond." ; hex(TWCR)
        ' warten bis TWINT gesetzt ist
        Gosub Twi_wait_int
      Print #4 , "TWINT OK"
    
        ' wenn Zugriff auf den Bus erlaubt, Slaveadresse ausgeben
        If Twi_status = &H08 Or Twi_status = &H10 Then
      Print #4 , "Bus Access"
            Twdr = Slave And &HFE ' slave adresse + Write
            Twcr = &B10000100     ' TWINT löschen, Byte senden
    
            ' warten bis TWINT gesetzt ist
            Gosub Twi_wait_int
    
            ' Slave hat sich gemeldet
            If Twi_status = &H18 Or Twi_status = &H20 Then
      Print #4 , "Slave OK"
                Twdr = Zeichen    ' Daten
                Twcr = &B10000100 ' TWINT löschen, Byte senden
    
                ' warten bis TWINT gesetzt ist
                Gosub Twi_wait_int
    
                ' Zeichen wurden gesendet
                If Twi_status = &H28 Or Twi_status = &H30 Then
        Print #4 , "Char Sent"
                    Error = 0     ' kein Fehler
                Else
                    Error = Twi_status       ' Fehler
                End If
    
            Else
                ' kein slave
                Error = Twi_status       ' Fehler
      Print #4 , "Error: " ; Hex(Error)
            End If
            ' STOPbedingung kommt hier immer im Ablauf, egal welcher Status
            Twcr = &B10010100     ' TWINT löschen, STOP senden
            ' nach einem STOP wird TWINT nicht mehr gesetzt,
            ' man darf/kann also nicht darauf warten !
        Else
            ' Bus belegt, wird er wieder freigegeben
            Twcr = &B10000100     ' TWINT löschen, Bus freigeben
            Error = Twi_status    ' Fehler
        End If
    End Sub
    
    Twi_wait_int:
        Do
            Twi_control = Twcr And &H80
        waitms 500
        Print #4 , "Wait... TWCR: " ; HEX(TWCR)
        Loop Until Twi_control = &H80
        Twi_status = Twsr And &HF8       ' status
        Print #4 , "ErrStat:" ; Hex(twi_status)
    Return

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    22.05.2005
    Ort
    12°29´ O, 48°38´ N
    Beiträge
    2.731
    Hallo,
    TWIE ist nur da, damit die ISR aufgerufen wird, darin muss die nächste TWI-Aktion ausgeführt werden.
    Wenn man das nicht benutzt, muss man das Flag TWINT pollen, wenn es gesetzt ist, TWSR auslesen und darauf reagieren, das wird in den meisten Beispielen auch so gemacht.
    Deswegen gibts auch die Funktion TWI-wait-int, weil das bei jedem Schritt gleich ist.
    Ich würde das waitms 500 da raus machen, da schläft ja jeder Slave ein
    Die ganzen Prints zögern auch unnötig raus.

    Die Beispiele aus der Wiki-Seite sollten funktionieren, ausser es gäbe einen Bug beim 2560 dazu.

    Welche Bascom-Version ?

    Hast Du die reine I2C-Softwarelösung auch probiert ? Die sollte doch immer funktionieren, ausser das Problem liegt ausserhalb des AVR.

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    42
    Beiträge
    2.009
    Die 500ms und die Prints waren nur zu Diagnosezwecken drin, da ich rausfinden wollte, wo genau das Programm stehen bleibt.

    Es scheint aber tatsächlich ein Bug im Zusammenhang mit dem 2560er zu sein. Hardwaremässig sind die Pins ok, da ich sie als Output definiert auf 5V/0V schalten kann. Ich hab das Programm annähernd 1:1 (ohne Print #4 etc) auf nen ATMega32 übertragen und da läufts ohne Probleme.
    Bascom-Version: 1.11.8.9

    Ok, könnte ja im Zielprojekt auch den 32er verwenden, nur werd ich da in absehbarer Zeit an die Grenzen des Programmspeichers kommen...

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    22.05.2005
    Ort
    12°29´ O, 48°38´ N
    Beiträge
    2.731
    Zum auffinden des Fehlers könntest Du noch ein
    Code:
    Print  hex(TWSR)
    nach jedem I2C-Befehl einbauen, um zu sehen was der letzte Befehl ergeben hat.
    Dann kannst Du die Werte mit dem vegleichen, wenns auf einem M32 läuft.

    Mit Bug meinte ich evtl. einen in Bascom, wenn man sich aber das in ASM anschaut was dabei rauskommt (Das TWI-Master-Beispiel aus dem Wiki), scheint es soweit in Ordnung zu sein
    Da ich keinen M2560 da habe, kann ich das leider nicht näher nachprüfen.

    Hast Du schon die Pegel der beiden Leitungen gemessen, ob sich da was rührt, bzw. ob die High sind wenn sie High sein sollen usw. ?
    Oder ob sich das beim I2C-Start schon aufhängt.

    Wie weit kommt Deine Debugausgabe im Programm ?

    Nimm beim Master die Bascom-Befehle, da kommt man nicht so leicht durcheinander

  7. #7
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    42
    Beiträge
    2.009
    Also beim Test mit dem M32 geht jede beliebige Pin-Kombination (Config SCL, Config SDA...), beim 2560 geht garnix davon. Verschiedenste Pins durchprobiert; also scheidet ein Hardwaredefekt wohl auch aus.
    (Hardware OK, Software geht auch... was bleibt dann noch?...)

    Wenn ich mit der Befehlsfolge

    I2CStart
    I2CwByte &H40
    I2CwByte 81
    I2Cstop

    ein Zeichen senden will, bleibt der 2560 irgendwo beim ersten Write Byte stehen. Also I2CStart wird ausgeführt, I2CwByte &H40 nicht mehr bzw. nicht vollständig. Wenn direkt I2CSend verwendet wird, stoppt er dort genauso.

    Beim Durchsuchen nach möglichen Fehlerquellen hab ich noch etwas gefunden. In der M2560def.dat ist ganz unten der Abschnitt
    Code:
    [I2CSLAVE]
    POSSIBLE=YES    ; software slave mode possible but TWI mode also
    PORT=D,7,0     ; PORTD , SCL D.7(T0) , SDA D.0(INT0)
    Der hat aber wohl nur was mit dem Slave zu tun. Dort werden nämlich die I2C-Pins "falsch" angegeben, da SDA normal D.1 ist und SCL D.0.
    Aber kanns trotzdem sein, dass dieser Abschnitt das ganze stört?

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    22.05.2005
    Ort
    12°29´ O, 48°38´ N
    Beiträge
    2.731
    Diese Werte in der .dat sind nur da falls man das im Programm nicht angibt, deshalb sollte es immer angegeben werden !

    Wenn du das Beipsiel von der Wiki-Seite unter "Software-I2C" verwendest, sollte es doch laufen, denn alle Ports liegen IO-mässig im unteren Bereich,
    also ohne TWI-lib probieren !

    Hast du ein Oszi, um zu sehen was sich auf dem Bus tut ?

  9. #9
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    42
    Beiträge
    2.009
    Ich hab sowohl Hardware als auch Software-I2C verwendet; geht beim M32 alles problemlos, mit Software auch auf beliebigen Pins; auch ohne die lib.
    Oszi wurde gerade mal verwendet:
    M32: Datenverkehr sichtbar (ja auch logisch, wenns so geht).
    M2560: SDA und SCL sind ständig auf High/5V; unabhängig davon ob über Software oder Hardware-I2C und unabhängig von der Auswahl der Pins bei Software-I2C; So als würden die direkt an VCC hängen.
    Wird der jeweilige Pin als normaler Output definiert und mit
    Do: Toggle Pinx.y: Waitms 1: Loop
    gefüttert, dann ist eine saubere Rechteckspannung zu erkennen.


    EDIT: 15:41 Uhr...
    Hab soeben SCL auf A.0 und SDA auf A.1 gesetzt und da gehts plötzlich!... Nur warum nur auf diesen beiden und sonst nirgendwo?...

  10. #10
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    22.05.2005
    Ort
    12°29´ O, 48°38´ N
    Beiträge
    2.731
    Ab jetzt muss dann jemand anders beim weiterforschen helfen, da ich (noch) kein M2560 im Zugriff habe !

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress