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.
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
booleani2c_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
returntrue;
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.
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.
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.