Probleme TWI (I2C) Atmega 16 Im Unterforum Microcontroller - Beschreibung: Hardware - Software - Ideen - Projekte
Autor |
Probleme TWI (I2C) Atmega 16 Suche nach: i2c (581) atmega (404) |
|
|
|
|
BID = 692376
terrorfreak Neu hier
Beiträge: 36 Wohnort: Weikersheim
|
|
Hi!
Ich bins mal wieder.^^
Hab mich jetzt schonmal ganz gut im Datenblatt zurecht gelesen. Nur eine Sache versteh ich noch nicht ganz. Wie kann ich dem Slave sagen, was er tun soll, wenn er adressiert wurde? Ich hab mich jetzt entschlossen, einen Master zu defineren, der die Slaves pollt, also dauerhaft alle nacheinander abfragt, da mir die Zeit nicht so wichtig ist. Ich hab also an Slave 1 bestimmte Schalterstellungen an PortA. Diese sollen dann vom Master erfasst werden. Und je nach Schalterstellung weiß der Master, welche Anfrage der Slave hat und was er ihm an Daten schicken soll. Zum Beispiel wenn am Slave1 die Schalterstellung 0000 0001 ist, weiß der Master, dass der Slave1 die momentane Temperatur haben will. Also startet der Master die Temperaturabfrage und schickt dieses Paket dann dem Slave1 zurück, sodass er es an der doppelten 7-Segment-Anzeige anzeigen kann.
Ich hoffe ich konnte mein Problem gut schildern und freu mich schon auf deine Antwort! Du hast mir nämlich schon rießig geholfen!
Gruß Bastian |
|
BID = 692379
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
|
Hallo,
Wenn der AVR im Slavemodus läuft, eine korrekte Adresse hat und mit ihr adressiert wurde, wird TWINT gesetzt. Ist zusätzlich der Interrupt für die TWI-Hardware aktiv sowie das Globale Interruptflag gesetzt, so wird die entsprechende ISR ausgeführt.
_________________
|
|
BID = 692383
terrorfreak Neu hier
Beiträge: 36 Wohnort: Weikersheim
|
Erstmal danke für die schnelle Antwort!
Also schreib ich für den Slave ein Programm, das ihn in der main() mit while(1); erstmal aufhängen lässt. und in der Interruptroutine lass ich ihn erstmal ein bisschen warten und sende die Daten (Schalterstellung). Falls die Schalterstellung größer 1 ist, wartet er dann auf die Daten, die er dann vom Main bekommen soll. Versteh ich das richtig?
Ich hoffe ich schreib gerade nicht großen Unsinn. ^^ Stehe nämlich gerade ein wenig auf dem Schlauch. Oder kennst du zufällig einen Beispiel Programmtext? Hab leider im Datenblatt keinen gefunden.
Gruß Bastian
|
BID = 692385
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Naja, schau dir einfach nur die Registerbeschreibung an, das reicht.
Dazu kannst du ja dann meine Bibliothek benutzen, damit kann man den Slave direkt initialisieren.
solte etwa so aussehen:
global:
volatile uint8_t twi_flag;
int main(void)
{
....
....
while( 1 )
{
....
....
if( twi_flag )
{ */ hier Auswertung der Daten, die der Master gesendet hat */
....
twi_flag = 0;
}
}
}
ISR(TWI_vect)
{ /* wir wurden gerade adressiert */
twi_flag = 1;
}
Dein Problem ansich verstehe ich allerdings nicht richtig. Wenn du deinen Algorithmus (nichts anderes ist es ja) nicht beschreiben kann, dann mal dir ein Flussdiagramm oder so auf.
Grundsätzlich pollt der Master den Slave, an dem die Taster hängen.
Also muss schonmal ein Code vereinbart werden, den der Master zum Slave sendet (z.B. 0xee, rein willkürlich). Empfängt der Slave 0xee, dann antwortet er wiederum mit einem Code, der entweder besagt, dass keine Aktion stattfand (Tastendruck) oder der direkt die aktuellen Tasterzustände zurückschickt.
Wie das im Detail aussieht kann ich dir natürlich nicht sagen, die Spezifikation musst du schon selbst entwickeln.
Auf jeden Fall dokumentiere, egal wie einfach es auch sein mag, das Protokoll orderntlich! Zu dem Protokoll entwirfst du dann einen C-Header, indem alle Codes (nennen wir es Instruktion) symbolisch abgelegt sind. Slave- und Masterquellkode binden dann diesen Header nur ein und du kannst fortan symbolische Codes verschicken.
_________________
|
BID = 692391
terrorfreak Neu hier
Beiträge: 36 Wohnort: Weikersheim
|
ahh, ok, das hilft mir schon viel, danke!
War mir nur nichtmehr sicher, wie genau ich die Register aufbauen soll. Wir haben es in der Schule nämlich immer ein wenig anders aufgebaut. Da war es aber auch ein anderer Controller.^^
Wo finde ich nochmal genau deine lib? Ich denke, dass ich daraus bestimmt auch erstmal viel lernen und erfahren kann und besser weiß, wie ich dann fortfahre.
Gruß Bastian
|
BID = 692400
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
|
BID = 698122
terrorfreak Neu hier
Beiträge: 36 Wohnort: Weikersheim
|
Hi wiedereinmal! ^^
Hab nun folgendes Programm geschrieben indem ich nur ein einfaches Datenpaket vom einen Atmega16(Master) auf den anderen Atmega16(Slave) schicken will. Der Slave soll das Datenpaket dann auf Port A ausgeben. Problem is nur, dass nichts funktioniert leider.Ich komme mit der einen Warnung leider nicht klar, bzw weiß ich nicht, was sie bedeutet.
../TA_SLAVE.c:52: warning: assignment makes integer from pointer without a cast
Könntest du mir bitte sagen, was damit gemeint ist?
Hier auch mal kurz das Programm, falls ich doch wiedermal irgendwelche dumme Fehler drin habe.^^
Master:
#include <avr/delay.h>
#include <avr/io.h>
void i2c_init(void)
{
TWSR = 0; // kein Vorteiler
TWBR = 32; // Da Quartz bei 8 MHz
}
void start_i2c()
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while (!(TWCR & (1<<TWINT)));
}
void stop_i2c()
{
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}
void senden_i2c(char daten)
{
TWDR=daten;
TWCR = (1<<TWINT) | (1<<TWEN);
while( !(TWCR & (1<<TWINT)) );
}
unsigned char i2c_empfangen(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
while(!(TWCR & (1<<TWINT)));
return TWDR;
}
void main (void)
{
i2c_init();
int daten = 0xAA;
while(1)
{
start_i2c(); // Start I2C
senden_i2c(0x01); // Adressierung Slave 1
senden_i2c(daten); // Sende 0xAA an Slave 1
stop_i2c();
}
}
Und dann noch Slave 1:
#include <avr/delay.h>
#include <avr/io.h>
uint8_t i2c_init (uint8_t Address)
{
TWSR = 0; // kein Vorteiler
TWBR = 32; // Da Quartz bei 8 MHz
TWAR = (Address << 1);
TWCR = (1<<TWEN)|(1<<TWEA);
}
unsigned char i2c_empfangen(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
while(!(TWCR & (1<<TWINT)));
return TWDR;
}
volatile uint8_t twi_flag;
int daten;
int main(void)
{
DDRA=0xFF;
PORTA=0xFF;
i2c_init(0x01);
while(1)
{
if( twi_flag )
{
daten = i2c_empfangen; <<Fehler wird hier angezeigt
twi_flag = 0;
}
PORTA = daten;
}
}
Ich hoffe du kannst mir helfen. Bin so langsam am verzweifeln, weil ich mir alles doch ein wenig einfacher vorgestellt hab...
Gruß Bastian
|
BID = 698134
terrorfreak Neu hier
Beiträge: 36 Wohnort: Weikersheim
|
Bin grad noch an der Fehlersuche. Also beim Master kanns eigentlich net liegen. Der arbeitet die while(1)-Schleife ohne Probleme non-stop ab. Also denk ich mal, dass ich noch ein Fehler im Slave-Programm hab.
Hab grad nochmal deine letzten Posts angeschaut und da war noch das:
ISR(TWI_vect)
{ /* wir wurden gerade adressiert */
twi_flag = 1;
}
Für was steht das nochmal genau, und kann es daran liegen?
Die andere Warnung hab ich jetzt schon wegbekommen.
Gruß Bastian
P.S. Ich hoffe ich kann wieder auf deine Hilfe zählen.
|
BID = 698147
terrorfreak Neu hier
Beiträge: 36 Wohnort: Weikersheim
|
Erstmal sorry, für die Mehrfachposts.^^
Hab jetzt gerade hier das Slaveprogramm. Aber der Fehler liegt wohl in der Adressierung. Der Master versucht die ganze Zeit 0x02 zu adressieren, aber der antwortet nicht komischerweise..
Hier nochmal das aktuelle Programm.
Code : |
#define F_CPU 8000000UL
#include <avr/delay.h>
#include <avr/io.h>
void i2c_init (uint8_t Address)
{
TWSR = 0; // kein Vorteiler
TWBR = 32; // Da Quartz bei 8 MHz
/*
** Set the TWI slave address
*/
TWAR = (Address << 1);
/*
** Activate TWI interface
*/
TWCR = (1<<TWEN)|(1<<TWEA);
}
unsigned char i2c_empfangen(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
while(!(TWCR & (1<<TWINT)));
return TWDR;
}
int daten = 0x00;
int main(void)
{
DDRA=0xFF;
PORTA=0xFF;
uint8_t status;
i2c_init(0x02);
while(1)
{
PORTA = 0x01;
while(!(TWCR & 0b10000000)); //solange warten, bis was ankommt
PORTA = 0x02;
TWCR &=~ (1<<TWINT); //TWINT auf 0 setzten damit TWI wieder arbeitet
PORTA = 0x03;
TWCR |= (1<<TWEA); //TWEA auf 1 setzten um Ack zu senden
PORTA = 0x04;
daten = i2c_empfangen();
PORTA = 0x05;
}
PORTA = daten;
}
|
|
Hab hier mal in der While(1)-Schleife den PortA nach jedem Schritt eine Nummer weiter Hochgezählt um den Fehler herauszufinden. Bloß leider bleibt er schon bei 1 stehen. Ich wüsste auch leider nimmer, was ich noch tun soll. Bin schon die ganze Zeit beim rumgoogeln und Datenblatt nachlesen...
Gruß Bastian
|
BID = 698169
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Zitat :
|
daten = i2c_empfangen; <<Fehler wird hier angezeigt |
Da weißt du einer Ganzzahlvariablen die Adresse der Funktion i2c_empfangen zu...
Da fehlt der Funktionsoperator(), haste aber selbst gemerkt.
Irgendwo hatte ich es bereits zigfach erwähnt: die Adressierung ist bei den Registern etwas verwirrend. Beim Slaveadressenregister ist das unterste Bit für den generell call reserviert, daher wird die Adresse dort um ein Bit nach links geschoben, wenn dieser Modus nicht erwünscht ist.
So, wenn du den Slave aber adressierst, legt das LSB fest, ob gelesen oder geschrieben werden soll. Eine 1 heißt dabei, dass gelesen werden soll, eine 0 bedeutet Schreibzugriff.
Also musst du die Adresse mit zwei multiplizieren und hinten entsprechend entweder das Bit setzen zum Lesen oder es unverändert lassen zum Schreiben.
Was ich ebenfalls erwähnt war, dass das TWINT-Flag anders als fast alle Flags/Bits ist: Es wird gelöscht, indem man eine 1 reinschreibt;
Zitat :
|
TWCR &=~ (1<<TWINT); //TWINT auf 0 setzten damit TWI wieder arbeitet
|
bleibt daher effektlos.
Leider hast du einen wilden Mix an Funktionen und ich erkenne nur noch Bruchteile meiner Bibliothek. Da ich keine Lust habe, zusammengeschusterte Bibliotheken auf logische Fehler zu prüfen (z.B. eben, dass man TWINT mit 1 löscht), musst du das selbst machen. Schließlich könntest du einfach meine Bibliothek komplett übernehmen, da weiß ich zumindest, dass sie funktioniert.
Aber warum einfach, wenns auch kompliziert geht.
Zitat :
|
[...]
volatile uint8_t twi_flag;
int daten;
int main(void)
{
DDRA=0xFF;
PORTA=0xFF;
i2c_init(0x01);
while(1)
{
if( twi_flag )
{
daten = i2c_empfangen; <<Fehler wird hier angezeigt
twi_flag = 0;
}
PORTA = daten;
}
[...]
|
Wieder ein Beispiel, wo man sieht, dass einfaches Kopieren von Programmtext meistens völlig in die Hose geht.
Du testest hier doch eine Variable, die nie verändert wird, da muss doch was fehlen! Und das, was fehlt, ist die Interruptroutine, die das Flag (twi_flag) setzt!
Das Ding
ISR(TWI_vect)
{ /* wir wurden gerade adressiert */
twi_flag = 1;
}
muss selbstredend da mit rein, oder eben über Polling wie beim letzen Beispiel.
Zitat :
|
Der arbeitet die while(1)-Schleife ohne Probleme non-stop ab. Also denk ich mal, dass ich noch ein Fehler im Slave-Programm hab.
|
Das ist auch schlecht. Der ballert den armen Slave ja geradezu voll, wenn er denn überhaupt die richtige Adresse senden würde .
Lasse Pausen von einer Sekunde oder ähnlich dazwischen, setze die Busfrequenz ganz runter. Das, was du da betreibst, nennt man "flooding", und man nutzt es, um Teilnehmer eines Busses aus dem Takt zu bringen...
---
Also:
* prüfe die richtige Adresse! Das LSB auf dem Bus muss 0 sein, damit er überhaupt schreibt.
* beim Slave müssen Interrupts allgemein zugelassen werden
( asm volatile ( "sei " ); )
und speziell das Interruptflag für TWI muss aktiv sein (in meiner Bibliothek bereits erledigt)
* Schicke alle paar Sekunden ein Datenpaket oder, wenn du es mit dem Oszi betrachten willst, alle 10ms.
* werte doch bitte die Statuskodes der TWI-Hardware aus (z.B. indem du sie an einen PC schickst oder auf nem Display darstellst. Die geben den Status exakt wieder! Anhand dieser Codes kann man genau nachvollziehen, warum eine Transaktion auf dem Bus schieflief.
* teste, ob die Werte für die Busfrequenz (SCL-Takt) plausibel sind.
_________________
|
BID = 698179
terrorfreak Neu hier
Beiträge: 36 Wohnort: Weikersheim
|
Also in dem Master-Programm hab ich schon Pausen reingemacht mit jeweils 1000ms und den Leds an Port A, die hochgezählt werden, wenn das Programm einen Schritt weiter ist. Geht also schön langsam.^^ Hab ich aber hauptsächlich gemacht, damit ich die Fehler besser einordnen kann. Aber kannst du mir bitte nochmal erklären, was die
ISR(TWI_vect)
{ /* wir wurden gerade adressiert */
twi_flag = 1;
}
Schleife genau macht? Und wo ich die dann hinmachen muss. Beziehungsweise für was das ISR auch steht usw. Blick da leider net ganz durch. Und könntest du mir bitte deine Library nochmal in diesem Thread posten, weil ich mit dem Link leider nicht ganz klar kam.
Ich glaub langsam musst du mir mal deine Adresse geben, damit ich dir mal ein Kasten Bier oder so als Dankeschön für die Hilfe schicken kann, soviel du mir schon geholfen hast.^^
Gruß Bastian
|
BID = 698180
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
https://forum.electronicwerkstatt.d.....r.txt
Herunterladen, eventuell die Endung .txt entfernen und mit einem Archivprogramm öffnen. Das ist ein normales TAR-Archiv.
Die Bibliothek entstand, als ich noch relativ neu in der C-Programmierung war, und ändern wollte ich auch nichts mehr dran. Denk dir die Semikolons am Ende jeder Funktion einfach weg, die haben da nichts zu suchen
Zitat :
|
Aber kannst du mir bitte nochmal erklären, was die
ISR(TWI_vect)
{ /* wir wurden gerade adressiert */
twi_flag = 1;
}
Schleife genau macht?
|
Das ist keine Schleife.
Das ist ein Interrupt-Handler, also (eigentlich) eine normale C-Funktion.
Diese Funktion wird dann aufgerufen, wenn der AVR per TWI/I²C adressiert wurde. Dort wird dann twi_flag auf 1 gesetzt und die ISR (interrupt service routine) wieder beendet. Je kürzer solche Routinen sind, desto besser.
Damit dies passieren kann, müssen Interrupts global aktiviert werden (dazu setzt man das entsprechende I-Bit im Statusregister, es gibt sogar eine gesonderte Maschineninstruktion, nämlich sei. Assembler kann man in C direkt einbinden:
asm( "Maschineninstruktionen" );
Besser als nur asm wäre allerdings volatile asm, da dann an dem Codestück nicht rumoptimiert wird.
Da es mehrere Interruptquellen gibt, hat jede Quelle einen Schalter, um das Interrupt unabhängig von anderen zu aktivieren /deaktivieren. In diesem Fall ist dafür TW IE (interruopt enable) zuständig.
So, wurde der AVR also adressiert, springt der Programmzeiger in die entsprechende ISR, führt sie aus und arbeitet danach das laufende Programm ab. Man sagt auch, dass das Programm in der Interruptroutine im Vordergrund läuft, auch wenn das etwas verwirrend sein mag.
Um diese ISRs nutzen zu können musst du den Header interrupt.h einbinden:
#include <avr/interrupt.h>
Dann definierst du dir noch:
#define enable_interrupts() asm volatile ( "sei" )
#define disable_interrupts() asm volatile ( "cli" )
und schon läuft die Sache
P.S.: das mit dem Bier ist eine gute Idee
_________________
|
BID = 698304
terrorfreak Neu hier
Beiträge: 36 Wohnort: Weikersheim
|
Also müsste der Programmtext dann so ausschauen, oder? und mit der enable und disable_interrupt kann ich dann die interrupts in der while (1)-Schleife an und ausschalten, dass nicht nochein Interrupt ausgelöst wird, wenn er gerade am Daten auslesen ist oder so. Jetzt wirds langsam lichte bei mir im Kopf.^^ In der Schule hatte wir bei dem Infineon C515C uC auch immer solche Interrupt-Funktionen. Bloß mussten wir da noch dahinterschreiben Interrupt 1,2,3... oder so.Hier steht es dann bei ISR(Welcher Interrupt_vect) soviel ich das in der interrupt.h gelesen hab.
Mit deiner lib hab ich leider immernoch Probleme. Man kann leider mit dem blöden vista nimmer so einfach die Dateiendungen ändern. Und wenn ich sie als .txt mit dem Editor öffne, sehe ich auch nur die Aufrufe von den TWI-Funktionen aber leider nicht, was in diesen Funktionen steht. Kannst du diese hier bitte als Code mal posten? Oder kannst mir ein Programm empfehlen, mit dem ich diese lib am besten öffnen kann? Kann gut sein, dass der wichtige Inhalt auch die tausend komischen Zeichen gleich am Anfang der Datei ist.^^
Hier nochmal mein bisheriger Fortschritt:
Code : |
#include <avr/interrupt.h>
#define F_CPU 8000000UL
#include <avr/delay.h>
#include <avr/io.h>
#define enable_interrupts() asm volatile ( "sei" )
#define disable_interrupts() asm volatile ( "cli" )
uint8_t twi_flag;
ISR(TWI_vect)
{ /* wir wurden gerade adressiert */
twi_flag = 1;
}
void i2c_init (uint8_t Address)
{
TWSR = 0; // kein Vorteiler
TWBR = 32; // Da Quartz bei 8 MHz
/*
** Set the TWI slave address
*/
TWAR = (Address << 1);
/*
** Activate TWI interface
*/
TWCR = (1<<TWEN)|(1<<TWEA);
}
unsigned char i2c_empfangen(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
while(!(TWCR & (1<<TWINT)));
return TWDR;
}
int daten = 0x00;
int main(void)
{
DDRA=0xFF;
PORTA=0xFF;
enable_interrupts(); // Interrupts anschalten um TWINT zu ermöglichen
i2c_init(0x02);
while(1)
{
PORTA = 0x01;
if ( twi_flag == 1)
{
disable_interrupts();
PORTA = 0x02;
_delay_ms(500);
TWCR |= (1<<TWEA); //TWEA auf 1 setzten um Ack zu senden
PORTA = 0x03;
daten = i2c_empfangen();
_delay_ms(500);
PORTA = daten;
twi_flag = 0;
enable_interrupts();
}
}
}
|
|
P.S. Kannst mir ja mal deine Adresse per E-Mail schicken, dann lass ich dir einen Kasten zukommen.^^
[ Diese Nachricht wurde geändert von: terrorfreak am 24 Jun 2010 16:18 ]
|
BID = 698310
terrorfreak Neu hier
Beiträge: 36 Wohnort: Weikersheim
|
Was ich gerade noch gesehen habe in meinem Master C-Code
Müsste ich net
Code : |
void senden_i2c(char daten)
{
TWDR = daten; // Sende Daten
TWCR = (1<<TWINT) | (1<<TWEN);
while( !(TWCR & (1<<TWINT)) );
}
|
|
in
Code : |
void senden_i2c(char daten)
{
TWDR = daten; // Sende Daten
while( !(TWCR & (1<<TWINT)) );
TWCR = (1<<TWINT) | (1<<TWEN);
}
|
|
ändern? Also ich mein, eigentlich muss er doch erst warten, bis das TWINT gesetzt wird und dann erst wieder Rücksetzen, oder?
Hab auch mal das aktuelle Programm getestet und das Status-Register ausgelesen und an PortA ausgegeben. Bloß komm ich mit dem Wert (11111000) leider net klar... Steht nirgends beschrieben, weil das doch F8 in hex wäre....
P.S. Wiedermal sorry für mehrfachpost, kann komischerweise nur einmal editieren.^^
[ Diese Nachricht wurde geändert von: terrorfreak am 24 Jun 2010 17:09 ]
|
BID = 698384
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Moin,
Zur Bibliothek: das ist ein (schrieb ich ja) TAR-Archiv, sollte selbst Vista lesen können. Kannst mir auch ne Mail schreiben, dann hänge ich dir die Bibliothek an, wenn das unter Vista nicht klappt.
Offtopic :
| Was für ein unfähiges System |
Zitat :
| Hier nochmal mein bisheriger Fortschritt: [...] |
Ergänze (Fettgedruckt) zu:
void i2c_init (uint8_t Address)
{
TWSR = 0; // kein Vorteiler
TWBR = 32; // Da Quartz bei 8 MHz
/*
** Set the TWI slave address
*/
TWAR = (Address << 1);
/*
** Activate TWI interface
*/
TWCR = (1<<TWEN)|(1<<TWEA)|(1<<TWIE);
}
Dann klappt das auch mit dem Interrupt
Prinzipiell sollte es so funktionieren.
Du musst bei der Adresse 0x2 also mit 0x4 beim Master adressieren. Eigentlich ist auch hier die Adresse 0x2, aber um ein Bit nach links verschoben wegen des nötigen R-/~W-Bits.
Zitat :
|
Müsste ich net
[...]
in
[...]
ändern?
|
Jein.
Wenn du in allen Prozeduren zur TWI dich darauf einigst, am Ende jeweils so lange zu warten, bis die TWI-Aktion durchgeführt wurde, dann musst du nichts ändern. So hält es auch meine Bibliothek.
Bei allen Aktionen, bis auf das Senden der Stopkondition, wird das TWINT-Flag gesetzt.
Man kann sich natürlich auch drauf einigen, anfangs zu warten, bis die ggfs. letzte Aktion abgeschlossen ist.
Erste ist der Übersicht halber vorzuziehen.
Richtig "profihaft" wäre es, das ganze asynchron zu machen: jedes Mal, wenn TW INT kippt, wird ein TWI-Interrupt ausgelöst, indem man dann entsprechend den Statuskodes die nächste Aktion startet.
Das ergibt vor allem dann Sinn, wenn ein langsamer Slave an einem sehr schnellen Prozessor betrieben wird. Denn Slaves können den Master zwingen, die Daten langsamer zu senden, wenn sie nicht mitkommen. Das kann für den flotten Master bedeuten, dass er über eine ms lang nichts tut. Da sind dann asynchrone Bibliotheken besser, aber auch geringfügig aufwendiger und größer.
Zitat :
|
Bloß komm ich mit dem Wert (11111000) leider net klar... Steht nirgends beschrieben, weil das doch F8 in hex wäre....
|
Das muss so.
f8 steht für den Grundzustand der TWI-Hardware und bedeutet, dass nichts Interessantes los ist. TWSR wird nach jedem setzen von TWINT interessant, weil es dann den letzten Status der Hardware repräsentiert.
Edit:
hier mal als ZIP-Archiv, vielleicht geht es so besser.
Offtopic :
| Linuxmaschinen sind schlau genug, den Dateityp nicht (nur) über die Endung zu ermitteln. Da wird meist das richtige Programm gestartet, auch wenn die Endung fehlt oder falsch ist. |
_________________
[ Diese Nachricht wurde geändert von: DonComi am 24 Jun 2010 23:16 ]
|
|
Zum Ersatzteileshop
Bezeichnungen von Produkten, Abbildungen und Logos , die in diesem Forum oder im Shop verwendet werden, sind Eigentum des entsprechenden Herstellers oder Besitzers. Diese dienen lediglich zur Identifikation!
Impressum
Datenschutz
Copyright © Baldur Brock Fernsehtechnik und Versand Ersatzteile in Heilbronn Deutschland
gerechnet auf die letzten 30 Tage haben wir 20 Beiträge im Durchschnitt pro Tag heute wurden bisher 10 Beiträge verfasst © x sparkkelsputz Besucher : 182397090 Heute : 4286 Gestern : 7548 Online : 436 25.11.2024 15:25 8 Besucher in den letzten 60 Sekunden alle 7.50 Sekunden ein neuer Besucher ---- logout ----viewtopic ---- logout ----
|
xcvb
ycvb
0.0483751296997
|