Hallo! Hab ein Problem mit meinem Mikrocontroller. Ich kann ganz normal 8 Bit rausschreiben über die SPI, hab das Ganze über einen Logikanalysator aufgenommen und ausgewertet. Bei dem Versuch, 16 Bit über die SPI rauszuschreiben, schreibt der Mikrocontroller trotzdem nur 8 Bit raus. Wo liegt mein Fehler? µC: PIC18F452, mit CCS Compiler #fuses HS, NOWDT, NOBROWNOUT, NOLVP #use delay(clock=20000000) #use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7) #use standard_io(d) #use spi(FORCE_HW, BITS=16, MSB_FIRST) unsigned int8 i=0; unsigned int8 j=0; #define CS PIN_E0 void main() { enable_interrupts(GLOBAL); setup_spi(spi_master | spi_l_to_h | spi_clk_div_16); delay_ms(100); while (1) { for(i = 200; i <=255; i++) { for(j=0;j<=50;j++) { printf("\n\r j=%lu",j); output_low(CS); spi_write(0xaa); //spi_write(0xaaaa); //-->GEHT NICHT! output_high(CS); delay_ms(10); } delay_ms(100); } } }
> //spi_write(0xaaaa); //-->GEHT NICHT!
Wie ist denn "spi_write" deklariert? Was macht die Funktion? Und kann
die SPI-Hardware Deines µCs überhaupt 16-Bit-Zugriffe ausführen?
Ich denk mal, weil spi_write (wie auch immer das definiert ist) nur 8 Bit haben will. Einfach 2x 8 Bit schicken oder die Funktion ändern.
kann spi_write nicht nur 8-Bit (char,uchar), oder wie sieht der Prototyp aus. Ansonsten machst halt spi_write(0xaa); spi_write(0xaa); EDIT: Verdammt, zu langsam. Immerhin alle die gleiche Idee.
spi_write wird halt nur 1 Byte übertragen. UNd wenn du versuchst dort 1 Mb hineinzustopfen, wird es trotzdem nur 1 Byte übertragen. Aber man kann spi_write ja auch 2 mal aufrufen. Einmal mit dem High-Byte und einmal mit dem Low-Byte. Oder auch umgekehrt: Zuerst Low-Byte, dann High-Byte. Je nachdem wie es die Gegenstelle haben will.
Rufus t. Firefly schrieb: >> //spi_write(0xaaaa); //-->GEHT NICHT! > > > Wie ist denn "spi_write" deklariert? Was macht die Funktion? Und kann > die SPI-Hardware Deines µCs überhaupt 16-Bit-Zugriffe ausführen? spi_write ist ein Standardbefehl des CCS. Die Funktion schreibt den Wert raus,welchen man ihr angibt. Ob das die Hardware kann,weiß ich jetzt nicht,aber ich bin auf nen andren weg gekommen,ich glaub,dass es die Software nicht zulässt mehr rauszuschreiben, da der spi_write Befehl angeblich nur ein Byte rausschreiben soll.
MeinerEiner schrieb: > Ich denk mal, weil spi_write (wie auch immer das definiert ist) nur 8 > Bit haben will. Einfach 2x 8 Bit schicken oder die Funktion ändern. Danke, ist richtig!
Timmo H. schrieb: > kann spi_write nicht nur 8-Bit (char,uchar), oder wie sieht der Prototyp > aus. Ansonsten machst halt > spi_write(0xaa); > spi_write(0xaa); > > EDIT: Verdammt, zu langsam. Immerhin alle die gleiche Idee. Danke, aber da stellt sich bei mir nur die nächste Frage: Macht es dem Baustein etwas aus? Oder achtet der Baustein nur darauf ob SS auf High oder Low ist? Der Baustein der angesprochen werden soll ist der 25LC320 (EEPROM) von Microchip.
Ja wie oben schon geschrieben: spi_write(x) schreibt nur 8-Bit über SPI. Möglichkeit:
1 | void spi_writeBytes(unsigned int8 u8Anzahl, unsigned int8 *pu8Bytes) |
2 | {
|
3 | unsigned int8 u8Index; |
4 | |
5 | for(u8Index = 0; u8Index < u8Anzahl; u8Index++) |
6 | {
|
7 | spi_write(*(pu8Bytes+u8Anzahl)); |
8 | }
|
9 | }
|
Nicht getestet !
Dem chip ist es egal. Nu musst nur das Chip Select richtig setzen. Also: setze Chipselect; spi_write(0xaa); spi_write(0xaa); lösche Chipselet;
Gast schrieb: > Dem chip ist es egal. Nu musst nur das Chip Select richtig setzen. > > Also: > > setze Chipselect; > spi_write(0xaa); > spi_write(0xaa); > lösche Chipselet; Ja genau, so habe ich es auch gemeint :-) Dankeschön für die Hilfe. Wo ich aber jetzt schon im Forum aktiv bin, hätte ich die nächste Frage: Einen Baustein zu beschreiben, der 11 Bit verlangt, wird wohl für mich nur zu Fuß möglich sein oder?
Gast schrieb: > Um welchen Baustein handelt es sich denn? Es handelt sich um den AD5292, und Korrektur: 10 Bits. Zuerst werden 6 Steuerbits (Ersten zwei sind nutzlos,also 4 Steuerbits) rausgeschrieben, danach zehn Datenbits.
Hab das Dtaenblatt eben überflogen: Der wird mit 16-Bit gefüttert. Die ersten 2 Bits haben dabei keine Funktion.
Nachtrag: Zitat aus dem Datenblatt: "The AD5291/AD5292 shift register is 16 bits wide (see Figure 2). The 16-bit input word consists of two unused bits (set to 0), followed by four control bits, and 10 RDAC data bits."
Gast schrieb: > Hab das Dtaenblatt eben überflogen: > Der wird mit 16-Bit gefüttert. Die ersten 2 Bits haben dabei keine > Funktion. JA Mit 10 Bits mein ich nur die Datenbits, hab mich etwas umständlich artikuliert. Natürlich sind es insgesamt 16 Bit. Wird aber nur zu Fuß möglich sein, oder habt ihr eine Idee?
Aber du hast doch oben schon 16Bit geschrieben? Wo liegt denn jetzt das Problem?
Nach wie vor: > setze Chipselect; > spi_write(0xaa); > spi_write(0xaa); > lösche Chipselet; Du musst nur den ersten und zweiten Wert entsprechend vorbereiten, ist easy. Nimm eine uint16_t variable, und setze sie auf zu übertragenden wert (10 Bit). Das ganze shiftest du 6 bits nach links, verORst das mit deinen Controlbits, und gut. Anschliessend macht du spi_writes() für das lo und und hi byte.
Nicht falsch verstehen, der obrige Quellcode hat mit dem AD5292 nichts zu tun!!! Das ist ein ganz unabhängiges Thema!
Also so, dass zum Beispiel im Higher Byte schon ein Teil der Daten steht. D.h. zwei Datenbits werden schon im ersten Byte mitgesendet? 2 aussagelose Bits + 4 Steuerbits + 2 Datenbits = 1 Byte Rest im Lower Byte?
Puh... Da stellt sich mir schon die nächste Frage. Ich möchte die zehn Datenbits aber als Dezimalwert rausschreiben. Jetzt stellt sich ja die Frage, wie kann ich den Dezimalwert in einen Binärwert umwandeln, sodass ich die Bits shiften kann? Versteht Ihr was ich meine? Wie würde so eine Realisierung aussehen?
Heinz Wichtelmann (heinz_wichtelmann) schrieb:
> Versteht Ihr was ich meine?
nein...im µC sind alle Zahlen binär, was anderes gibt es nicht
Ja OK, aber, möchte ich zum Beispiel den Wert "126d", also 1111110b rausschreiben, wie realisiere ich dann das shiften? Sodass eben die zwei MSB schon mit dem Higher Byte gesendet werden?
...gleichzeitig sind alles zahlen hexadezimal, was anderes gibt es nicht! und sie sind auch "dezimal", was anderes gibt es nicht! ok..was damit gesagt werden soll, ist: nur die DARSTELLUNG entscheidet, ob bei du der AUSGABE einer Zahl ihre Binäre, Dezimale, oder Hexadezimale oder wasauchimmer REPRESENTATION siehst. Aber das sind absolutes Bascis.. bevor du irgendwas mit Programmierung anfängst, noch dazu in C solltest du dich zumindest ein bischen einlesen.
uint16_t Wert = 328; uint8_t HighByte = ( Wert >> 8 ); uint8_t LowByte = Wert; Bist du sicher, dass du vorher nicht ein wenig Basics am PC üben solltest?
uint16_t a = 126; // = 1111110b inhalt von a : 000000001111110b um 6 stellen shiften: a = (a<<6); // 001111110000000b jetzt noch die control-bits um 2 verschoben verORen //controlbits = 0101b a = a | (0b0101 << 2); ergebnis: 0b001111110010100 oder anders ausgedrückt : 00111111 0010100 ^hi ^lo
huch...wenn du meinen fehler findest, hast du's verstanden ;-)
Nein warum? Ich bin mir dessen bewusst, dass die Zahlenformate in jeglicher Form implementiert werden können. Hab nur gedacht, zum shiften muss man es vielleicht in eine Art umwandeln etc. Dass wenn ich einen Int16 verwende die Dezimalzahl immer "16" Bit hat, ist mir bewusst! Ich dachte nicht, dass mein so "einfach" shiften kann, aber DANKE für die Information!!
Passt irgendwie nicht ganz mit der Bitanzahl zusammen?
uint16_t a = 126; // = 1111110b inhalt von a : 00000000001111110b um 6 stellen shiften: a = (a<<3); // 0000011111100000b jetzt noch die control-bits verschieben //controlbits = 0101b a = a | (0b0101 << 13); ergebnis: 0b0001010001111110 oder anders ausgedrückt : 00010100 01111110 ^hi ^lo
Heinz Wichtelmann (heinz_wichtelmann) schrieb: > uint16_t a = 126; // = 1111110b > > inhalt von a : 00000000001111110b > > um 6 stellen shiften: > > a = (a<<3); // 0000011111100000b Genau. Drum schreibt man 3, wenn man um 6 Stellen schieben muss :-) (Geschenkt, ist nur ein Tippfehler) > > jetzt noch die control-bits verschieben > > //controlbits = 0101b > > a = a | (0b0101 << 13); Warum 13? Du hast 10 Datenbits. Wenn die Kontrollbits links von diesen 10 Bits sein sollen, dann wird man wohl um 10 Bits verschieben. > ergebnis: > > 0b0001010001111110 Aber nur wenn du vom Originalen a ausgehst :-)
uint16_t a = 126; // = 1111110b inhalt von a : 0000000001111110b um 3 stellen shiften: a = (a<<3); // 0000001111110000b jetzt noch die control-bits verschieben //controlbits = 0101b a = a | (0b0101 << 10); ergebnis: 0b0001011111110000b oder anders ausgedrückt : 00010111 11110000 ^hi ^lo Jetzt hab ich mal genau nachgezählt^^
Bleibt nur noch die Frage, warum du a (welches ja offenbar den Wert darstellt) überhaupt verschiebst :-) Dein Datenblattt fordert von dir das du sendest 00ccccdddddddddd c Controlbits d Datenbits 0 0-Bits gesendet in 2 Paketen (aka Bytes) 00ccccdd dddddddd Die komplette 16 Bit Zahl entsteht also durch total = ( control << 10 ) | Daten; und die Bytes kriegst du HighByte = total >> 8; LowByte = total; (Noch die richtigen Datentypen eingesetzt und ev. sollte man bei den Datenwerten noch dafür sorgen, dass da nicht zufällig noch ein 1-Bit über dem 10. Datenbit existiert. Aber das wars dann)
Stimmt, hier stellt sich die Frage warum überhaupt verschieben? Es würde so ganz gut klappen. Und jetzt habe ich mir noch etwas überlegt, wozu das Ganze? Ich kann ja ganz einfach den Higher Byte rausschreiben und die zwei MSB mit Null ergänzen (Gut, dann hab ich nichtmehr so viel Bit für Daten zur Verfügung, aber das ist mir egal!) In das restliche Lower Byte schreibe ich meinen Wert ganz einfach als unsigned int8 und fertig. Ist meine Überlegung richtig oder? Blöd wäre es nur, würde ich die vollen 10 Bit wollen. Denn was wäre, wenn ich eine Zahl eingebe, wo die letzten MSB 1 sind? Z.B.: 1000000000b = 512d. Dann müsste ich eine Abfrage dazuprogrammieren, bei welchen Zahlen die MSB eins sind, und diese dann verarbeiten. Ist aber auch irgendwie blöd oder?
Oder so gehts natürlich auch, wie du das beschrieben hast!! Super, danke für die Hilfe! :-)
öh... ok,ich nehm alles zurück, ich hab das Datenblatt nämlich nicht gelesen und ging von einer anderer Reihenfolge aus. Entschuldigung.
Heinz Wichtelmann (heinz_wichtelmann) schrieb: > Und jetzt habe ich mir noch etwas überlegt, wozu das Ganze? > Ich kann ja ganz einfach den Higher Byte rausschreiben und die zwei MSB > mit Null ergänzen (Gut, dann hab ich nichtmehr so viel Bit für Daten zur > Verfügung, aber das ist mir egal!) > In das restliche Lower Byte schreibe ich meinen Wert ganz einfach als > unsigned int8 und fertig. > Ist meine Überlegung richtig oder? Wenn du nach 6 Stunden einen derartigen Vorschlag bringst, sollte man eigentlich als Helfer einen Schreikrampf bekommen. 6 Stunden! Für einen 3-Zeiler! Bei dem der Compiler die meiste Arbeit macht! Aaaaaaargh
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.