Hallo, ich versuche seit Tagen, die Kommunikation mit einem ADXL345 Beschleunigungssensor herzustellen. Leider ohne Erfolg. Mitlerweile beschränke ich mich auf den Versuch, einfach nur die Device ID auszulesen. Aber selbst das gelingt nicht. Zuerst habe ich versucht, die AVR interne USI Schnittstelle zu verwenden, als ich nach zwei Tagen immer noch keine Daten vom ADXL345 erhielt, habe ich die Kommunikation vollständig in Software umgesetzt, um auszuschließen, dass ich bei der Verwendung der USI einen Fehler mache. Leider bietet sich mir exakt das gleiche Bild wie mit der USI. Habe Euch im Anhang mal die Timing Diagramme angehängt: 1. Timing Diagramm aus dem Datenblatt 2. Timing Diagramm meines Programms 1 3. Timing Diagramm meines Programms 2 Die Zustände in Diagramm 2 und 3 wechseln sich in regelmäßigen Abständen ab. Der Sensor ist per 4 Wire SPI angeschlossen. Die Zeiten(s. Datenblatt S. 17): insbesondere: -tDELAY (CS falling edge to SCLK falling edge) -tQUIET (SCLK rising edge to CS rising edge) -tSETUP (SDI valid before SCLK rising edge) werden eingehalten(delays im Programm). Link zum Datenblatt des ADXL345: http://www.analog.com/static/imported-files/data_sheets/ADXL345.pdf Ab Seite 15 geht die Beschreibung der SPI Kommunikation los. Viele Grüße und für jeden hilfreichen Beitrag Danke im Vorraus! Stefan
Sehe gerade, dass in den Diagrammen teilweise die Beschriftung fehlt bzw. durcheinander sind. Die Signale von oben nach unten: - ~CS(active low) - SCL - SDI - SDO Gruß Stefan
Stimmt der SPI mode? Muesste nach den Bildchen "steigende CLK aktiv" sein. ist das auch in Deiner Software so eingestellt?
>Leider ohne Erfolg. Geht's auch genauer? >als ich nach zwei Tagen immer noch keine Daten vom ADXL345 >erhielt, Deine Oszillogramme zeigen das Gegenteil... Was steht nach der Übertragung eines Bytes im SPI RX Datenregister?
Gartenzwergleiche schrieb: > Was steht nach der Übertragung eines Bytes im > SPI RX Datenregister? Lese ich mitlerweile gar nicht mehr aus, da die Oszillogramme ja schon Murks zeigen!? Ich sende ja immer nur: Befehl lesen (R = 1, Bit 7), einfache Übertragung(MB = 0, Bit 6) und Adresse 0x00 (Bits 5:0), so dass ja eigentlich nur die Device ID ausgegeben werden muss. Diese lautet 11100101 Danke unf Gruß Stefan
Gartenzwergleiche schrieb: >>Leider ohne Erfolg. > > Geht's auch genauer? Ich erhalte keine gültgen Daten, da ich nur die Device ID auslese und diese nicht stimmt(siehe Beitrag oben). Gruß Stefan
Nabend, im Bildanhang mal die Zeichenfolge die ich erhalte. Der wechsel zwischen 0x00 und 0xE6 ist mir nicht ganz klar, wie dieser Zustande kommt. Genau so wenig aber auch, warum 0xE6 und nicht 0xE5 (Device ID) Hier der Code
1 | #include <avr/io.h> |
2 | |
3 | //#define F_CPU 8000000UL
|
4 | #define F_CPU 3686400UL
|
5 | |
6 | #include <util/delay.h> |
7 | #include "usi_isp.c" |
8 | |
9 | void uart_init(void) |
10 | {
|
11 | #define BAUD 9600
|
12 | #include <util/setbaud.h> |
13 | /* Set baud rate */
|
14 | UBRRH = UBRRH_VALUE; |
15 | UBRRL = UBRRL_VALUE; |
16 | #if USE_2X
|
17 | UCSRA |= (1 << U2X); |
18 | #else
|
19 | UCSRA &= ~(1 << U2X); |
20 | #endif
|
21 | // Enable receiver and transmitter
|
22 | UCSRB = (1<<RXEN)|(1<<TXEN); |
23 | // Set frame format: 8data,
|
24 | UCSRC = (3<<UCSZ0); |
25 | |
26 | }
|
27 | |
28 | |
29 | int main (void) |
30 | {
|
31 | |
32 | uart_init(); |
33 | spi_init(); |
34 | |
35 | while (1) |
36 | {
|
37 | UDR = spi_read_byte(0x00); |
38 | _delay_ms(100); |
39 | }
|
40 | |
41 | return 0; |
42 | }
|
Datei usi_isp.c
1 | #include <avr/io.h> |
2 | #include <util/delay.h> |
3 | |
4 | //#define SPI_CLK 12500 // spi clock
|
5 | |
6 | #define CS_PIN PB4 // chip select pin
|
7 | #define CS_REG PORTB // chip select register
|
8 | #define SPI_DEVICE_T_DELAY 1
|
9 | |
10 | // SPI port and pin definitions.
|
11 | |
12 | #define SPI_PORT PORTB //!< SPI port output register.
|
13 | #define SPI_PIN_REG PINB //!< SPI port input register.
|
14 | #define SPI_DIR_REG DDRB //!< SPI port direction register.
|
15 | #define SPI_CLOCK_PIN PB7 //!< SPI clock I/O pin.
|
16 | #define SPI_DATAIN_PIN PB5 //!< SPI data input pin.
|
17 | #define SPI_DATAOUT_PIN PB6 //!< SPI data output pin.
|
18 | #define SPI_CS_PIN PB4 //!< SPI Cock Select pin.
|
19 | |
20 | |
21 | void spi_init(){ |
22 | // outputs
|
23 | SPI_DIR_REG |= ( 1<< SPI_CLOCK_PIN | 1<< SPI_CS_PIN ); |
24 | // inputs
|
25 | // when 4 wire mode is choosen, define DI- and DO- pin mode here
|
26 | }
|
27 | |
28 | |
29 | void spi_chip_enable() |
30 | {
|
31 | CS_REG &= ~(1<<CS_PIN); // ~CS = 0 -> enable slave device; |
32 | _delay_us(10); //später durch _delay_cycles ersetzen |
33 | }
|
34 | |
35 | void spi_chip_disable() |
36 | {
|
37 | // _delay_us(SPI_DEVICE_T_DELAY); // see ADXL345 Data Sheet Figure 37 to 39
|
38 | _delay_us(10); //später durch _delay_cycles ersetzen! |
39 | CS_REG |= (1<<CS_PIN); // ~CS = 1 -> disable slave device; |
40 | }
|
41 | |
42 | |
43 | //**************************************************************
|
44 | //***********[ READ BYTE FROM SPI without USI ]*****************
|
45 | //**************************************************************
|
46 | |
47 | unsigned char spi_read_byte( unsigned char address ){ |
48 | |
49 | unsigned char cnt, data; |
50 | |
51 | //******************** transmitt byte *********************************
|
52 | |
53 | // configure IO pin functions (not nessesary for 4-wire spi but for 3 wire mode)
|
54 | SPI_DIR_REG |= ( 1<< SPI_DATAOUT_PIN); //!< USI port direction register |
55 | |
56 | // 0x80: read(single byte) mode
|
57 | data = ( 0x80 | (address & 0x3F) ); |
58 | cnt = 0; |
59 | |
60 | spi_chip_enable(); |
61 | |
62 | if( ( (data << cnt) & 0x80 ) ) |
63 | SPI_PORT |= (1<< SPI_DATAOUT_PIN); // |
64 | else
|
65 | SPI_PORT &= ~(1<< SPI_DATAOUT_PIN); // |
66 | |
67 | _delay_ms(1); // t_delay (ADXL345) |
68 | |
69 | // generate SLK
|
70 | SPI_PORT &= ~(1<< SPI_CLOCK_PIN); // |
71 | _delay_ms(20); // _delay_us(1000000/(2*SPI_CLK)); |
72 | SPI_PORT |= (1<< SPI_CLOCK_PIN); // |
73 | _delay_ms(20); // _delay_us(1000000/(2*SPI_CLK)); |
74 | cnt++; |
75 | |
76 | do{ |
77 | // transmitt data
|
78 | if( ( (data << cnt) & 0x80 ) ) |
79 | SPI_PORT |= (1<< SPI_DATAOUT_PIN); // |
80 | else
|
81 | SPI_PORT &= ~(1<< SPI_DATAOUT_PIN); // |
82 | |
83 | // generate SLK
|
84 | SPI_PORT &= ~(1<< SPI_CLOCK_PIN); // |
85 | _delay_ms(20); // _delay_us(1000000/(2*SPI_CLK)); |
86 | SPI_PORT |= (1<< SPI_CLOCK_PIN); // |
87 | _delay_ms(20); // _delay_us(1000000/(2*SPI_CLK)); |
88 | |
89 | cnt++; |
90 | |
91 | }while ( cnt < 8 ); // stop when 8bits are transmitted |
92 | |
93 | //******************** receive byte *******************************
|
94 | |
95 | // configure IO pin functions (not nessesary for 4-wire spi but for 3 wire mode)
|
96 | SPI_DIR_REG &= ~( 1<< SPI_DATAIN_PIN); // |
97 | SPI_PORT |= ( 1<< SPI_DATAIN_PIN); |
98 | cnt = 0; |
99 | data = 0; |
100 | |
101 | do{ |
102 | // generate SLK
|
103 | SPI_PORT &= ~(1<< SPI_CLOCK_PIN); |
104 | _delay_ms(20); // _delay_us(1000000/(2*SPI_CLK)); |
105 | SPI_PORT |= (1<< SPI_CLOCK_PIN); // |
106 | |
107 | // read data from pin DI (sample on rising edge)
|
108 | if( SPI_PIN_REG & ( 1<< SPI_DATAIN_PIN) ) |
109 | data |= ( 1 << cnt ); |
110 | |
111 | _delay_ms(20); // _delay_us(1000000/(2*SPI_CLK)); |
112 | |
113 | cnt++; |
114 | }while ( cnt < 8 ); // stop when 8 bits are transmitted |
115 | |
116 | |
117 | spi_chip_disable(); |
118 | |
119 | return data; |
120 | }
|
Einen Schaltplan müsste ich noch erstellen, ist ein fertiges Modul aus dem Netz http://hobbycomponents.com/other/431-gy-291-adxl345-triple-axis-accelerometer SDI, SDA, SCL, CS liegen jedenfalls über Pullups an Vcc Grüße Stefan
Stefan schrieb: > nicht ganz klar, wie dieser Zustande kommt. Genau > so wenig aber auch, warum 0xE6 und nicht 0xE5 (Device ID) ausgeben wird.
Guten Abend, durch Zufall habe ich die Schaltung zum Laufen bekommen. Der Zufall sieht so aus, dass ich dem ADXL345 die GND leitung durchtrennt habe. Er verfügt jetzt also nicht mehr über GND, sondern nur SDA,SDO, SLC, und CS. Habe gerade nochmal alle Spannungspegel überprüft und die Qualität mit dem Oszilloskop untersucht. Ergebnis, alles einwandfrei. Da breche ich mir seit jetzt bald einer Woche einen ab und verstehe die Welt nicht mehr und jetzt entferne ich durch zufall GND und alles geht??? Kann sich das jemand logisch erklären oder hat schonmal ein Ähnliches Problem gehabt? Viele Grüße Stefan
Stefan schrieb: > durch Zufall habe ich die Schaltung zum Laufen bekommen. Der Zufall > sieht so aus, dass ich dem ADXL345 die GND leitung durchtrennt habe. Er > verfügt jetzt also nicht mehr über GND, sondern nur SDA,SDO, SLC, und > CS. Klingt nicht gut. Das Ding hat ja 3 GND-Pins. Schaltplan (original!) wäre interessant. Besonders die Verschaltung von Pin 3 und 11.
Wie gesagt, ist ein fertiges Modul gewesen. http://hobbycomponents.com/other/431-gy-291-adxl345-triple-axis-accelerometer Werde mich morgen in Ruhe mal dran setzen und das Modul untersuchen und einen Schaltplan erstellen. Wobei die Dinger ja in Tausenden verkauft werden. Würde daher einen schwerwiegenden Fehler im Schaltplan ausschließen. Es kann ja eigentlich nur ein Bauteil- oder Lötstellendefekt sein. Gruß Stefan
Wie erzeugst Du die Beriebsspannung für den AVR und wie hoch ist die? Abblockkondensatoren drin? Der Schaltplan wäre auch sehr aufschlussreich.
Detlef Kunz schrieb: > Wie erzeugst Du die Beriebsspannung für den AVR und wie hoch ist die? > Abblockkondensatoren drin? Der Schaltplan wäre auch sehr > aufschlussreich. Der Avr steckt in einem STK500 und die Bertriebsspannung erzeuge ich über den boardeigenen VTarget Generator. Habs zwischendrin aber auch über externe Spannung versucht, hat auch nicht geholfen. Gru0 Stefan
Stefan schrieb: > Detlef Kunz schrieb: >> Wie erzeugst Du die Beriebsspannung für den AVR und wie hoch ist die? >> Abblockkondensatoren drin? Der Schaltplan wäre auch sehr >> aufschlussreich. > > Der Avr steckt in einem STK500 und die Bertriebsspannung erzeuge ich > über den boardeigenen VTarget Generator. Habs zwischendrin aber auch > über externe Spannung versucht, hat auch nicht geholfen. > > Gru0 > Stefan Nagut, aber wie hoch ist die Betriebsspannung, weil mit 5V wäre das ganz schlecht. Du musst den AVR mit 3.3v betreiben, weil der ADXL auch mit 3.3v arbeitet (die kleine Platine hat einen eigenen Spannungsregler).
adenin schrieb: > Du musst den AVR mit 3.3v betreiben, weil der ADXL auch mit 3.3v > arbeitet (die kleine Platine hat einen eigenen Spannungsregler). Betreibe den AVR mit 3.6V Gruß Stefan
Es ist auf alle Fälle keine gute Idee, wenn die Spannung an den AVR-Pins größer als die Versorgungsspannung des ADXL ist.
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.