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
P.S.: Ich habe es frei runtergeschrieben, ohne zu testen. Also betrachte es kritisch ;-) 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
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; }
Ok, das Beispiel von crazy scheint mir der optimale, praktische Weg zu sein. danke dir! Sven
@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
Ja, mit dem Komma das kannte ich auch noch nicht.. werds mal ausprobieren wenn die samples da sind.. Sven
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.