Hi Folgendes ich arbeite mit dem ATMEGA128 und benutze das SPI. Nun benötige ich aber zum programmieren eines DAC eine weitere SPI Schnittstelle. Da ich hier immer nur 16 Bit an Daten an den DAC schicken muss nehm ich also 3 I/Os - eine CLK, ein CS und ein DataOut. Soweit so gut aber irgendwie krieg ich die 16 Bit nicht einzeln auf den DataOut Pin, bzw. rausgeschiftet. Arbeite zudem mit CVAVR also wenn dann in C bidde. dachte eigentlich es würde so funktionieren: #define SDOUT PORTB.7 ... unsigned char control; for(j=0;j<8;j++) { ... SDOUT= (control>>(7-j)); ... } ... Schonmal danke im vorraus.
Ein Codefragment. Vielleicht hilft's: void softspi_W(uint8_t data) { uint8_t i; i = 0x80; do { if (data & i) SPIPORT |= (1<<SPIMOSI); else SPIPORT &= ~(1<<SPIMOSI); pulse_sck(); i>>=1; } while (i); }
In Deiner Schleife shiftest Du einerseits nur ein Byte, andererseits solltest Du -sicherheitshalber- noch eine verANDung mit 1 vornehmen: SDOUT= (control>>(7-j)) & 1; Mit Takt könnte das dann so aussehen: #define SDOUT PORTB.7 #define CLOCK PORTB.6 #define CHIPSEL PORTB.5 ... unsigned char control; CHIPSEL = 0; // active-Low-CS for (j = 0; j < 8; j++) { ... CLOCK = 0; SDOUT = (control >> (7 - j)) & 1; CLOCK = 1; ... } CHIPSEL = 1; .. Du musst Dir noch Gedanken über die Polarität des Taktsignales machen und wann in Relation zu den Daten das Taktsignal umschalten soll. Außerdem musst Du überlegen, ob Du das LSB (wie in Deinem Quelltext) oder das MSB als erstes übertragen willst; es gibt beide Varianten. Wie hier vor einiger Zeit bereits diskutiert wurde, ist das Konstrukt mit dem Shiftoperator ein relativ ineffizientes, da der AVR über keinen sog. "Barrel Shifter" verfügt. Besser wäre daher eine Variante wie unsigned char control; unsigned char temp; temp = control; CHIPSEL = 0; // active-Low-CS for (j = 0; j < 8; j++) { ... CLOCK = 0; SDOUT = temp & 1; temp >>= 1; // oder temp /= 2; CLOCK = 1; ... } CHIPSEL = 1;
Nachtrag: Das ganze für 16-Bit-SPI: unsigned short control; unsigned short temp; temp = control; CHIPSEL = 0; // active-Low-CS for (j = 0; j < 16; j++) { ... CLOCK = 0; SDOUT = temp & 1; temp >>= 1; // oder temp /= 2; CLOCK = 1; ... } CHIPSEL = 1;
Das ich nur ein Byte shifte und somit nur 8 Bit und nicht 16 war mir schon klar. Und ob bei steigender oder fallender Flanke übernomen werden soll auch, deshalb ja die vielen ... "pünktchen" ;-) Wollte nur nicht den ganzen Code posten. Das einzige was mir theoretisach fehlte war die Ausmaskierung mit & 1 Und ein wenig umgestrickt damit ich das MSB zuerst sende und nicht das LSB sieht das ganze jetzt so aus und funzt auch: void WriteDAC(unsigned char control, unsigned char wert) { unsigned char j= 0; unsigned char temp_control, temp_wert; cs = 0; // active-Low-CS for (j=0;j<16;j++) { sclk = 1; if(j<8) { temp_control = control; temp_control >>= (7-j); sdin = temp_control & 1; } else { temp_wert= wert; temp_wert >>= (15-j); sdin = temp_wert & 1; } sclk = 0; } cs = 1; } In diesem Sinne dankeschön für die Mühe
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.