Hallo, ich will einen DAC ansteuern (MAX528) dieser verfügt über ein SPI
Interface.
Ich habe ihn noch nicht hier, möchte aber schon etwas Software
vorbereiten.
Als uC kommt ein Mega 16 (später 8) zum Einsatz.
den eingebauten SPI will ich nicht nutzen, da ich ihn beliebig an einen
Port anschließen will.
Darum habe ich mir gedacht eine Funktion zu schreiben.
klappt das so? oder soll ich doch den eingebauten benutzen? Nutzt der
eingebaute das SS Signal als CS?
Danke schonmal, hier der Code:
void softspi(unsigned int data)
{
unsigned int i=0;
PORTD.1=0; //CS=low übertragung anfang
for (i=16;i<0;i--)
{
PORTD.2=0; //clock low
PORTD.3 = data & (1<<i);
PORTD.2 = 1; //Clock bit rising edge
}
PORTD.1=1; //CS high, übertragung beendet
return;
}
Hi Sven,
so sieht man sich wieder ;-))
Zwei Punkte würde ich ändern:
Die Portnamen per #define in den Header schreiben. Dann musst Du nicht
jedesmal das ganze Programm ändern, wenn Du die Portpins wirklich
tauschen willst.
PORTD.3 = data & (1<<i);
Hier musst Du bei jedem Bit bis zu 16* schieben. Fixer geht es so:
if (data & 1){
PIN_SPI_DATA = 1;
else{
PIN_SPI_DATA = 0;
}
data = data >> 1;
Sieht zwar länger aus, ist aber im Programmcode kürzer und schneller.
Wenn es ganz optimal sein soll, dann kannst Du i auch noch als 8 Bit
definieren.
Den eingebauten musst Du nur benutzen, wenn Du die Geschwindigkeit
wirklich brauchst.
Viele Grüße, Stefan
Hallo Stefan,
Dann war meine Idee doch nicht so falsch..
Aber dein Programm verstehe ich nicht ganz..
Du prüfst ja erst ob das lsb von data =1 ist shiftest dann rechts dann
bist du doch beim MSB??
Ich meine doch das MSB muss zuerst rein...
Data besteht bei mir aus adresse + wert
vielleicht erklärst du mir deine optimierung noch etwas. Danke.
Sorry. War von LSB first ausgegangen. Ich ahbe aber auch kein Datenblatt
angeschaut :-(
Mit MSB first muss es so aussehen:
if (data & 0x8000){ /* Wenn MSB-Bit gesetzt */
PIN_SPI_DATA = 1; /* Data-Pin auf 1 schalten, */
else{
PIN_SPI_DATA = 0; /* ansonsten auf 0 */
}
data = data << 1; /* das Ganze nach Links schieben, dann */
/* ist das MSB-1 beim nächstenmal das MSB */
/* Das geht solange (16*), bis das LSB */
/* nach links als MSB aufgerückt ist */
Insgesamt wird 16* geshiftet. Bei Dir sinds pro 16Bit-Ausgabe 128*
Ist aber im Prinzip auch kein Problem.
Viel wichtiger finde ich die symbolische Darstellung der Portpins.
PIN_SPI_DATA (oder ähnlich) ist auch ohne Kommentar klar, bei PORTD.3
weisst Du in 14 Tagen nicht mehr, was es soll, ohne im Schaltplan zu
schauen.
Stefan
JA, mit dem benennen hast du recht. habe es auch schon geändert..
Also packe ich deinen Code in die for schleife. schalte vorher und
nachher die clock um..muss man warten? oder kann ich das so laufen
lassen?
Ich verstehe das Datenblatt zumindest so das zuerst das MSB kommt.. ist
etwas knapp gehalten..
Danke schonmal. Sven
>Also packe ich deinen Code in die for schleife. schalte vorher und>nachher die clock um..muss man warten? oder kann ich das so laufen>lassen?
Im Datenblatt steht je 80ns für Low- und High-Clock. Die wirst Du nicht
unterschreiten, denke ich. Dazu müssten die Assembler-Befehle zum
setzen und löschen von clk direkt hintereinander kommen.
>Ich verstehe das Datenblatt zumindest so das zuerst das MSB kommt..
ist
>etwas knapp gehalten..
Hast Du völlig Recht. Ich habe einfach nicht geschaut.
Es gibt aber schlimmere Datenblätter ... vor allem bei Chips aus Japan.
Die scheinen ganz anders zu denken ;-)
Stefan
@Ccrazy horse:
Sieht hübsch aus, und weil es nur mit 8-Bit-Werten rechnet, ist es
sicher sehr nah am Optimum.
for (loop=0,mask=0x80;loop<8;loop++, mask=mask>>1)
Erstmal war ich in dieser Zeile etwas irritiert: das Komma in der
for-Schleife hat mich stutzig gemacht, also habe ich mal bei K&R
nachgeschaut: Es gibt einen Komma-Operator!
Wieder was gelernt, danke.
Stefan