Autor |
Probleme TWI (I2C) Atmega 16 Suche nach: i2c (581) atmega (404) |
|
|
|
|
BID = 698925
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
|
Also Moment mal.
Das Statusregister hat immer nur dann aussagekräftige Inhalte, wenn TWINT gesetzt wurde. Sonst nicht.
Das heißt, nach -
- i2c_start()
ist ein gültiger Wert im Statusregister,
- i2c_transmit();
- i2c_receive();
und i2c_stop();.
Und die will ich haben.
11111000 bzw. 0xf8 bedeutet, dass keine besondere Aktion stattgefunden hat.
Kannst du Daten mit der seriellen Schnittstelle zum Rechner senden? Wenn ja, lass dir nach jeder Aktion (siehe oben) den Statuskode hexadezimal zum Rechner senden.
Ansonsten hast du offensichtlich einen groben Fehler drin. Da hilft nur Datenblatt rausholen und penibel alles überprüfen.
Übermorgen habe ich wieder mehr Zeit, bis dahin habe ich einen A****h voll zu tun. Daher kann ich jetzt nicht schreiben, wie ich es machen würde.
Prinzipiell aber: mit meiner Bibliothek und nach jeder Aktion den entsprechenden Statuskode testen. Die sind im Datenblatt ja alle gelistet. Sobald etwas abweicht, ist ein Fehler aufgetreten, so einfach ist das.
_________________
|
|
BID = 698934
terrorfreak Neu hier
Beiträge: 36 Wohnort: Weikersheim
|
|
Aber irgendwie is komisch, dass sich dann überhaupt nix ändert. Hab ja nach jeder Funktion eine Sekunde Pause reingemacht. Und mit dem Statuscode vom Master kann man ja leider auch nichts anfangen. UART hab ich leider keine zum PC. Bin mir sicher, dass ich auch daran verzweifelt wäre.^^
Aber mal ne ganz dumme Frage. Hab grad gesehen, dass bei mir nach dem HEX-Datei erstellen unten
AVR Memory Usage
----------------
Device: atmega128
Program: 506 bytes (0.4% Full)
(.text + .data + .bootloader)
Data: 0 bytes (0.0% Full)
(.data + .bss + .noinit)
Build succeeded with 0 Warnings...
steht. Aber ich wähle doch bei jedem Projekt immer meinen Atmega 16 aus... Ich weiß, dass es nur für den Debugger ist, aber das müsste ich doch umstellen können, oder nicht? Ich weiß auch, dass das eigentlich nicht der Fehler ist, da ja mein Programm vorher mit der Temperaturauslesung auch funktioniert hat.
Gruß Bastian
|
|
BID = 698943
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Welcher Controller ist denn eingestellt oder wie ist der Compileraufruf (damit kenne ich mich mehr aus ).
Das müste beim GCC sowas wie -mmcu=atmega16 sein.
Sollte der falsche µC ausgewählt sein, würde mich nichts wundern .
Wie dem auch sei, es scheint entweder ein Softwareproblem zu sein, oder ein elektrisches. Sollte sich rausstellen, dass softwaretechnisch alles in Ordnung ist, musst du wohl oder übel mal mit dem Oszi ran.
Edit:
Also keiner der Statuskodes ergibt wirklich Sinn außer 0xf8.
Da stimmt also was bei dir nicht! Es könnte sogar sein, dass du wirlich für einen falschen Prozessor kompiliert hast und die IO-Adressen nicht alle stimmen... Aber soweit kann ich von hier aus nicht denken!
Also, folgendes Programm sollte passen:
inline uint8_t i2c_stat(void) { return TWSR & 0xf8; }
uint8_t ein_byte_senden(uint8_t byte)
{
register uint8_t ret = 0;
i2c_start();
if( (ret=i2c_stat()) != 0x08 ) goto i2c_err; /* Stat fehlg. */
i2c_transmit(0x46 + 0);
if( (ret=i2c_stat()) != 0x18 ) goto i2c_err; /* kein ACK erhalten */
i2c_transmit(byte);
if( (ret=i2c_stat()) != 0x30 ) goto i2c_err; /* siehe unten */
i2c_stop();
return 0;
i2c_err:
i2c_stop(); /* Verbindung abbrechen */
return ret;
}
Werte nach Datenblatt ATMEGA16, Seite 182.
0x18 wird nur dann zurückgegeben, wenn die Schreibeadresse gesendet und ein ACK empfangen wurde. Nur dann ist der Slave bereit, Daten anzunehmen. Antwortet er mit NACK (lehnt die Verb. ab) ist der Kode 0x20.
Dann senden wir Daten. Wir wollen nur ein Byte schicken, also muss der Slave danach die Verb. beenden, das tut er mit einem NACK. Also muss der Statuskode 0x30 sein. Antwortet er mit ACK ist der Kode 0x28.
Das Protokoll muss auf der anderen Seite genauso implementiert werden: der Slave muss mit NACK antworten, da der Master nur diese Möglichkeit testet, nicht etwa ein ACK.
Die Routine gibt jeweils den Statuskode im Fehlerfalle zurück, sonst 0.
Sie ist ein wenig sicherer, aber kann in den While-Schleifen immer noch abstürzen. Da könnte man entweder ein Timer einbauen oder gleich asynchron arbeiten. Aber es soll ja erstmal nur funktionieren, Sicherheit kommt dann später
Klar soweit?
P.S.: normalerweise packt man solche Konstanten noch in Enumeration (enum...) oder definiert sie zumindest symbolisch. Das gehört sich so, weil es dann verständlicher wird. Ich habe das Programm in einer Minute getippt, da darf man das nicht erwarten.
_________________
[ Diese Nachricht wurde geändert von: DonComi am 27 Jun 2010 21:34 ]
[ Diese Nachricht wurde geändert von: DonComi am 27 Jun 2010 21:35 ]
|
BID = 698985
terrorfreak Neu hier
Beiträge: 36 Wohnort: Weikersheim
|
Auwee.^^ Prompt als ich beim Master wieder auf Atmega 16 geschalten hab, funktioniert garnix mehr.^^ Der Slave arbeitet immernoch mit dem Selben Statuscode, aber der Master spuckt garnix mehr aus. Langsam wirds mir unheimlich. Dein C-Code kann ich dann komplett in meine main() einbauen, oder? Ich frag nur lieber im Vorraus, um gleich Fehler zu vermeiden.^^ Ich glaub sowieso langsam, dass ich mich damit abfinden muss, dass ich es nicht auf die Reihe krieg.^^
Gruß Bastian
|
BID = 698989
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Nix in main einbauen. Das ist eine Funktion, die kommt irgendwo außerhalb einer anderen Funktion hin.
In main kannst du sie aber aufrufen
Du kannst meine Rückfragen übrigens gern beantworten:
· Hast du ein Oszi (eventuell von Schule, Uni, Atomphysiker um die Ecke, ...)
· wie lautet der Compileraufruf?
_________________
[ Diese Nachricht wurde geändert von: DonComi am 28 Jun 2010 2:00 ]
|
BID = 698991
terrorfreak Neu hier
Beiträge: 36 Wohnort: Weikersheim
|
Oh, sorry. Hab doch glaub in ein paar posts vorher schon gesagt, dass ich kein Oszi hab. Könnte höchstens mit nem älteren Multimeter dienen.^^ Is schön orange und schaut aus wie ein China-Import.^^ Aber messen kann man zumindest mit.
Ich dachte der Compileraufruf steht da unter Einstellungen, also da wo ich von Atmega128 auf Atmega16 gestellt hab. Oder muss ich da wo anders schaun?
Gruß Bastian
|
BID = 698992
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Du nutzt doch WinAVR?
Da sieht man unten im Log doch, wie der Compiler (avr-gcc) aufgerufen wird.
_________________
|
BID = 699012
terrorfreak Neu hier
Beiträge: 36 Wohnort: Weikersheim
|
Meinst du das:
Loaded plugin STK500
Loaded plugin AVR GCC
Loaded partfile: C:\Program Files\Atmel\AVR Tools\PartDescriptionFiles\ATmega16
?
Gruß Bastian
|
BID = 699042
terrorfreak Neu hier
Beiträge: 36 Wohnort: Weikersheim
|
Sorry, für den Doppelpost. Kann leider nimmer Editieren. Bind ich so dann richtig? Oder soll ich die Funktion lieber erst in einer Variablen speichern und dann an PortB ausgeben?
Code : |
int main (void)
{
DDRB=0xFF;
PORTB=0xFF;
uint8_t daten2 = 0xAA;
uint8_t rueckgabewert;
i2c_switch_master(64);
while(1)
{
rueckgabewert = ein_byte_senden(daten2);
PORTB = rueckgabewert;
_delay_ms(500);
}
}
|
|
Aber es tut sich wieder was.^^ Der Master zeigt 00100000 an. Der Slave erst wieder die 11111000 wie immer. Dann sind alle Leds ewig auf 0 und dann auf 01100000.Und wenn ich noch länger warte, also so ca 1 min oder länger ist alles auf 0.
Demnach entnehme ich aus dem Datenblatt, dass der Master mit 00100000(0x20)
SLA+W has been transmitted;
NOT ACK has been received
Für den Slave habe ich dann mit 01100000(0x60) und dem entehme ich aus dem Datenblatt:
Own SLA+W has been received;
ACK has been returned
Und wenn ich gaaaaaaaaannnnnnzzzzzz lange warte.^^ ca 2-3 min oder zeigt der Slave 10001000(also 0x88) Daraus entnehme ich aus dem Datenblatt:
Previously addressed with own
SLA+W; data has been received;
NOT ACK has been returned
Kurz Darauf steht auf meinem PortB des Slaves 10101010(0xAA)
========> Es geeeeeeeehhhhhhttttt!!!!!!!!!!!!
Gruß Bastian
P.S. Rießen Dankeschön für deine Hilfe, ohne dich hätte ich das echt nicht hinbekommen!!!!!! Wie gesagt, brauch ich nur noch deine Adresse für du weißt schon.^^
|
BID = 699068
terrorfreak Neu hier
Beiträge: 36 Wohnort: Weikersheim
|
Aber das nächste Problem ist schon da.^^ Habe jetzt noch meine Funktion zum Temperaturauslesen noch mit reingepackt, aber der Atmega hängt sich leider an dieser Stelle auf. Kannst du bitte mal drüberschaun?
Code : |
uint8_t temperatur_auslesen(void)
{
uint8_t MSB;
// SEND A "STANDALONE" COMMAND (START/STOP CONVERT)
i2c_start(); // Start I2C
i2c_transmit(0x90); // 1001 000 0 Adressierung (write)
i2c_transmit(0xEE); // Messung starten
i2c_stop();
// READ FROM A TWO-BYTE REGISTER (TH, (TL), TEMPERATURE)
i2c_start(); // Start I2C
i2c_transmit(0x90); // 1001 000 0 Adressierung (write)
i2c_transmit(0xAA); // Befehl Temperatur lesen
i2c_start(); // Repeated start
i2c_transmit(0x91); // 1001 000 1 Adressierung (read)
MSB = i2c_receive(ACK); // Wert empfangen
/*LSB = i2c_receive();*/ // Kommastelle empfangen
i2c_stop();
return MSB;
}
int main (void)
{
DDRB=0xFF;
PORTB=0xFF;
uint8_t temperatur;
/*uint8_t daten2 = 0xAA;*/
uint8_t rueckgabewert;
i2c_switch_master(64);
temperatur = temperatur_auslesen();
if (temperatur >= 0){PORTB = 0xAA;}
while(1)
{
rueckgabewert = ein_byte_senden(temperatur);
PORTB = rueckgabewert;
_delay_ms(500);
}
|
|
P.S. Im Anhang hab ich nochmal das Datenblatt und den Aufbau mit dem Temperatursensor und das Datenblatt dafür. Wenn das noch klappt wäre ich endlich fertig mit meinem Projekt und kann mich an die Doku ranmachen.^^
Gruß Bastian
|
BID = 699072
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
MSB = i2c_receive(ACK); // Wert empfangen
/*LSB = i2c_receive();*/ // Kommastelle empfangen
i2c_stop();
Das ist das Problem. Der Master sendet nach dem ersten Datenbyte ein ACK zurück -> signalisiert dem Slave, dass der das nächste Byte schicken soll. Nur holst du das nicht ab...
Es müsste vielmehr (ohne das Datenblatt gelesen zu haben...)
MSB = i2c_receive(ACK); // Wert empfangen
LSB = i2c_receive(NACK); // Kommastelle empfangen
i2c_stop();
sein.
Dennoch funktioniert was mit dem Slave nicht richtig. Das muss reproduzierbar funktionieren, nicht erst nach 5 Minuten.
Daher fragte ich bereits zigmal, wie der eigentlich genau beschaltet ist (ALLES! und bitte RICHTIG!).
-5V sind -5V, die Pullupwiderstände kommen ans SCL und SDA. Und alle ICs müssen Stützkondensatoren haben, sonst ist es mehr oder weniger klar, dass das nicht ordentlich funktioniert.
_________________
|
BID = 699081
terrorfreak Neu hier
Beiträge: 36 Wohnort: Weikersheim
|
wie gesagt, so wie auf dem Blatt ist alles beschalten. Die Zeit, warum er solange braucht is nur wegen den vielen Warteschleifen denk ich. Ich hab da ja nach jeder Statusabfrage 500ms Pause, damit ich die codes aufschreiben kann.
Aber mal noch ne andere Frage, kann ich auch noch ne andere c-datei einbinden? Wenn ja, wie muss ich da dann die include machen, also mit <> oder mit "" ?
Gruß Bastian
|
BID = 699125
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Nein verdammt.
SO wie gezeigt, kann es nicht sein! Ein Widerstand geht von 5V auf SDA, einer auf SCL! Nix mit -5V und parallel!
Wir sind Techniker, wir arbeiten ordentlich.
Wie gesagt, spendiere jedem IC einen Keramik- oder Folienkondensator, dazu noch einen Elko 1µ-10µF. Sonst ist es klar, dass es nicht stabil läuft.
Mich interessiert, wie das AVR Studio den Compiler avr-gcc aufruft. Wenn du mit dieser Frage nichts anfangen kannst, hilft es, etwas zu googeln. Ich nutze das Studio nicht, ich kann es nicht wissen.
Zur letzen Frage:
Jein - reine C-Dateien bindet man nie ein. In C-Dateien ist nur die Implementierung enthalten (also der eigentliche Programmkode).
Die Datei wird dann völlig vom Rest getrennt kompiliert (in den sogenannten Objektkode). Andere Programmteile (z.B. main.c) werden später mit diesem Objektkode verlinkt. Damit die Symbole jedoch richtig aufgelöst und angewendet werden, verwendet man die Header - *.h-Dateien. Dort werden z.B. Funktionen oder Datentypen bekanntgemacht.
Die werden in main.c eingebunden.
Man kann es auch ohne expliziten Objektkode machen (das lohnt nur, wenn sich danach nichts mehr an der Bibliothek ändert):
avr-gcc -o main main.c code1.c code2.c ...
_________________
|
BID = 699127
Kleinspannung Urgestein
Beiträge: 13359 Wohnort: Tal der Ahnungslosen
|
Zitat :
DonComi hat am 29 Jun 2010 00:06 geschrieben :
|
Nix mit -5V und parallel!
|
Putz mal dein Display oder die Brille.
Von Weitem sieht das wirklich wie Minus aus,weil der "Querstrich" viel "fetter" ist.
Wenn du genau hinsiehst erkennst du,das dass Plus sein soll.
Kondis seh ich allerdings auch nirgendwo...
_________________
Manche Männer bemühen sich lebenslang, das Wesen einer Frau zu verstehen. Andere befassen sich mit weniger schwierigen Dingen z.B. der Relativitätstheorie.
(Albert Einstein)
|
BID = 699133
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Zitat :
| Putz mal dein Display oder die Brille. |
Danke für den Rat, war mal wieder nötig
@Terrorfreak
Sorry, hatte ich übersehen. Dennoch sind sie im Plan immer noch nicht korrekt verschaltet).
_________________
|