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.
Inhaltsverzeichnis
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 = TWEN 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
- Avr - Infos zu AVR allgemein
- I2C - Details zu I2C
- TWI - Two-wire Serial Interface
- SPI - Serial Peripheral Interface
- TWI Praxis - Bascom-Beispiele für Hardware TWI
- TWI Praxis Multimaster - Bascom-Beispiele für Hardware TWI
- Bascom und USI-Kommunikation - Bascom-Beispiele für Hardware USI
- Bascom Soft-I2c Library - weitere Tipps zu I2C mit Bascom
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)