Hallo, Ich lass den MSP430F2013 als SPI Slave laufen und teste mit einem "Aardvark" SPI analyzer. Ich möchte gerne 16bit übertragen, was allerdings zu gewissen Problemen führt. Ich hab das Programm aus den Beispielen umgeschrieben und habe mir diese auch bereits angesehen und alle Register überprüft. Mein Code ist im Anhang, es geschieht folgendes: SPI Master sendet: B6 C3 und empfängt: 11 11 (so wie es laut Init sein soll) Slave geht in ISR, in die else anweisung. In USISR steht nun: 0xABCD (soweit auch richtig) Nun sendet Master erneut: B6 C3. Master empfängt aber: CD B6 (CD= unteres Byte wird als oberes Byte gesendet; B6= Oberes Byte der gerade empfangenen Nachricht werden als unteres Byte gesendet) Weder verstehe ich, warum die B6 mitgesendet wird, noch verstehe ich wo das "AB" hin ist. Das ist einfach verschwunden?! Wie geht das? Das sind doch nur zwei Schieberegister, wo immer lustig im Kreis geschoben wir oder nicht??! Ich hab mir den Spaß auch auf dem Oszilloskop angesehen. Da kommen alle Nachrichten genauso über die Leitung, wie sie hier auch beschrieben werden. Der Analyzer macht seine Arbeit also Richtig, das Problem muss im MSP430 liegen, welcher hier die oberen 8Bit des Register unterschlägt :( Kann mir jemand helfen, bzw. mir das erklären? Gruß Techniggo PS. erste upload ist veraltet, kann den upload leider nicht weg editieren.
:
Bearbeitet durch User
Niko H. schrieb: > In USISR steht nun: 0xABCD (soweit auch richtig) Wenn B6C3 gesendet wurde, ist ABCD richtig? Wie stellst Du fest, was in USISR steht? Siehst Du Dir das etwas in einem Debugger an, oder gibst Du diesen Wert irgendwohin aus?
Naja in der ISR geht das Programm ja in die "else" Anweisung und schreibt da "ABCD" ins USISR. Ganz genau, ich stelle das im Debugger fest. Ich benutze IAR Kickstart, da kann ich mir an der Seite sämtliche USI register anzeigen lassen, unter anderem auch das USISR :) PS: direkt nach dem senden, also am start der ISR steht übrigens auch tatsächlich "B6 C3" im USISR, so wie es soll. "ABCD" steht da erst, nachdem die entsprechende Zeiele durchlaufen ist... Sorry, war unklar ausgedrückt :)
:
Bearbeitet durch User
Beim Betrachten von Hardwareregistern mit dem Debugger musst Du vorsichtig sein; denn das Auslesen ist ein Vorgang, der nicht unbedingt beliebig oft wiederholt werden kann. Gerade bei UARTs und vergleichbaren Peripheriebausteinen löst das Auslesen das Empfangen weiterer Daten aus -- so daß nur exakt ein Lesezugriff pro ISR-Durchlauf statthaft ist. Kopiere den gelesenen Wert in irgendeine Variable und sieh Dir die im Debugger an, aber nie direkt die Hardwareregister.
Interessanter Hinweis, wusste ich nicht. Habe jetzt je eine unsigned Int Variable vor und hinter dem "USISR=0xABCD" eingefügt. Es stehen aber dennoch die gleichen Werte drinn wie auch im Hardware Register, also vorher "B6C3", nachher "ABCD".
Niko H. schrieb: > Slave geht in ISR, in die else anweisung. In USISR steht nun: 0xABCD > (soweit auch richtig)
1 | else
|
2 | {
|
3 | USISRH = 0xBC; |
4 | USISRL = 0xAD; |
Wo siehst du da 0xABCD ?
Oh man, peinlich. Hier kommt natürlich die richtige Datei, hatte ausversehen ne alte Version oben geladen, die wird auch direkt editiert!
Niko H. schrieb: > Slave geht in ISR, in die else anweisung. In USISR steht nun: 0xABCD > (soweit auch richtig) > > Nun sendet Master erneut: B6 C3. Master empfängt aber: CD B6 (CD= > unteres Byte wird als oberes Byte gesendet; B6= Oberes Byte der gerade > empfangenen Nachricht werden als unteres Byte gesendet) > > Weder verstehe ich, warum die B6 mitgesendet wird, noch verstehe ich wo > das "AB" hin ist. Das ist einfach verschwunden?! Wie geht das? Das sind Mach mal das Ganze 2-3 Mal hintereinander, ohne die Werte in USISR zu ändern.
Also nicht USISR=ABCD schreiben? Ohne diese Anweisung bekomme ich am Master aufgenommen sende B6 C3 empfange C3 B6 sende B6 C3 empfange C3 B6 sende B6 C3 empfange C3 B6 sende B6 C3 empfange C3 B6 sende B6 C3 empfange C3 B6 Das ist beliebig oft reproduzierbar. Der oben geschilderte Fall ist übrigens ebenso reproduzierbar.
Niko H. schrieb: > sende B6 C3 > empfange C3 B6 > sende B6 C3 > empfange C3 B6 > > Das ist beliebig oft reproduzierbar. Der oben geschilderte Fall ist > übrigens ebenso reproduzierbar. Und ? LoByte von zuletzt gesendetem Word + HiByte von eben gesendetem Word. Was ist daran falsch ? Wahrscheinlich ist Register shadowed.
:
Bearbeitet durch User
Was ist shadowed? gespiegelt? also umgedreht vermutlich richtig? Hatte ich auch schon die Vermutung, aber wenn ich etwas ins Register schreibe, wo geht denn dann das Highbyte hin? Beziehungsweise, was wirklich interessant wäre: Wie bekomme ich das hin dann 16bit vernünftig zu übertragen?
Niko H. schrieb: > Was ist shadowed? gespiegelt? also umgedreht vermutlich richtig? Hatte > ich auch schon die Vermutung, aber wenn ich etwas ins Register schreibe, > wo geht denn dann das Highbyte hin? Beziehungsweise, was wirklich > interessant wäre: Wie bekomme ich das hin dann 16bit vernünftig zu > übertragen? Du hast nach dem Empfang einen neuen Wert ins Register geschrieben, also 0xABCD. Wenn du diesen Wert gleich abschickst, ist es OK. Tust du aber nicht, sondern wartest auf Empfang. Da USI annimmt, dass das HiByte von vorhergehendem Empfang schon zurückgesendet würde, wird USISRH zu USISRL, und danach wird USISRH auch zurückgesendet, neuer Wert wird ins USISRL übernommen. EDIT: War noch nie in einem Kontroller drin, weiss auch nicht, ob das so wie oben beschrieben geht, nur meine Vermutung. ;-D Schreibe jetzt 0xCDAB ins Register.
:
Bearbeitet durch User
Ja, das leuchtet soweit ein.... Aaaaber: Ich muss doch auf Empfang warten, da mein Slave nicht von alleine Senden kann (Senden und Empfangen geht ja gleichzeitig übers selbe Register oder?!) Ich verstehe immernoch nicht ganz die Logik, wie ich demnach 16bit versenden können sollte... Oder muss ich High und Low Byte komplett von einander getrennt übertragen? Wozu gibts dann ein 16 bit Register und nicht direkt nur ein 8Bit register?
Niko H. schrieb: > Ich verstehe immernoch nicht ganz die Logik, wie ich demnach 16bit > versenden können sollte... Oder muss ich High und Low Byte komplett von > einander getrennt übertragen? Wozu gibts dann ein 16 bit Register und > nicht direkt nur ein 8Bit register? Schau doch mal ins DaBla. Vielleicht hat USI nur Byte Access.
:
Bearbeitet durch User
1 | // USI interrupt service routine
|
2 | __interrupt void universal_serial_interface(void) |
3 | {
|
4 | if (0x59AA == USISR) // <--- Lesezugriff auf USISR |
5 | {
|
6 | // SD16CCTL0 &= ~ SD16IFG; // clear ADC Interrupt Flag
|
7 | // SD16CCTL0 |= SD16SC; // AD Wandler starten
|
8 | // while (!(SD16CCTL0 & SD16IFG)); // AD Wandlung fertig ?
|
9 | // USICNT = 16;
|
10 | USISR = 0x3456; // <---- Schreibzugriff auf USISR |
11 | }
|
12 | else
|
13 | {
|
14 | empfangen = USISR; // <--- Lesezugriff auf USISR |
15 | USISR = 0xABCD; // <---- Schreibzugriff auf USISR |
16 | senden = USISR; // <---- Lesezugriff auf USISR |
17 | USICNT = 16; |
18 | }
|
19 | }
|
Du greifst hier gleich dreimal lesend auf USISR zu, außer, wenn 0x59AA empfangen wurde. Das solltest Du ändern.
@ Marc: DaBla und User Guide hab ich schon zig mal alles zu SPI und USI durchgeackert, hätte da nie irgendwo was entdeckt, dass es nur Byteweise geht. @Rufus: Die beiden Lesezugriffe mit "empfangen" und "senden" habe ich nur sporadisch eingefügt, weil du meintest ich sollte die Register mal in Variablen abspeichern und nicht im Debugger anschauen. Wenn die diese beiden Zeilen rausnehme, verhält sich der Controller immernoch gleich, und das bei je einem Lese- und einem Schreibzugriff, egal was er empfängt. Naja also wenn der Controller das nicht hinbekommt, dann frage ich mich ernsthaft, was man mit einer Schnittstelle soll, über die man weder lesen, noch schreiben kann ;)
Niko H. schrieb: > DaBla und User Guide hab ich schon zig mal alles zu SPI und USI > durchgeackert, hätte da nie irgendwo was entdeckt, dass es nur Byteweise > geht. Table 15. Peripherals With Byte Access
1 | USI USI control 0 USICTL0 078h |
2 | (MSP430F20x2 and MSP430F20x3) USI control 1 USICTL1 079h |
3 | USI clock control USICKCTL 07Ah |
4 | USI bit counter USICNT 07Bh |
5 | USI shift register USISR 07Ch |
Also, ich habe es nur einmal.
Marc Vesely schrieb: > Peripherals With Byte Access Das bedeutet, daß es auch byteweise geht. Wäre es anders, wäre eine Registerdefinition für einen 16-Bit-Zugriff irgendwie ziemlich daneben. Im "'F20xx Family User's Guide" (slau144j) wird auf Seite 405 in Tabelle 14-2 USISR als Register mit "Word Access" beschrieben. Und natürlich in 14-1 USISRL und USISRH als Register mit "Byte Access".
Schau mal in den User Guide: 14.2.3.3 USISR Operation The 16-bit USISR is made up of two 8-bit registers, USISRL and USISRH. Control bit USI16B selects the number of bits of USISR that are used for data transmit and receive. When USI16B = 0, only the lower 8 bits, USISRL, are used.
Ok, das heißt also das ist nur ein fake Register, und mann kann tatsächlich immer nur 1Byte aufeinmal senden?
Betrachtet man den User's Guide, so fällt dort das hier auf: SPI Slave Mode Once all bits are received, the data must be read from USISR and new data loaded into USISR before the next clock edge from the master. In a typical application, after receiving data, the USI software will read the USISR register, write new data to USISR to be transmitted, and enable the USI module for the next transfer by writing the number of bits to be transferred to USICNTx. (Hervorhebung von mir) Wenn man das mit dem Code aus der ISR vergleicht, fehlt der letzte Schritt:
1 | // USI interrupt service routine
|
2 | __interrupt void universal_serial_interface(void) |
3 | {
|
4 | if (0x59AA == USISR) // <--- Lesezugriff auf USISR |
5 | {
|
6 | // SD16CCTL0 &= ~ SD16IFG; // clear ADC Interrupt Flag
|
7 | // SD16CCTL0 |= SD16SC; // AD Wandler starten
|
8 | // while (!(SD16CCTL0 & SD16IFG)); // AD Wandlung fertig ?
|
9 | // USICNT = 16;
|
10 | USISR = 0x3456; // <---- Schreibzugriff auf USISR |
11 | }
|
12 | else
|
13 | {
|
14 | empfangen = USISR; // <--- Lesezugriff auf USISR |
15 | USISR = 0xABCD; // <---- Schreibzugriff auf USISR |
16 | senden = USISR; // <---- Lesezugriff auf USISR |
17 | USICNT = 16; // enable |
18 | }
|
19 | }
|
Die Routine sollte so umgestaltet werden:
1 | // USI interrupt service routine
|
2 | __interrupt void universal_serial_interface(void) |
3 | {
|
4 | empfangen = USISR; // <-- Lesezugriff USISR |
5 | |
6 | if (empfangen == 0x59AA) |
7 | senden = 0x3456; |
8 | else
|
9 | senden = 0xABCD; |
10 | |
11 | USISR = senden; // <-- Schreibzugriff USISR |
12 | USICNT = 16; // enable |
13 | }
|
:
Bearbeitet durch User
Habe ich auch alles ausprobiert, trotzdem noch der gleiche Fehler... Scheinbar hilft es alles nichts, dann muss ich wohl leider mit 8bit Übertragung leben, denn das funktioniert ja immerhin...
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.