Forum: Mikrocontroller und Digitale Elektronik Soft SPI


von Sven Müller (Gast)


Lesenswert?

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;



}

von Stefan Kleinwort (Gast)


Lesenswert?

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

von Stefan Kleinwort (Gast)


Lesenswert?

P.S.:
Ich habe es frei runtergeschrieben, ohne zu testen. Also betrachte es
kritisch ;-)

Stefan

von Sven Müller (Gast)


Lesenswert?

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.

von Stefan Kleinwort (Gast)


Lesenswert?

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

von Sven Müller (Gast)


Lesenswert?

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

von Stefan Kleinwort (Gast)


Lesenswert?

>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

von Sven Müller (Gast)


Lesenswert?

Gut, dank dir. Dann geh ich jetzt beruhigt schlafen..

Sven

von crazy horse (Gast)


Lesenswert?

ob optimal, weiss ich nicht, jedenfalls funktionierts prima mit einem
2313/MAX528 und MAX192 an einem Software-SPI.

void write_spi (unsigned char data_out){       //msb first
unsigned char loop, mask;
for (loop=0,mask=0x80;loop<8;loop++, mask=mask>>1)
    {sclk=0;
    if (data_out & mask) mosi=1;
     else mosi=0;
     sclk=1;
    }
sclk=0;
}

void write_max528 (unsigned char adress, unsigned char data){
dac_cs=0;
write_spi(adress);
write_spi(data);
dac_cs=1;
watchdog=0;
}

von Sven Müller (Gast)


Lesenswert?

Ok, das Beispiel von crazy scheint mir der optimale, praktische Weg zu
sein. danke dir!

Sven

von Stefan Kleinwort (Gast)


Lesenswert?

@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

von Sven Müller (Gast)


Lesenswert?

Ja, mit dem Komma das kannte ich auch noch nicht..

werds mal ausprobieren wenn die samples da sind..

Sven

von Roman (Gast)


Lesenswert?

crazy horse, danke! :) ich blicke bei der for schleife nicht ganz durch 
aber es funzt!

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
Noch kein Account? Hier anmelden.