Aus RN-Wissen.de
Wechseln zu: Navigation, Suche


In diesem Artikel folgen verschiedene Programmbeispiele, um einen AVR mit Bascom zu einem I2C-Master zu schlumpfen.

In allen Beispielen wird einem PCF8574 jeweils der Wert &HAA nach einer Pause &H55 gesendet, was als Blinken, evtl. auch als Lauflicht zu erkennen sein kann, falls LEDs an dessen Ports angeschlossen sind.

Beispielumgebung mit PCF8574


Software I2C

Die Softwareversion der I2C-Implementierung kann auf allen AVR programmiert werden, man kann sich die Ports auf denen Data (SDA) und Clock (SCL) angeschlossen werden selbst aussuchen.

Standardmäßig wird von Bascom die Software-Version verwendet um auf den I2C-Bus zuzugreifen, d.H. die einzelnen Bits der zu übertragenden Daten werden per Software auf High- oder Low-Pegel an den Ports ausgegeben. Der AVR kann in dieser Zeit keine anderen Aufgaben erledigen.

Bei dieser Art I2C zu implementieren wird eine aktuelle Aktivität auf dem Bus nicht beachtet, dies kann zu Problemen führen falls mehr als ein Master am Bus hängt. Siehe Links unter "Siehe auch".


$regfile = "M32def.dat"                           ' the used chip 
$crystal = 16000000                               ' frequency used 
$baud = 9600

Config Scl = Portb.0                              ' Ports fuer IIC-Bus, nicht Standard ! 
Config Sda = Portb.1
' Config I2cdelay = 10                  ' je höher der Wert umso langsamer der Bus 

I2cinit

Const Pcf_write = &H40                            ' Slaveadresse 
Const Pcf_read = &H41

' Startausgabe 
Print
Print "I2C-Soft Demo mit PCF 8574"
Print

Do
    I2cstart
    I2cwbyte Pcf_write
    I2cwbyte &HAA
    I2cstop

    Print Err                                     ' Err = 0 -> kein Fehler ! 

    Waitms 500

    I2cstart
    I2cwbyte Pcf_write
    I2cwbyte &H55
    I2cstop

    Print Err                                     ' Err = 0 -> kein Fehler ! 

    Waitms 500

Loop

End

Mit ERR kann nach jedem gesendeten Byte abgefragt werden, ob es mit ACK quittiert wurde (=0), oder nicht (=1).

Falls mehr als nur ein Byte an einen Slave gesendet werden sollte, und nach dem letzten Byte ERR=1 ist, sollte anschließend ein I2Cstop folgen, da der Slave kein weiteres Byte haben will !

Hardware TWI

AVR Controller, die I2C hardwaremäßig Unterstützen, haben das TWI-Modul, die Ports für Data und Clock sind dabei vorgegeben. TWI ist bei den meisten ATMegas vorhanden, z.B. dem ATMega32.

Damit Bascom das TWI-Modul verwendet muss die i2c_twi.lib (bzw. .lbx, bei der Bascom-Demo) eingebunden werden, ansonsten ist, bis auf die Initialisierung, alles genauso wie bei Software-I2C. Bei Verwendung der Bascom-I2C-Befehle macht es Performancemäßig keinen großen Unterschied, ob man Software-I2C oder TWI verwendet, denn bei beiden Versionen wird solange darauf gewartet, bis das Byte über den Bus gesendet ist, und ein ACK oder NACK empfangen ist.

Der Vorteil von TWI ist aber, das es in Multimasterumgebungen besser verträglich ist (z.B. I2CStart). Gibt es nur einen Master, kann man sich für eine der beiden Versionen entscheiden.

Der Master bestimmt wie schnell die Daten auf dem Bus übertragen werden (Ausnahme: Clock_Stretching ). Dafür ist hier die Zeile mit Config TWI zuständig, Bascom berechnet aus der angegebenen Taktfrequenz den richtigen Wert für TWBR um an den gewünschten I2C-Takt zu kommen.

$regfile = "M32def.dat"                           ' the used chip 
$crystal = 16000000                               ' frequency used 
$baud = 9600

$lib "i2c_twi.lbx"                                ' Für Hardware TWI 

Config Twi = 400000                               ' Init TWBR und TWSR 

' TWI gleich einschalten, das macht Bascom ansonsten erst beim I2CStart ! 
TWCR = &B00000100                                 ' nur TWEN setzen 

Const Pcf_write = &H40                            ' Slaveadresse 
Const Pcf_read = &H41

' Startausgabe 
Print
Print "I2C-TWI Demo mit PCF 8574"
Print

Do
    I2cstart
    I2cwbyte Pcf_write
    I2cwbyte &HAA
    I2cstop

    Print Err                                     ' Err = 0 -> kein Fehler ! 

    Waitms 500

    I2cstart
    I2cwbyte Pcf_write
    I2cwbyte &H55
    I2cstop

    Print Err                                     ' Err = 0 -> kein Fehler ! 

    Waitms 500

Loop

End

Mit ERR kann nach jedem gesendeten Byte abgefragt werden, ob es mit ACK quittiert wurde (=0), oder nicht (=1).

Mit der TWI-Lib wird zwar die Hardware benutzt um die Bytes auf den I2C-Bus auszugeben bzw. von dort einzulesen, es wird aber kein Status von TWSR abgefragt, ob die erwartete Reaktion eingetreten ist !

Unter Zuhilfenahme des Datenblattes könnte eine Highend-Version so aussehen:

$regfile = "M32def.dat"                           ' the used chip 
$crystal = 16000000                               ' frequency used 
$baud = 9600

$lib "i2c_twi.lbx"                                ' Für Hardware TWI 

Config Twi = 400000                               ' Init TWBR und TWSR 

' TWI gleich einschalten, das macht Bascom ansonsten erst beim I2CStart ! 
TWCR = &B00000100                                 ' nur TWEN setzen 

Const Pcf_write = &H40                            ' Slaveadresse 
Const Pcf_read = &H41

' Startausgabe 
Print
Print "I2C-TWI High-Demo mit PCF 8574"
Print

Do
    I2cstart
    If TWSR = &H08 Then                           ' Start wurde abgesetzt 
        I2cwbyte Pcf_write                        ' Slaveadresse ausgeben 

        If TWSR = &H18 Then                       ' Slave hat sich gemeldet 
            I2cwbyte &HAA                         ' Datenbyte ausgeben 

            If TWSR <> &H28 Then                  ' Byte erfolgreich übertragen 
                Print "Byte mit NACK quittiert !"
            End If
        Else
            Print "kein Slave !"
        End If
    Else
        Print "Fehler bei Start"
    End If

    ' Immer Stop, damit die Buspegel wieder stimmen 
    I2cstop

    Print "E " ; Err                              ' Err = 0 -> kein Fehler ! 

    Waitms 1500

    I2cstart

    If TWSR = &H08 Then                           ' Start wurde abgesetzt 
        I2cwbyte Pcf_write                        ' Slaveadresse ausgeben 

        If TWSR = &H18 Then                       ' Slave hat sich gemeldet 
            I2cwbyte &H55                         ' Datenbyte ausgeben 

            If TWSR <> &H28 Then                  ' Byte erfolgreich übertragen 
                Print "Byte mit NACK quittiert !"
            End If
        Else
            Print "kein Slave !"
        End If
    Else
        Print "Fehler bei Start"
    End If

    ' Immer Stop, damit die Buspegel wieder stimmen 
    I2cstop

    Print "E " ; Err                              ' Err = 0 -> kein Fehler ! 

    Waitms 1500

Loop

End

Die Printausgaben im Else-Teil sind natürlich nur in der Demo nützlich, in der Praxis entweder den Else-Teil ganz weglassen, oder entsprechende Variablen setzen um den Fehler später zu bearbeiten.

Eine einfachere Version einen Fehler frühzeitig zu erkennen, ist statt TWSR nur ERR auf 0 zu prüfen.


Hardware USI

Kleinere AVR Controller, die zwar kein TWI-Modul haben, aber I2C hardwaremäßig Unterstützen, haben das USI-Modul, die Ports für Data und Clock sind dabei vorgegeben. USI ist bei den meisten ATTinys und einigen ATMegas vorhanden, z.B. dem ATTiny2313.

Das USI-Modul kann evtl. als eine Art von TWI-Light angesehen werden, denn es ist nicht so komfortabel wie TWI, es muss intern noch viel in Software erledigt werden, weshalb es Performancemäßig auch keinen großen unterschied macht, ob man Software-I2C oder USI beim Master verwendet.

Am einfachsten benutzt man die Lib, die unter Weblinks aufgeführt ist, denn dann kann man die von Bascom vorgegebenen Befehle benutzen.

$regfile = "attiny2313.dat"                       ' the used chip 
$crystal = 16000000                               ' frequency used 
$baud = 9600

$lib "i2c_usi.lbx"                                ' Für Hardware USI-I2C 

Config Scl = Portb.7                              ' Ports fuer IIC-Bus 
Config Sda = Portb.5
' Config I2cdelay = 5                  ' je höher der Wert umso langsamer der Bus 

I2cinit

Const Pcf_write = &H40                            ' Slaveadresse 
Const Pcf_read = &H41
 
' Startausgabe 
Print
Print "I2C-USI Demo mit PCF 8574"
Print

Do
    I2cstart
    I2cwbyte Pcf_write
    I2cwbyte &HAA
    I2cstop

    Print Err                                     ' Err = 0 -> kein Fehler ! 

    Waitms 500

    I2cstart
    I2cwbyte Pcf_write
    I2cwbyte &H55
    I2cstop

    Print Err                                     ' Err = 0 -> kein Fehler ! 

    Waitms 500

Loop

End

Mit ERR kann nach jedem gesendeten Byte abgefragt werden, ob es mit ACK quittiert wurde (=0), oder nicht (=1).

Nach I2Cstart (auch I2CStop) kann ERR kontrolliert werden, ob das Start (bzw. Stop) auch auf den Bus abgesetzt werden konnte.


Siehe auch


WebLinks

  • [1] - Forum-Artikel, in dem eine Bascom-Lib vorgestellt wird, um die Bascom-I2C-Befehle mit dem USI-Modul als Master zu verwenden.


--Linux 80 02:08, 28. Okt 2007 (CEST)