- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 7 von 7

Thema: I2C und Word

  1. #1

    I2C und Word

    Anzeige

    Praxistest und DIY Projekte
    Ich kämpfe nun seit drei Tagen mit dem Lesen und Schreiben auf einen 24c64.

    Bin nun soweit das ich ein Byte geziehlt schreiben und lesen kann, allerdings würde ich viel lieber ein Word geziehlt schreiben und lesen.

    Mit den Prog kann ich auf Tastendruck ein Wert (Word) an den 24C64 senden,
    allerdings beim lesen geht es nur mit Werten bis 255 (also Byte)

    Was muss ich noch ändern?

    Code:
    $regfile = "m8def.dat"
    $crystal = 8000000
    
    
    Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portb.5 , Rs = Portb.4
    Config Lcd = 16 * 2
    Cursor Off
    
    
    Config Scl = Portc.5                                        'PIN für I2C Bus
    Config Sda = Portc.4
    Config Pinc.3 = Input
    Config Pinc.1 = Input
    Config Portc.2 = Output
    Config Portc.0 = Output
    
    Portc.3 = 1                                                 'Pullup ein
    Portc.1 = 1                                                 'Pullup aus
    
    Dim X As Word
    Dim A As Byte
    Dim B As Byte
    Dim Lesen As Word
    Cls
    
    Main:
    
    Do
    
        X = X + 5
        A = 1
        B = 1
        If Pinc.3 = 0 Then
        Portc.2 = 1
        Gosub Eschreiben
        End If
    
        If Pinc.3 = 1 Then
        Portc.2 = 0
        End If
    
        If Pinc.1 = 0 Then
        Portc.0 = 1
        Gosub Elesen
        End If
    
        If Pinc.1 = 1 Then
        Portc.0 = 0
        End If
    
    Loop
    
    Eschreiben:                                                 '---- schreibe in EEprom ----
    
        I2cstart                                                'Start I2C
        I2cwbyte &HA0                                           'Sende Slave Adresse
        I2cwbyte A                                              'Sende Speicheradresse High
        I2cwbyte B                                              'Sende Speicheradresse LOw
        I2cwbyte X                                              'Sende Wert
        I2cstop                                                 'Stop I2C
        Waitms 10                                               'warte 10ms
    
        Locate 1 , 1
        Lcd "ins EE= " ; X ; "  "                               ' Ausgabe der geschriebenen Werte am LCD
        Waitms 500
    
        Return
    
    Elesen:                                                     '--- lesen vom EEprom ----
    
        I2cstart                                                'Start I2C
        I2cwbyte &HA0                                           'sende Slave Adresse
        I2cwbyte A                                              'sende Speicheradresse High
        I2cwbyte B                                              'sende Speicheradresse Low
    
        I2cstart                                                'Start I2C
        I2cwbyte &HA1                                           'sende Slave Adresse +1 für Lesen
        I2crbyte Lesen , Nack                                   'lese Adresse vom EEprom
        I2cstop                                                 'Stop I2C                                                 'Stop I2C
    
        Locate 2 , 1
        Lcd "Lese EE= " ; Lesen ; "  "                          'Ausgabe der EEprom Werte
        Waitms 500
    
        Return
    
    End

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

    ein Word sind 2 Byte, Du musst diese beiden Bytes hintereinander senden bzw. lesen.
    zB mit High(Word) und Low(word) bekommst Du die einzelnen Bytes aus dem Word,
    mit makeint sollte man eins aus 2 Bytes bauen können (nach dem lesen).

    Siehe Hilfe zu Bascom zu den hier vorgeschlagenen Befehlen.

  3. #3
    Ja die Bascomhilfe und das Board habe ich schon rauf un runter studiert.

    Aber irgend wie habe ich da eine Gedanken blockade.

    Wenn ich den Wert 125 abspeichern will dann mach ich das so.

    I2cstart 'Start I2C
    I2cwbyte &HA0 'Sende Slave Adresse
    I2cwbyte 1 'Sende Speicheradresse High
    I2cwbyte 1 'Sende Speicheradresse LOw
    I2cwbyte 125 'Sende Wert
    I2cstop 'Stop I2C

    Wenn ich nun den Wert 12534 abspeichern möchte, wie mache ich das ?

    Oder teilt er das dann Automatisch in die High und Low Adresse auf?

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    22.05.2005
    Ort
    12°29´ O, 48°38´ N
    Beiträge
    2.731
    Nein, dafür gibts die Befehle High und Low, damit sendet man die zwei Bytes hintereinander ans EEprom.
    Beim lesen liest man einfach 2 Bytes ein, und setzt die mit Makeint in der richtigen Reihenfolge wieder zusammen, und kommt auf den alten Wert. Sollte ein anderer Wert rauskommen, stimmt entweder die Reihenfolge bei Makeint nicht (einfach mal bei de Werte tauschen), oder es wurde von einer falschen Adrese gelesen.

    Du musst die Bascom-Hilfe nicht rauf- und runterlesen, in diesem Fall hier erstmal nur diese drei Befehle von oben nach unten
    Bei Makeint steht, wie man high und low übergibt, damit wieder der gewünschte Wert rauskommt.

    zB so:
    Code:
    I2cstart            'Start I2C
    I2cwbyte &HA0       'Sende Slave Adresse
    I2cwbyte 1          'Sende Speicheradresse High
    I2cwbyte 1          'Sende Speicheradresse LOw
    I2cwbyte WertLow    ' oder andersrum völlig egal 
    I2cwbyte WertHigh   ' muss nur beim lesen in der gleichen Reihenfolge zusammengesetzt werden !
    I2cstop            'Stop I2C
    vom Prinzip her so wie beim senden der Speicheradresse.

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    31.07.2007
    Beiträge
    15
    Ich erlaube mir jetzt mal, diesen Thread zu benutzen, geht aber genau um das gleiche Thema,
    nämlich eine Word-Variable über I2C zu übertragen, nur in die andere Richtung.

    Auf einem ATMEGA8 ist ein Slave implementiert, ein ATMEGA16 ist der Master,
    der vom Slave einen (später mehrere) Werte auslesen soll.
    Der Code ist aus dem Wiki-Artikel "TWI Praxis" übernommen und dann zugegebener maßen etwas zusammengepfuscht.

    Hier der Code für den Slave:
    Code:
    ' TWI-slave test
    $regfile = "m8def.dat"                                      ' the used chip
    $crystal = 8000000                                          ' frequency used
    
    Dim Twi_control As Byte                                     ' Controlregister lokale kopie
    Dim Twi_status As Byte
    Dim Twi_data As Byte
    
    Dim Count As Byte
    
    Dim Wert As Word
    Wert = &H1234
    
    Dim Temp As Byte
    Dim Count2 As Byte                                       
    
    Declare Sub Twi_init_slave
    
    ' Werte zurcksetzen
    Count = 7
    Count2 = 23
    Twi_data = 0
    Call Twi_init_slave                                         ' TWI aktivieren
    
    
    ' Hauptschleife
    Do
       
    
    
        ' schauen ob TWINT gesetzt ist
        Twi_control = Twcr And &H80                             ' Bit7 von Controlregister
    
        If Twi_control = &H80 Then
            Twi_status = Twsr And &HF8                          ' Status
    
            ' will der Master ein Byte haben
            If Twi_status = &HA8 Or Twi_status = &HB8 Then
                'Temp = High(wert)
                'Twdr = Temp
                'Incr Count
                Twdr = Count                                    ' testwert +1
            End If
    
            ' TWINT muss immer gelscht werden, damit es auf dem Bus weiter geht
            Twcr = &B11000100
            Twi_status = Twsr And &HF8
            If Twi_status = &HA8 Or Twi_status = &HB8 Then
               'Temp = Low(wert)
                'Twdr = Temp
                'Incr Count
                Twdr = Count2                                
            End If
    
            ' TWINT muss immer gelscht werden, damit es auf dem Bus weiter geht
            Twcr = &B11000100                                   ' TWINT löschen, mit ACK
        End If
    
    Loop
    
    End
    
    
    ' Unterprogramme
    
    
    ' TWI als slave aktivieren
    Sub Twi_init_slave
        Twsr = 0                                                ' status und Prescaler auf 0
        Twdr = &HFF                                             ' default
        Twar = &H40                                             ' Slaveadresse setzen
        Twcr = &B01000100                                       ' TWI aktivieren, ACK einschalten
    
    End Sub
    und der des masters:
    Code:
    ' TWI Testprogramm
    ' mit Slave @ &H40
    
    
    $regfile = "M16def.dat"                                     ' the used chip
    $crystal = 16000000                                         ' frequency used
    $baud = 9600                                                ' baud rate
    
    Declare Function Twi_read_byte(byval Slave As Byte) As Word
    
    Dim Twi_control As Byte                                     ' Controlregister lokale kopie
    Dim Twi_status As Byte
    Dim Twi_data As Byte
    Dim Twi_read1 As Byte
    Dim Twi_read2 As Byte
    
    Dim B As Byte                                               ' Zeichen von UART
    Dim X As Byte                                               ' Zeichen von TWI
    Dim Error As Byte                                           ' Fehlermerker
    
    Dim Msg As Word
    
    ' TWI Init
    Twcr = &B00000100                                           ' erstmal nur TWI aktivieren
    Twsr = 0                                                    ' Status und Prescaler Register
    Twbr = 72                                                   ' Bit Rate Register, 100kHz
    
    ' Startausgabe
    Print "TWI Master Receiver"
    
    ' Hauptschleife
    Do
        
        ' warten bis etwas ber UART kommt (egal welcher Wert, wird nur als Startbutton genutzt)
        Input B
    
        ' ein Byte vom Slave holen
        Msg = Twi_read_byte(&H40)
    
        ' Ausgabe, damit wir sehen was geschehen ist
        Print "LSB: " ; Twi_read2
        Print "MSB: " ; Twi_read1
        Print Msg ;
        Print " Error : " ;
        Print Hex(error)                                        ' error status Ausgeben
    
    Loop
    
    End
    
    ' Unterprogramme
    
    ' TWI read_byte
    ' holt ein Byte und schliesst die bertragung ab
    Function Twi_read_byte(slave As Byte) As Word
        Error = 0                                               ' Fehler zurücksetzen
    
        Twi_read_byte = 0                                       ' Wert vorbelegen
    
        ' Startbedingung
        Twcr = &B10100100                                       ' TWINT
    
        ' warten bis TWINT gesetzt ist
        Gosub Twi_wait_int
    
        ' wenn Zugriff auf den Bus erlaubt, Slaveadresse ausgeben
        If Twi_status = &H08 Or Twi_status = &H10 Then
            Twdr = Slave Or &H01                                ' slave adresse + Read
            Twcr = &B10000100                                   ' TWINT lschen, Byte senden
    
            ' warten bis TWINT gesetzt ist
            Gosub Twi_wait_int
    
            ' Slave hat sich gemeldet
            If Twi_status = &H40 Then
                Twcr = &B11000100                               ' TWINT lschen, Byte senden
                          ' ein ACK (TWEA = 1) 
                ' warten bis TWINT gesetzt ist
                Gosub Twi_wait_int
    
                ' ein Byte wurde empfangen
                If Twi_status = &H58 Or Twi_status = &H50 Then
                    Twi_read1 = Twdr                            ' Daten lesen
                    Error = 0                                   ' kein Fehler
                Else
                    Error = Twi_status                          ' Fehler
                End If
    
    
                'zweites lesen
                Twcr = &B10000100                               ' TWINT lschen, Byte senden
                              ' kein ACK (TWEA = 0) senden, weil wir nur ein Byte lesen wollen
    
                ' warten bis TWINT gesetzt ist
                Gosub Twi_wait_int
    
                ' ein Byte wurde empfangen
                If Twi_status = &H58 Or Twi_status = &H50 Then
                    Twi_read2 = Twdr                            ' Daten lesen
                    Error = 0                                   ' kein Fehler
                Else
                    Error = Twi_status                          ' Fehler
                End If
                Twi_read_byte = Makeint(twi_read2 , Twi_read1)
    
            Else
                ' kein slave
                Error = Twi_status                              ' Fehler
            End If
    
            ' STOPbedingung kommt hier immer im Ablauf, egal welcher Status
            Twcr = &B10010100                                   ' TWINT lschen, 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 lschen, Bus freigeben
            Error = Twi_status                                  ' Fehler
        End If
    
    End Function
    
    ' warten bis TWINT gesetzt ist, status auslesen
    Twi_wait_int:
        Do
            Twi_control = Twcr And &H80
        Loop Until Twi_control = &H80
    
        Twi_status = Twsr And &HF8                              ' status
        ' status nur zu Debugzwecken ausgeben, weil Bus sehr langsam wird !
    '    Print "Err " ; Hex(twi_status)
    Return
    Leider verhält sich das ganze jetzt garnicht so wie es soll,
    in der Variante wie sie jetzt das steht, also das nicht auskommentierte,
    sendet es zwei mal die 7 obwohl das zweite 23 seien sollte.
    Wenn ich die Variante mit einer Variable verwende, die immer erhöht wird,
    treten Sprünge auf wie:
    LSB: 1
    MSB:3
    LSB:5
    MSB:7

    Wenn ich die Word Variable verwende, wie es ja eig. sein soll,
    klappt das auch nicht wie gewollt.

    Ich hab mir jetzt echt schon das Hirn zermartert, aber ich weiß nicht,
    wie ich das hinkriegen soll, bitte helft mir.

    Lukas

  6. #6
    Also ich irgend wie kapier ich das nicht.

    I2cstart 'Start I2C
    I2cwbyte &HA0 'Sende Slave Adresse
    I2cwbyte 1 'Sende Speicheradresse High
    I2cwbyte 1 'Sende Speicheradresse LOw
    I2cwbyte WertLow ' oder andersrum völlig egal
    I2cwbyte WertHigh ' muss nur beim lesen in der gleichen Reihenfolge zusammengesetzt werden !
    I2cstop 'Stop I2C
    Dann versteh ich das so zb.

    I2cstart 'Start I2C
    I2cwbyte &HA0 'Sende Slave Adresse
    I2cwbyte 1 'Sende Speicheradresse High
    I2cwbyte 1 'Sende Speicheradresse LOw
    I2cwbyte 123Low ' oder andersrum völlig egal
    I2cwbyte 123High ' muss nur beim lesen in der gleichen Reihenfolge zusammengesetzt werden !
    I2cstop 'Stop I2C
    Wenn ich das aber so ein tippe, motzt Bascom schon beim übersetzen.


  7. #7
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    06.07.2006
    Alter
    94
    Beiträge
    627
    Hi XT600SM,
    hatte selbes Problem - das Word verschwand im eeprom und ich habs nicht wiedergefunden....
    so geht´s:

    Code:
    $regfile = "m8def.dat"                                      'MEGA8-Deklarationen
    
    $hwstack = 32
    $swstack = 8
    $framesize = 24
    
    
    $crystal = 8000000                                          'intern 8MHz
    $baud = 9600                                                'Baudrate definieren
    '-------------------------------------------------------------------------------
    'Ein / Ausgänge definieren:
    'Ddrb = &B00111100                                           '0=Eingang
    'Ddrc = &B1111111
    Ddrd = &B01100011                                           '0=Eingang
    
    
    'PullUps setzen:
    'Portb = &B00000000                                          '1 = PullUp AKTIV
    'Portc = &B0000000                                           '1 = PullUp AKTIV
    'Portd = &B00000000                                          '1 = PullUp AKTIV
    
    '-------------------------------------------------------------------------------
    'Alias
    Taster1 Alias Pind.2
    Taster2 Alias Pind.3
    Taster3 Alias Pind.4
    Led1 Alias Portd.5
    Led2 Alias Portd.6
    
    
    
    
    '-------------------------------------------------------------------------------
    'Variablen
    
    
    '-------------------------------------------------------------------------------
    'Timer
    'Timer1 = 2x / sec bei 8MHz
    'Config Timer1 = Timer , Prescale = 256                      'Teiler
    'Const Timervorgabe = 49910
    'Enable Timer1
    'Enable Interrupts
    
    '-------------------------------------------------------------------------------
    Dim Wert As Word                                            'eigendlicher Wert
    Dim Wert1 As Byte                                           'Hilfswert1
    Dim Wert2 As Byte                                           'Hilfswert2
    
    
    Dim Lesen As Word                                           'Auslesen
    Dim Lesenlow As Byte                                        'Hilfswert1
    Dim Lesenhigh As Byte                                       'Hilfswert2
    
    Dim Adresse As Word At $160                                 'Die Adresse als Word-Variable
    Dim Low_adresse As Byte At $160 Overlay                     'Zeiger auf das erste Byte
    Dim High_adresse As Byte At $161 Overlay                    'Zeiger auf das zweite Byte
    
    
    
    'SDA und SCL definieren
    Config Sda = Portc.4                                        ' I2C-Port festlegen
    Config Scl = Portc.5                                        ' I2C-Port festlegen
    
    
    Const Ext_eeprom = 162                                      'I2C Geräteadresse ggf. anpassen
    Wert = 64998
    
    
    '-------------------------------------------------------------------------------
    'Für RS232:
    'On Urxc Onrxd                                               'Interrupt-Routine setzen
    'Enable Urxc                                                 'Interrupt URXC einschalten
    Enable Interrupts                                           'Interrupts global zulassen
    
    
    '---------------------------------------------------------------------------------------------------------------
    '---------------------------------------------------------------------------------------------------------------
    Do
    
    If Taster1 = 1 Then
    '----schreiben----
    For Adresse = 250 To 260                                    'Adresse geht über die Byte-Grenze
    Incr Wert                                                   '1 bis Überlauf
    Gosub Eeprom_schreiben
    Print "schreiben ->Adres.=" ; Adresse ; "Wert=" ; Wert ; "  "       'Anzeige vom schreiben
    Waitms 500
    Adresse = Adresse + 1                                       'weil ja immer 2 Bytes abgefragt werden
    Next Adresse
    End If
    
    
    If Taster2 = 1 Then
    '---lesen----
    For Adresse = 250 To 260
    Gosub Eeprom_lesen
    Lesen = Makeint(lesenhigh , Lesenlow)
    Print "lesen <-Adres.=" ; Adresse ; "Wert= " ; Lesen        'Anzeige vom lesen
    Waitms 500
    Adresse = Adresse + 1                                       'weil ja immer 2 Bytes abgefragt werden
    Next Adresse
    End If
    
    
    
    
    
    Loop
    
    
    
    
    
    '------------------------------------------------------
    '- Byte (wert) auf EEprom Adresse (address) speichern -
    '------------------------------------------------------
    Eeprom_schreiben:
    Wert1 = High(wert)
    Print Wert1 ; " W1 "
    Wert2 = Low(wert)
    Print Wert2 ; " W2 "
    
    I2cstart                                                    'Start
    I2cwbyte &HA0                                               'Sende Slavadresse
    I2cwbyte High_adresse                                       'Sende Speicheradresse High
    I2cwbyte Low_adresse                                        'Sende Speicheradresse  LOW
    I2cwbyte Wert2                                              'Sende Wert
    I2cwbyte Wert1                                              'Sende Wert
    I2cstop                                                     'stop
    Waitms 10
    Return
    
    
    
    '-----------------------------------------------------------------
    '---  Byte (wert) von EEprom Adresse (address) lesen           ---
    '-----------------------------------------------------------------
    Eeprom_lesen:
    
    I2cstart                                                    'Start
    I2cwbyte &HA0                                               'Sende Slavadresse +1 für Schreiben
    I2cwbyte High_adresse                                       'Sende Speicheradresse High
    I2cwbyte Low_adresse                                        'Sende Speicheradresse Low
    
    I2cstart                                                    'Start
    I2cwbyte &HA1                                               'Sende Slavadresse +1 für Lesen
    I2crbyte Lesenhigh , Ack                                    'Lese Adresse vom EEprom
    I2crbyte Lesenlow , Nack                                    'Lese Adresse vom EEprom
    I2cstop                                                     'Stop
    Return
    vielleicht hast du ja auch schon eine Lösung gefunden - der Beitrag ist ja schon etwas älter....

Berechtigungen

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

12V Akku bauen