Hallo Zusammen, ich bin auf der Suche nach einer reinen einfachen IIC Routine ohne Assembler für einen 8591(AD Wandler). Bisher habe ich die Routinen von Peter Fleury verwendet, die auch gut funktionieren. Zum besseren Verständnis für meine Schüler hätte ich aber gerne eine reine C-Routine ohne Assembler. Ich hab mir da zwar was gebastelt (vgl. Dateianhang) - funktioniert aber nicht. Vielen Dank carly
wird deine warteschleife vielleicht wegoptimiert? Ich glaube du must die variable als volatile deklarieren, damit der compiler meint, sie könnte sich auch innerhalb der schleife ändern...
vielen Dank für deinen Hinweis "volatile" hats aber leider auch nicht gebracht; carly
Hallo Carly Vielleicht kannst Du mit meinen I2C Routinen etwas anfangen..? (Siehe Attachement) Die Funktionen sollte gut überschaubar sein. MfG Peter
wenn du schon <util/delay.h> include'st, warum benutzt du dann nicht auch die entsprechenden Funktionen ??
1 | void i2c_warte(void) |
2 | {
|
3 | _delay_us(10); // 1µs ist ein Takt bei 1Mhz... |
4 | }
|
5 | //oder auch
|
6 | #define I2WAIT _delay_us(10);
|
7 | |
8 | // und das
|
9 | sbi(PORTB,SDA); // SDA-Leitung ist jetzt Eingang |
10 | // .. stimmt irgendwie nicht ;)
|
(Außerdem mag ich weder sbi()/cbi(), noch mehrere Anweisungen pro zeile!!, aber das ist meine Meinung ;) ) hth. jörg ps.: Hast du mal in der Codesammlung nach twi* oder i2c* gesucht, da gibts doch bestimmt C-Routinen
sbi/cbi ist deprecated (veraltet!). http://www.nongnu.org/avr-libc/user-manual/deprecated.html PS: Zumindest in der AVR-libc..
> sbi/cbi ist deprecated
Er hat ja seine eigene Implementierung drübergeschrieben.
Ich finde die Wahl trotzdem nicht glücklich, gerade auch für Lernende.
Wenn's schon unbedingt in Makros verwurschtelt werden muss, dann
wären SETBIT und CLEARBIT allemal aussagekräftiger. Eigentlich ist
es aber sinnvoller, gleich noch einen Schritt weiter zu gehen und eine
Art HAL daraus zu machen (hardware abstraction layer), sodass z. B.
die Startbedingung dann aussieht wie:
1 | void i2c_start(void) |
2 | {
|
3 | SDA_HIGH; i2c_warte(); |
4 | SCL_HIGH; i2c_warte(); |
5 | SDA_LOW; i2c_warte(); |
6 | SCL_LOW; i2c_warte(); |
7 | }
|
Ansonsten Zustimmung dazu, dass man delays nicht ,,nach Gutdünken'' zimmern sollte, entweder einen Timer oder die Funktionen aus <util/delay.h> bzw. auch <util/delay_basic.h> nehmen. Das ist zwar wieder inline asm, aber in diesem Falle vom Hersteller des Systems, damit transparent für den Nutzer. Man kann sogar so weit gehen, den Lernenden an Hand des aus der ,,privaten'' Zählschleife generierten (oder besser: nicht generierten) Codes zu zeigen, warum man genau sowas nicht machen darf und an welchen Stellen der C-Standard dem Compiler Freiraum für seine Optimierungen gegeben hat.
1 | if (Daten >= 128) |
2 | sbi(PORTB,SDA); |
3 | |
4 | else
|
5 | cbi(PORTB,SDA); |
6 | |
7 | i2c_warte(); |
8 | |
9 | sbi(PORTB,SCL); |
10 | Daten <<= 1; |
11 | |
12 | i2c_warte(); |
13 | cbi(PORTB,SCL); i2c_warte(); |
14 | }
|
Ich finde das >= 128 gefährlich. Je nach Datentyp kann das zu Problemen führen nach dem Shift. Besser & 128 verwenden.
> Ich finde das >= 128 gefährlich. > Je nach Datentyp kann das zu Problemen führen nach dem Shift. Stimmt, der Typ von Daten (die ganz Zeile glaskugelanwerf "i2c_schreibe(unsigned char Daten)") fehlt Es sieht außerdem unlogisch aus und Lernende müssen jedes Mal zwischen Bit- und Dezimaldarstellung hin- und herdenken Ich würde da:
1 | if (Daten & (1<<7)) |
2 | ...
|
nehmen (funktioniert eben auch mit signed-Typen) hth. Jörg
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.