Hallo zusammen Irgendwie druckt wieder mal der Schuh :o) Versuche schon den ganzen Tag mein Gyro zum laufen zu bewegen, aber es will nicht so recht. Hier mal der Code. Es handelt sich um einen ADIS16250 von Analog Device. Programmieren tue ich auf einem MSP430 mit mspgcc und Eclipse. Dachte mir ich lese zuerst mal die Spannung aus, die kann ich gut überprüfen. Die Adresse für die Spannung ist 0x03 float ADIS16250_Read_spannung12bit(unsigned short address) { unsigned int result = 0; // Variable für Messwert float result_temp = 0; // Variable für Resultat definieren P6OUT &= 0xF7; // setze Chip select P6.3 low TXBUF0 = address; // Sende Adresse while ((IFG1 & UTXIFG0) == 0); // USART0 TX buffer ready? while ((IFG1 & URXIFG0) == 0); // USART0 RX buffer ready? char dummy = RXBUF0; // RXBUF0 auslesen (somit: löschen TXBUF0 = 0x00; // Sende Dummy Byte um SCLK zu generieren while ((IFG1 & UTXIFG0) == 0); // USART0 TX buffer ready? while ((IFG1 & URXIFG0) == 0); // USART0 RX buffer ready? dummy = RXBUF0; P6OUT |= 0x08; // setze chip select high delay(100); P6OUT &= 0xF7; // setze chip select low TXBUF0 = 0x00; // Sende Dummy Byte um SCLK zu generieren while ((IFG1 & UTXIFG0) == 0); // USART0 TX buffer ready? while ((IFG1 & URXIFG0) == 0); // USART0 RX buffer ready? result = RXBUF0; // erhalte MSB des Sensors result = result << 8; // Shifte MSB um 8 nach links TXBUF0 = 0x00; // Sende Dummy Byte um SCLK zu generieren while ((IFG1 & UTXIFG0) == 0); // USART0 TX buffer ready? while ((IFG1 & URXIFG0) == 0); // USART0 RX buffer ready? result |= RXBUF0; // erhalte LSB des Sensors P6OUT |= 0x08; // Setze P6.3 high (Chip Select ADIS16250 löschen) result &= 0x0FFF; // maskiere oberste 4 bit mit 0 result_temp = result; // resultat als float abspeichern result_temp = (result_temp * 0.001832); // Counts in Volt umrechnen return result_temp; } Hier dann noch wie ich den SPI initialisiert habe: void init_spi_0(void) { U0CTL |= SWRST; P3SEL = 0x0E; // Port 3 fur SPI verwenden U0CTL = CHAR + SYNC + MM; // SPI-Modus (8-bit, Master) U0TCTL = CKPL + SSEL0 + STC; // (polarity, ACLK, 3-wire) U0BR0 = 0x02; // SPICLK = ACLK/2 entspricht 500kHz U0BR1 = 0x00; U0MCTL = 0x00; ME1 |= USPIE0; // Modul aktivieren U0CTL &= ~SWRST; // SPI aktivieren } Ich bekomme ganz komische Werte Werte, meist 7.5….Volt. Das würde heissen es sind alles „1er“. Manchmal bekomme auch auch genau die Hälfte, 3.75….. und dann wieder 0. Schön immer in der selben Reihenfolge. Habe echt keinen Plan mehr wo ich noch suchen soll. Irgendwas verstehe ich an dem Datenblatt falsch. Wäre toll wenn ihr mir helfen könntet. Gruss reflection
Hat keiner eine Ahnung, habe gester noch den ganzen Abend weiterversucht, aber leider ohne Erfolg. Wäre echt toll wenn mir jemand weiterhelfen könnte Gruss reflection
nimm den folgenden Block raus P6OUT |= 0x08; // setze chip select high delay(100); P6OUT &= 0xF7; // setze chip select low Hat dein µC eine FPU ? Falls nicht lass die FLOAT weg und rechne mit Integer.
Das ist nur mal so für einen Test, also das mit dem Floating Point. Laut Datenblatt wird aber der CS dort kurz high gesetzt. Habe es auch schon ohne versucht, aber geht auch nicht. Ist das mit der Adresse so richtig? Denke da liegt irgendwo mein Fehler. (Vielleicht MSB,LSB verdreht oder so) oder setze ich die empfangenen Daten falsch zusammen? Habe noch einen Code für einen Pic im Netz gefunden. Da schiebt er die Adresse zuerst um 8 nach links. Wieso ist mir schleierhaft. Gruss reflection
Könnte es vielleicht an der Initialisierung des SPI liegen? Gruss reflection
Mich irritieren ein paar Sachen in deinem Code. Wieso betreibst du deinen SPI im 8bit Mode? Eigentlich solltest du 16 Bit verwenden. Dann überträgst du ganz zu Anfang die Adresse des gewünschten Registers, Ok. Danach liest du deinen Empfangsbuffer aus der etwas enthält was du nicht haben willst. Danach überträgst du abwechseld 0x00 und liest die Empfangenen Daten ein. 0x00 ist aber die Adresse des "Flash Memory Write Counter". An deiner Stelle würde ich zunächst also erstmal den SPI-Master im 16Bit Mode betreibnen. Und danach lass den Unsinn immer "Dummy"-Daten (die noch nichtmal dummy sind) zu übertragen, sondern sende immer deine Zieladresse und lese den Empfang ein. Dann hast du ab dem zweiten Empfangszyklus immer den gewünschten Wert. Gruß
Also ich sende lediglich 0x00 weil das so in einem Timingdiagramm im Datenblatt ist. (siehe S. 13/20) Hm, der TXBuf0 ist beim MSP430 doch nur 8Bit, oder sehe ich das jetzt falsch? Ist nicht so schön, ok, aber es sollte doch auch gehen wenn ich 2x8Bit sende, oder nicht? "Danach liest du deinen Empfangsbuffer aus der etwas enthält was du nicht haben willst"... Ja das sieht man auch im DAtenblatt, steht da, das es don't Care Bits sind. Denke mal für diese bekomme ich auch eine Antwort vom Gyro. Diesen lese ich dann in dummy ein um das Register des SPI wieder frei zu bekommen. Beim zweiten Druchlauf sende ich dann 0x00 um das MSB vom Sensor zu erhalten. Danach noch einmal 0x00 um das LSB vom Sensor zu erhalten. grrrr jetzt sehe ich das 0x00 das Flash Memory ist... Wieso machen die das dann im Datenblatt so? (S13/20)
> "Danach liest du deinen Empfangsbuffer aus der etwas enthält was du > nicht > haben willst"... > > Ja das sieht man auch im DAtenblatt, steht da, das es don't Care Bits > sind. Denke mal für diese bekomme ich auch eine Antwort vom Gyro. Diesen > lese ich dann in dummy ein um das Register des SPI wieder frei zu > bekommen. > Nein, damit meinte ich bloss, dass du erst mit dem zweiten Lesen die gewünschten Daten bekommst. > Beim zweiten Druchlauf sende ich dann 0x00 um das MSB vom Sensor zu > erhalten. Danach noch einmal 0x00 um das LSB vom Sensor zu erhalten. > grrrr jetzt sehe ich das 0x00 das Flash Memory ist... Wieso machen die > das dann im Datenblatt so? (S13/20) Im Datenblatt gehen sie davon aus, dass deine SPI-Schnittstelle im 16bit-Mode arbeitet. In dem Fall ist es egal was für einen Wert die hinteren 8 bit haben. Ob man Problemlos den Sensor über 8bit SPI ansprechen kann, das weiss ich nicht, in die Verlegenheit bin ich noch nicht gekommen. Da müsste sich jemand anderes zu Wort melden. Evtl. musst du dir sonst ne Softwarelösung basteln. Gruß
Ich habe glaube ich ein grundsätzliches Verständnisproblem: Ist das so korrekt? 1. Ich sende die Adresse z.B. 0x03 (8Bit) 2. Ich erhalte dann vom Gyro irgendwelche Daten (8Bit) die ich nicht benötige 3. Ich sende 8 Dummy Bits um Clock zu generieren und erhalte wieder Daten die ich nicht benötige (vom letzten Zugriff) 4. CS HIGH 5. CS LOW 6. Ich sende irgendetwas und bekomme das MSB des Registers welches ich unter Pkt. 1 angesprochen habe 7. Ich sende wieder irgendwas und bekomme das LSB des REgisters welches ich unter Pkt. 1 angesprochen habe. Wenn diese Vorgehensweise stimmen sollte muss es wohl an dem senden der 0x00 liegen, auch wenn ich das nicht nachvollziehen kann. Wenn ich 0x00 sende, hat das ja erst für den nächste 16Bit Wert eine Bedeutung oder nicht? Gruss reflection
Hallo zusammen Habe immer noch grosse Probleme das Ding zum laufen zu kriegen. Im Moment bekomme ich zwar Werte aber nur sch... Was ich nun aber mit erstaunen feststellen musste ist: Ich habe drei Gyros montiert, eines auf dem Hauptprint und je eins 90° dazu auf einen kleinen steckbaren Printchen. SPI Leitungen sind dennoch rel. kurz gehalten. sicher kleiner 5cm. Wenn ich jetzt nur schon eines dieser beiden einstecke, bleibt der uP einfach stehen. Also er initialiert alles inkl. SPI, gibt mir meinen Startup Screen aus und dann ist sense... bleibt einfach stehen das Teil. Stecke ich es aus, und schalte mein Gerät erneut ein läuft alles wunderbar (mit dem einen Gyro auf der Hauptplatine) Angeschlossen sind die beiden steckbaren genau gleich. Gemerkt habe ich es eigentlich wegen der SD Karte, die konnte ich auf einmal nicht mehr initialisieren. Als ich dann diesen Teil als Kommentar deklarierte passierte eben oben beschriebenes. Kann es sein, dass ich meinen SPI Bus vom MSP einfach "überlaste"? :o) Folgendes läuft an dem Bus: 1x 3-Achsen Beschleunigungsmesser VTI3000 1x SD-Karte 1x LCD (4x20 Zeichen Electronic Assembly blau/weiss) 3x oder besser gesagt halt im Moment 1x Gyro Analog Device ADIS16250 Ist das zu viel? Kann es sein dass die TrieState (oder wie man das schreibt) einfach zu niederohmig sind? Ich habe in meinen Leitungen übrigens keine Wiederstände drin, weder in Serie, noch Pull-Ups. Tja, der Print ist leider komplett SMD und die Gyros waren das einzige was ich vorher nicht testen konnte weil die doch einen stolzen Preis haben. Der Rest lief absolut problemlos, selbst auf einer mit Kabel verdrahteten Lochrasterkarte. Kann also fast keine Wiederstände mehr einfügen. Sch.............. :o) Hoffe es liegt vielleicht an was anderem, hat von Euch schonmal jemand so ein Prob gehabt? Gruss reflection
Antwort etwas spät, aber wir haben erst gestern den ADIS16251 in Betrieb genommen. Der folgende Codeausschnitt läuft für den ATMEGA128 von ATMEL mit WINAVR und eigenen libs, ist ein quick-shot, noch nicht optimiert, aber läuft. Unser Hauptproblem war die Initialisierung der SPI mit CPOL und CPHA, also Setup und Sample-Zeitpunkt. Erfahrungsbericht bisher: Momentan sind wir von der Genauigkeit des Gyros etwas enttäuscht, da er mit 14 Bit bei Einstellung 20°/s zu viel rauscht (ca. +/- 60°/min). Zusätzliche Mittelungen helfen natürlich, machen den Gyro aber zu langsam. Wir probieren gerade noch ein paar Sachen. Bei Interesse halte ich Euch gerne auf dem Laufenden.
1 | //----------------------------------------------------------
|
2 | //----------------------------------------------------------
|
3 | #define ADIS_GYRO_OUT 0x04
|
4 | #define ADIS_TEMP_OUT 0x0C
|
5 | #define ADIS_ANGL_OUT 0x0E
|
6 | #define ADIS_GYRO_SENS_AVG 0x38
|
7 | //-----------------------------------------------
|
8 | |
9 | |
10 | //-----------------------------------------------
|
11 | //general SPI-interface to ADIS-device
|
12 | //sends 16Bit OutData to MOSI
|
13 | //returs 16Bit data from MISO
|
14 | u16 ADIS_getsetData(u16 OutData) { |
15 | u16 Result=0; |
16 | u08 Count =0; |
17 | //
|
18 | CPUSYS_stopInt(); |
19 | cbi(PORTB,0); //Gyro CS |
20 | cbi(PORTB,0); |
21 | cbi(PORTB,0); |
22 | //
|
23 | OutData&=0xBFFF; //with !Bit6-Mask |
24 | //MSB
|
25 | SPDR =(OutData>>8); |
26 | Count =255; while((!(SPSR & (1<<SPIF)))&&(Count--)); |
27 | Result=(u16)SPDR<<8; |
28 | //LSB
|
29 | SPDR =OutData&0xFF; |
30 | Count =255; while((!(SPSR & (1<<SPIF)))&&(Count--)); |
31 | Result|= SPDR; |
32 | //
|
33 | sbi(PORTB,0); //Gyro CS |
34 | CPUSYS_enabInt(); |
35 | waituS(5); |
36 | //
|
37 | return Result; |
38 | }
|
39 | |
40 | u08 ADIS_OldAdr=0xFF; |
41 | //-----------------------------------------------
|
42 | //reads 16-Bit expression from ADIS-device
|
43 | //Param Address 6Bit-Address
|
44 | //returns Data at Address
|
45 | u16 ADIS_readWord(u08 Address) { |
46 | //
|
47 | u08 Adr=Address&0x3F; //filters read Address and LSB |
48 | if (ADIS_OldAdr!=Adr) { |
49 | //set Address before reading
|
50 | ADIS_getsetData((u16)Adr<<8); |
51 | ADIS_OldAdr=Adr; |
52 | }
|
53 | return ADIS_getsetData((u16)Adr<<8); |
54 | }
|
55 | |
56 | //-----------------------------------------------
|
57 | //writes 16-Bit Data to Address of ADIS-device
|
58 | void ADIS_writeWord(u08 Address, u16 Data) { |
59 | u08 Adr =Address&0x3E; //filters read Address and LSB |
60 | ADIS_OldAdr=Adr; |
61 | Adr |=0x80; //write |
62 | //
|
63 | ADIS_getsetData(((u16)Adr<<8)|(Data&0xFF)); |
64 | Adr++; |
65 | ADIS_getsetData(((u16)Adr<<8)|(Data>>8 )); |
66 | //
|
67 | }
|
68 | |
69 | //-----------------------------------------------
|
70 | //writes 16-Bit Data to Address of ADIS-device
|
71 | //with Readback before writing
|
72 | void ADIS_writeWordRB(u08 Address, u16 Data) { |
73 | if (ADIS_readWord(Address)!=Data) { |
74 | //only write if not already set (non volatile mem-parts)
|
75 | ADIS_writeWord(Address,Data); |
76 | }
|
77 | }
|
78 | |
79 | //-----------------------------------------------
|
80 | //returns 1, if new value was polled
|
81 | //returns Turnrate (0.1 °/min) in &Value
|
82 | u08 ADIS_readTurnrate(s16 *Value) { |
83 | u16 Test =ADIS_readWord(ADIS_GYRO_OUT); |
84 | s16 Result=(Test&0x3FFF); |
85 | Result =(Result<<2); //shift to Minus-Bit |
86 | //math-divide
|
87 | s32 Res=Result; |
88 | Res *= 2748; |
89 | Res /= 4000; |
90 | *Value = Res; |
91 | if (Test&0x8000) |
92 | return 1; |
93 | else
|
94 | return 0; |
95 | }
|
96 | |
97 | //-----------------------------------------------
|
98 | s16 ADIS_readTemperature(void) { |
99 | s16 Result=(ADIS_readWord(ADIS_TEMP_OUT)&0x3FFF); |
100 | //shift to Minus-Bit
|
101 | Result =(Result<<4); |
102 | //math-divide
|
103 | s32 Res=Result; |
104 | Res *= 1453; |
105 | Res /= 16000; |
106 | Res += 250; |
107 | return Res; |
108 | }
|
109 | |
110 | //-----------------------------------------------
|
111 | s16 ADIS_readCourse(void) { |
112 | s16 Result=(ADIS_readWord(ADIS_ANGL_OUT)&0x3FFF); |
113 | //shift to Minus-Bit
|
114 | //math-divide
|
115 | s32 Res=Result; |
116 | Res*= 3663; |
117 | Res/= 10000; |
118 | //
|
119 | return Res; |
120 | }
|
121 | |
122 | //----------------------------------------------------------
|
123 | //----------------------------------------------------------
|
124 | void ADIS_init(void) |
125 | {
|
126 | DDRB =0x07; |
127 | PORTB=0xFF; // Configure SPI-PINs |
128 | //
|
129 | DDRF =0xFF; //all output for LS245-TestBoard |
130 | PORTF=0x20; //only Dir high for LS245-TestBoard |
131 | //PORTF=0x60; //Dir/CS high
|
132 | //
|
133 | waitMS(10); //reset Gyro |
134 | sbi(PORTF,3); //Gyro-Reset up |
135 | waitMS(30); //reset Gyro |
136 | //
|
137 | //div 16
|
138 | SPSR= 0; |
139 | SPCR=_BV(SPE)|_BV(MSTR)|_BV(SPR0)|_BV(CPOL)|_BV(CPHA); |
140 | }
|
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.