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
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?
> 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
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_tbyte1,byte2,byte3;
7
charBuffer[20];
8
9
10
voidreceiveSPI()
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
voidInitSPI(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
intmain(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
return0;
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...
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.
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.