Hallo zusammen, ich versuche gerade, eine SoftI2C Lib (http://homepage.hispeed.ch/peterfleury/avr-software.html bzw. direkt: http://homepage.hispeed.ch/peterfleury/i2cmaster.zip) so umzuschreiben, dass ich das ganze mehrfach (mit verschiedenen Pins) verwenden kann. Von Haus aus erlaubt die Library lediglich einen SoftI2C-Bus. Leider bin ich keine große ASM-Leuchte und bin daher ein wenig ratlos: Im Quelltext werden die SDA- und SCL-Pins durch #define-Statemens gesetzt. Ich müsste das ganze jedoch durch Variablen ersetzen, um dynamisch auf die korrekten Pins zugreifen zu können. Vermutlich ist die Sache mit etwas Erfahrung schnell gegessen, aber bevor ich jetzt für dieses Detail von GCC auf ASM umsteige, wollte ich doch lieber kurz nachfragen, ob jemand vllt eine Idee hat? Gute Nacht Sonovice
Sonovice schrieb: > (mit verschiedenen Pins) An verschiedenen Ports? > Vermutlich ist die Sache mit etwas Erfahrung schnell gegessen Vermutlich nicht... Hier mal ein Ausschnitt:
1 | ;***** Adapt these SCA and SCL port and pin definition to your target !! |
2 | #define SDA 4 // SDA Port D, Pin 4 |
3 | #define SCL 5 // SCL Port D, Pin 5 |
4 | #define SDA_PORT PORTD // SDA Port D |
5 | #define SCL_PORT PORTD // SCL Port D |
6 | ;****** |
7 | |
8 | #define SDA_DDR (_SFR_IO_ADDR(SDA_PORT) - 1) |
9 | #define SCL_DDR (_SFR_IO_ADDR(SCL_PORT) - 1) |
10 | #define SDA_OUT _SFR_IO_ADDR(SDA_PORT) |
11 | #define SCL_OUT _SFR_IO_ADDR(SCL_PORT) |
12 | #define SDA_IN (_SFR_IO_ADDR(SDA_PORT) - 2) |
13 | #define SCL_IN (_SFR_IO_ADDR(SCL_PORT) - 2) |
14 | |
15 | : |
16 | : |
17 | |
18 | i2c_init: |
19 | cbi SDA_DDR,SDA ;release SDA |
20 | cbi SCL_DDR,SCL ;release SCL |
21 | cbi SDA_OUT,SDA |
22 | cbi SCL_OUT,SCL |
23 | ret |
Die Zugriffe erfolgen über IO-Bit-Befehle, deren Parameter zur Übersetzungszeit festgelegt sind. Das zu ändern ist eine Operation am offenen Herzen. Insbesondere das zeitliche Verhalten wird sich durch die dynamische Auswahl drastisch ändern. Denn dann können nicht mehr die schnellen cbi/sbi Befehle genommen werden, sondern es geht langsam über ld/st Befehle (bei denen zusätzlich noch der vorige Inhalt der X(YZ)-Register gesichert und wiederhergestellt werden muss) und Read-Modify-Write Abläufe, bei denen zudem Interrupts gesperrt werden müssen... > so umzuschreiben, dass ich das ganze mehrfach (mit verschiedenen Pins) > verwenden kann. Wozu brauchst du mehrere Soft-I2C? Der Prozessor kann sowieso immer nur 1 gleichzeitig bedienen... Wenn du viele gleiche Slaves anschließen willst, die aber nur 1 umschaltbare Adressleitung haben, dann könntest du diese Leitung evtl. als "Chip-Select" verwenden, und nur dem einen Slave, den du ansprechen willst, die richtige Adresse aufschalten.
:
Bearbeitet durch Moderator
Herzlichen Dank für deine Antwort. Lothar Miller schrieb: > An verschiedenen Ports? Ja, leider. > Hier mal ein Ausschnitt: > #define SDA_DDR (_SFR_IO_ADDR(SDA_PORT) - 1) _SFR_IO_ADDR hat doch sicherlich ein C-Äquivalent, oder? > i2c_init: > cbi SDA_DDR,SDA ;release SDA > cbi SCL_DDR,SCL ;release SCL > cbi SDA_OUT,SDA > cbi SCL_OUT,SCL > ret > Die Zugriffe erfolgen über IO-Bit-Befehle, deren Parameter zur > Übersetzungszeit festgelegt sind. Dazu habe ich eine Frage. Am Ende jeder Funktion stehen ein paar Zeilen, die offensichtlich die Register auf andere "Variablen" mappen:
1 | boolean i2c_init(void) |
2 | {
|
3 | __asm__ __volatile__ |
4 | (" cbi %[SDADDR],%[SDAPIN] ;release SDA \n\t" |
5 | " cbi %[SCLDDR],%[SCLPIN] ;release SCL \n\t" |
6 | " cbi %[SDAOUT],%[SDAPIN] ;clear SDA output value \n\t" |
7 | " cbi %[SCLOUT],%[SCLPIN] ;clear SCL output value \n\t" |
8 | " clr r24 ;set return value to false \n\t" |
9 | " clr r25 ;set return value to false \n\t" |
10 | " sbis %[SDAIN],%[SDAPIN] ;check for SDA high\n\t" |
11 | " ret ;if low return with false \n\t" |
12 | " sbis %[SCLIN],%[SCLPIN] ;check for SCL high \n\t" |
13 | " ret ;if low return with false \n\t" |
14 | " ldi r24,1 ;set return value to true \n\t" |
15 | " ret "
|
16 | : : |
17 | [SCLDDR] "I" (SCL_DDR), [SCLPIN] "I" (SCL_PIN), |
18 | [SCLIN] "I" (SCL_IN), [SCLOUT] "I" (SCL_OUT), |
19 | [SDADDR] "I" (SDA_DDR), [SDAPIN] "I" (SDA_PIN), |
20 | [SDAIN] "I" (SDA_IN), [SDAOUT] "I" (SDA_OUT)); |
21 | return true; |
22 | }
|
Wäre es nicht möglich, SCL_DDR etc. als Variablen zu betrachten und entsprechend unten anzugeben? > Wozu brauchst du mehrere Soft-I2C? Der Prozessor kann sowieso immer nur > 1 gleichzeitig bedienen... Ich entwickle gerade (unter C) ein Framework für den Anschluss verschiedener Sensoren an meine Platine. Der Clou ist, dass alle benutzbaren Pins frei in ihrer Funktion sind, sodass man sich erst in der Software um die "Pinbelegung" kümmern muss und nicht schon auf Hardwareebene. Dass immer nur ein Gerät zur gleichen Zeit bedient werden kann, ist mir klar. Bei mehreren Sensoren wäre es dennoch ungemein praktisch und eleganter, als 2 große Multiplexer für SDA bzw. SCL zu benutzen.
Sonovice schrieb: > Ich entwickle gerade (unter C) ein Framework für den Anschluss > verschiedener Sensoren an meine Platine Für solch eine Aufgabe reicht es aber nicht einfach Code aus anderen Quellen zusammenzukopieren. Es wird dir also nichts anderes übrig bleiben, als den Code zu verstehen und dir idealerweise eine C-Zugriffsfunktion mit inline ASM zu erzeugen, oder gleich in C zu schreiben. Für den (statischen) Ansatz könnte man im AVR Assembler Macros benutzen, aber auch da: Vorher muss der Code verstanden werden.
:
Bearbeitet durch User
Sonovice schrieb: > _SFR_IO_ADDR hat doch sicherlich ein C-Äquivalent, oder? Das ist irgend eine Konstante. Deren Wert findest du im Abschnitt "Register Description" und/oder "Register Summary" des Datenblatts. > Wäre es nicht möglich, SCL_DDR etc. als Variablen zu betrachten und > entsprechend unten anzugeben? Nein, weil die Parameter von cbi/sbi/sbis/sbic zum Übersetzungszeitpunkt statisch sein müssen. Denn die werden ja fest als Maschinencode ins Flash assembliert.
:
Bearbeitet durch Moderator
Lothar Miller schrieb: > Nein, weil die Parameter von cbi/sbi/sbis/sbic zum > Übersetzungszeitpunkt statisch sein müssen. Denn die werden ja fest > als Maschinencode ins Flash assembliert. Okay, wusste nicht, dass das "Mapping" auch vom Präprozessor verarbeitet wird. Läubi .. schrieb: > Für solch eine Aufgabe reicht es aber nicht einfach Code aus anderen > Quellen zusammenzukopieren. Das ist mir klar, aber ich ging davon aus, dass es bei diesem gezielten Problem kein großer Akt mit der Anpassung wäre. So kann man sich irren. Ich werde wohl doch meine eigene Lösung komplett in C schreiben, die Geschwindigkeit sollte eigentlich ausreichen, dafür ist kein ASM nötig. Dennoch danke euch beiden, jetzt bin ich schlauer.
Sonovice schrieb: > Ich werde wohl doch meine eigene Lösung komplett in C schreiben Sieh dir den Beitrag "AVR: Pointer IO-Register" und den Beitrag "AVR Port und Pin in Array ablegen und dann per Schleife drauf zugreifen" an.
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.