Der Master erzeugt Lesezyklen, übernimmt die Daten und stellt sie dann im Datenregister der Anwendersoftware zur Verfügung.
Hi!
Ich baue gerade einen I2C Bus auf, dank der vielen wirklich guten Tutorials scheint das sehr einfach zu sein. Allerdings habe ich noch nichts gefunden wo ein Master vom Bus liest.
Ich habe mal angefangen mir die wichtigsten Funktionen zu bauen,
aber gerade bei der lese-Funktion bin ich mir doch sehr sehr unsicher...
Würde mich sehr freuen wenn sich jemand das mal ansieht, und mich vll. berichtigt, oder mir vll. ne gute Seite empfielt...
Gruss
Bastian
Code:#include <avr/twi.h> #include <avr/io.h> void i2cStart() { // TWINT = Enables the TWI Interrupt Flag // TWSTA = Writes the TWI Start Condition Bit into the Bus (Master) // TWEN = Enables the TWI Hardware TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); while (!(TWCR & (1<<TWINT))); //wait until the Bus is not ready } void i2cStop() { // TWINT = Enables the TWI Interrupt Flag // TWSTO = Writes the TWI Stop Condition Bit into the Bus (nolonger Master) // TWEN = Enables the TWI Hardware TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); //Send Stop } void i2cSendData(unsigned char address,unsigned char data) { TWDR = address << 1; //load Slave Address + Write in TWDR TWCR = (1<<TWINT)|(1<<TWEN); //clear Bits to start transmission while (! (TWCR & (1<<TWINT))); //wait until the Bus is not ready TWDR = data; //load data in TWDR TWCR = (1<<TWINT)|(1<<TWEN); //clear Bits to start transmission while (! (TWCR & (1<<TWINT))); //wait until the Bus is not ready } //???????????????????????????????????????????? unsigned char i2cReadData(unsigned char address) { TWDR = (address << 1) + 1; //load Slave Address + Read in TWDR TWCR = (1<<TWINT)|(1<<TWEN); //clear Bits to start transmission while (! (TWCR & (1<<TWINT))); //wait until the Bus is not ready TWCR = (1<<TWINT)|(1<<TWEN); //clear Bits to start transmission while (! (TWCR & (1<<TWINT))); //wait until the Bus is not ready return TWDR; //return TWDR }
Der Master erzeugt Lesezyklen, übernimmt die Daten und stellt sie dann im Datenregister der Anwendersoftware zur Verfügung.
hast du schonmal ins Datenblatt des ATMEGA8/16 usw. geschaut, da steht das ganze sehr ausführlich und verständlich drin
Nun gut, werde das wohl so hinbekommen.
Scheitere jetzt nur an einem anderen Problem.
Sobald ich meine Funktion i2cStart() aufrufe
und TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); ausgeführt wurde
läuft das Programm in die Endlosschleife da das TWINT-Bit nicht gesetzt wurde.
Nach der schlauen Literatur bedeutet dies doch das kein "START" gesendet werden konnte, dass also der Bus nicht bereit war.
Dies deutet dann doch auf einen Hardware-Fehler, wenn mein Bus nur einen Master enthält (im "Bus" sind nur der Atmega32 und ein PCF8574).
Grundsetzlich müsste aber doch auch ein "Start" gesendet werden können, wenn gar keine Slaves im Bus existieren, oder?
Denn auch dieses funktioniert nicht.
Ich fürchte an dieser Stelle hilft mir kein Tutorial weiter...
Gruss
Bastian
Hast du Pull-UpWiderstände ordentlich an die Busleitungen geschalten?
Falls du Interrupts freigegeben hast (sei()), existiert für das TWI eine ISR?
Ansonsten schau mal hier: www.mc-project.de unter der Rubrik ICs&Co ist der von dir verwendete Baustein samt Code beschrieben.
ja, ich hab Interrupts freigegeben.
Aber diese sind doch unabhängig von den Interrupts des µC wenn ich bei diesem das Interrupt Enable Flag nicht gesetzt habe.
Als Pullups nutze ich zwei 10k Ohm Widerstände.
Danke für den Link!
Dort scheint es alles zu geben, was ich so brauchte.
MfG
Bastian
10K sollte ok sein (ich verwende meist 4,7K), welche Datenrate verwendest du?
Woran kann es liegen, das ich kein Start senden kann???
bekomme das TWINT-Bit nicht gesetzt.
Im Bus existieren nur ein PCF8574 und ein PCF8591.
setze den TWBR auf 15 ( TWBR = 0x10 )
ach ja, und der µC läuft mit 16Mhz
Lesezeichen