Hallo, das hier ist mein erster Beitrag hier, deswegen stelle ich mich mal kurz vor. Bin Philipp, 21 Jahre, aus Aachen. Studiere hier Elektrotechnik in der Vertiefung Automatisierungs- und Antriebstechnik. Leider sind µCs in unserem Studium nie erwähnt worden und da ich mir ein Temperaturgeregeltes Wasserbad bauen möchte habe ich das zum Anlass genommen mich selbst damit zu beschäftigen. Ich bastele nun schon seit ca. 4 Wochen mit einem Atmega8 herum den ich mit AVR Studio in C programmiere. PWM Ausgabe, Anschluss eines LCD Displays und den internen ADC habe ich bereits erfolgreich benutzen können. Nun habe ich mir bei Reichelt einen MCP3551 bestellt (22 Bit ADC Wandler) und 2 Tage lang das Internet nach Theorie zum Anschluss und zur SPI Schnittstelle sowie das Datenblatt des ICs durchsucht. Dabei habe ich einige Dinge verstanden, vieles ist aber noch nicht ganz klar. Am wichtigsten: Wie Schließe ich den ADC überhaupt an den Atmega8 an? Einige ähnliche ADCs besitzen 4 Pins zur SPI Kommunikation (Clock, DataIN DataOut und ChipSelect). Dem 3551 fehlt jedoch ein DataIn Pin. Bleibt dann am AVR der MOSI unbelegt? Das ist erstmal meine Hauptfrage, ich denke es werden aber noch viele weitere folgen bis ich das Teil am laufen habe. Gruß, Philipp
Philipp K. schrieb: > Wie Schließe ich den ADC überhaupt an den Atmega8 an? Frei -- MOSI SDO -- MISO SCK -- SCK CS -- Irgendein IO mit externem Pullup
:
Bearbeitet durch User
Ich habe jetzt den CS Pin an PB0 gehängt, den ich vor dem Empfangen auf low ziehe. (Im Dattenblatt ist Dokumentiert, dass dadurch der ADC anfängt Daten zu senden) Hier mal mein Code: #include <avr/io.h> #include "lcd-routines.h" #include <util/delay.h> char byte1, byte2, byte3; void receiveSPI() { char dontcarebyte=0b10101010; PORTB &= ~(1<<PB0); SPDR = dontcarebyte; while(!(SPSR & (1<<SPIF))); byte1 = SPDR; SPDR = dontcarebyte; while(!(SPSR & (1<<SPIF))); byte2 = SPDR; SPDR = dontcarebyte; while(!(SPSR & (1<<SPIF))); byte3 = SPDR; PORTB |= (1<<PB0); } void InitSPI(void) { DDRB = (1<<PB4)|(1<<PB5) | (1<<PB7) | (1<<PB0); PORTB |= (1<<PB0); SPCR = ( (1<<SPE)|(1<<MSTR) | (1<<SPR1) |(1<<SPR0)); } int main(void) { lcd_init(); InitSPI(); while (1) { lcd_clear(); receiveSPI(); lcd_data(byte1); lcd_data(byte2); lcd_data(byte3); _delay_ms(10); } return 0; } Natürlich funktioniert es nicht, war auch erstmal nur ein Versuch. Auf dem LCD Display sind für ein paar sekunden Wilde Zeichen zu lesen, dann gar nichts mehr. Hat Jemand einen Tipp der mich in eine richtigere Richtung bringt? Ist es überhaupt sinnvoll die 22 Bit in 3 Bytes zu teilen?
Versuch es mal so:
1 | PORTB &= ~(1<<PB0); // Start conversion |
2 | while (1) |
3 | {
|
4 | if(!(PINB & (1 << PINB4))) // If data ready |
5 | {
|
6 | lcd_clear(); |
7 | receiveSPI(); |
8 | lcd_data(byte1); lcd_data(byte2); lcd_data(byte3); |
9 | |
10 | PORTB &= ~(1<<PB0); // Start conversion |
11 | }
|
12 | }
|
> Wilde Zeichen Was macht lcd_data()? Wenn sie nur das Byte 1:1 ans LCD schickt, wirst du nix sinnvolles lesen, da die Bytes als ASCII interpretiert werden. > Ist es überhaupt sinnvoll die 22 Bit in 3 Bytes zu teilen? Ich würde einen int24_t oder wenn es das nicht gibt eine int23_t verwenden P.S. In Zukunft bitte die C-Formatierung verwenden
1 | [c]C-Code[/c] |
:
Bearbeitet durch User
Danke schonmal für die Antwort! Ja das mit dem ACSII Code ist mir auch schon eingefallen, hier mal der verbesserte Code
1 | #include <avr/io.h> |
2 | #include "lcd-routines.h" |
3 | #include <util/delay.h> |
4 | #include <stdlib.h> |
5 | |
6 | uint8_t byte1, byte2, byte3; |
7 | char Buffer[20]; |
8 | |
9 | |
10 | void receiveSPI() |
11 | |
12 | {
|
13 | |
14 | PORTB &= ~(1<<PB0); |
15 | |
16 | SPDR = 0; |
17 | while(!(SPSR & (1<<SPIF))); |
18 | byte1 = SPDR; |
19 | |
20 | SPDR = 0; |
21 | while(!(SPSR & (1<<SPIF))); |
22 | byte2 = SPDR; |
23 | |
24 | SPDR = 0; |
25 | while(!(SPSR & (1<<SPIF))); |
26 | byte3 = SPDR; |
27 | |
28 | PORTB |= (1<<PB0); |
29 | }
|
30 | |
31 | void InitSPI(void) |
32 | {
|
33 | DDRB = (1<<PB4)|(1<<PB5) | (1<<PB7) | (1<<PB0); |
34 | PORTB |= (1<<PB0); |
35 | SPCR = ( (1<<SPE)|(1<<MSTR) | (1<<SPR1) |(1<<SPR0)); |
36 | }
|
37 | |
38 | |
39 | |
40 | |
41 | |
42 | int main(void) |
43 | {
|
44 | |
45 | lcd_init(); |
46 | InitSPI(); |
47 | |
48 | PORTB &= ~(1<<PB0); // Start conversion |
49 | while (1) |
50 | {
|
51 | if(!(PINB & (1 << PINB4))) // If data ready |
52 | {
|
53 | lcd_clear(); |
54 | receiveSPI(); |
55 | itoa(byte1,Buffer,2); lcd_string(Buffer); |
56 | // itoa(byte2,Buffer,2); lcd_string(Buffer);
|
57 | //itoa(byte3,Buffer,2); lcd_string(Buffer);
|
58 | PORTB &= ~(1<<PB0); // Start conversion |
59 | }
|
60 | }
|
61 | |
62 | |
63 | return 0; |
64 | }
|
Frage: Max H. schrieb: > PORTB &= ~(1<<PB0); // Start conversion Warum ziehst du PB0 am Anfang vor der Schleife und am Ende des If states auf 0? Der MCP reagiert an diesem Pin auf eine fallende Flanke. Ich bekomme jetzt eine Reihe Einsen auf dem Display, unabhängig davon was am Eingang des ADCs anliegt...
:
Bearbeitet durch User
Philipp K. schrieb: > Warum ziehst du PB0 am Anfang vor der Schleife und am Ende des If states > auf 0? Der MCP reagiert an diesem Pin auf eine fallende Flanke. Die fallende Flanke am /CS Pin startet die Wandlung, siehe Datenblatt S. 16 ff.
Das habe ich doch aber in der Funktion receiveSPI() schon am Anfang und Ende realisiert, oder sehe ich das falsch? Gruß, Philipp
Philipp K. schrieb: > Ich bekomme jetzt eine Reihe Einsen auf dem Display, unabhängig davon > was am Eingang des ADCs anliegt... Wie sehen die Signale an den Datenleitungen aus? Philipp K. schrieb: > Das habe ich doch aber in der Funktion receiveSPI() schon am > Anfang und > Ende realisiert, oder sehe ich das falsch? Ja, die Wandlung dauert aber ca. 72.73ms und man kann die Daten nicht sofort auslesen.
Philipp K. schrieb: > einen MCP3551 bestellt (22 Bit ADC > Wandler) und 2 Tage lang das Internet nach Theorie zum Anschluss und zur > SPI Schnittstelle sowie das Datenblatt des ICs durchsucht. So, du bist also 21 und Student der Elektrotechnik. Und du scheiterst schon an dem simplen und ausführlich beschriebenen Datenspiel zum Lesen des MCP3551 ? Lies nochmal das Manual, programmiere dir ein paar Pins deines µC als GPIO Pins und mach das Datenspiel zu Fuß per Programm. Ist auch nicht langsamer als das Benutzen einer halben SPI Schnittstelle. Und lerne, aus den Angaben des Manuals herauszulesen, was nd wann die Beine des ADC tun. W.S.
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.