Forum: Mikrocontroller und Digitale Elektronik SPI-Problem mit AVR


von Martin (Gast)


Angehängte Dateien:

Lesenswert?

Hallo

Das Problem ist, dass ich den SPI einfach nicht zum ordnungsgemässen 
Funktionieren bringe. Der AVR ist ein Mega328p, und ich will über den 
SPI ein Grafikdisplay ansteuern.

Dazu verwende ich den Hardware-SPI, jedoch nicht das SS-Signal des SPI 
sondern ein separates chip select Signal, weil später einmal mehrere 
Slaves damit angesteuert werden sollen. Der SS-Pin ist als Out 
konfiguriert und unbenutzt.

Beiliegend ein KO-Bild, oben Clock und unten MOSI, mir scheints die 
Datenpulse sind nicht ganz sauber, sehe ich das recht? Die dürfen ja 
wohl nicht so verschiedene Breiten haben, oder?

Wenn dem so ist, was könnte das Problem sein? Ich habe den Takt so weit 
runter geschraubt wie möglich, bei einem 8MHz-Quarz habe ich die 
CLKDIV8-Fuse gesetzt und den SPI-Taktteiler nochmal auf 128 eingestellt. 
Wahrscheinlich übersehe ich irgendwas, da ich auch kein geübter 
SPI-Benutzer bin...

Grüsse
Martin

von Michael M. (Gast)


Lesenswert?

source?

von Bensch (Gast)


Lesenswert?

Passen CPOL und CPGHA zum Empfänger?

Senden und empfangen auf der gleichen CLK-Flanke geht im allgemeinen 
schief.

von Klaus (Gast)


Lesenswert?

Irgendwie schon kurios. Sogar das Clocksignal ist nicht regelmässig...

von Benedikt K. (benedikt)


Lesenswert?

Da ist garnichts kurios:
SPI sendet 8bits am Stück, dazwischen ist halt eine mehr oder weniger 
große Pause in der Clock länger ist, und MOSI auf high liegt. Also 
vollkommen normal.
Der Fehler liegt also wo anders.

von Martin (Gast)


Angehängte Dateien:

Lesenswert?

Danke für eure Antworten.

@Bensch: Ich versuche gar nicht zu empfangen, weil der Slave nicht 
gelesen werden kann. Es handelt sich um ein BL12896A-Display.

@Michael M: Beiliegend die Display-Treiber .c und .h (abgeändert von 
Luminary Micro).

main sieht so aus:
1
int main(void) {
2
3
DDRB =  0b00101110;
4
PORTB = 0b00000001;
5
                      
6
DDRC =  0b0111111;
7
PORTC = 0b0000000;
8
9
DDRD =  0b00000011;
10
PORTD = 0b11111100;
11
12
// SPI CONFIG
13
SPCR = 0;
14
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);
15
SPSR = (0<<SPI2X);
16
17
// Init OLED display
18
SSD1329_Init();
19
20
// Write Hello World
21
SSD1329_StringDraw("Hello World!", 30, 24, 15);
22
23
   //main loop
24
   while(1) {
25
26
   }
27
}

Hilft das was?

Grüsse

Martin

von Soeren A. (abraxa)


Lesenswert?

Wie sieht denn die Beschaltung aus? Ohne die sagen uns deine 
Port-Konfigurationen leider nichts.

Es ist desweiteren moeglich, dass du reset falsch angeschlossen, chip 
select invertiert und/oder D0/D1 vertauscht hast. Das sehen wir im Code 
nicht :)

von Bensch (Gast)


Lesenswert?

> @Bensch: Ich versuche gar nicht zu empfangen, weil der Slave nicht
gelesen werden kann. Es handelt sich um ein BL12896A-Display

Also wenn das Display nichts empfangen soll, warum dann das Ganze?
Nochmal gaaaaanz langsam: Sender=AVR, Empfänger=Display.
Wenn also das Display auf der negativen Flanke sampled, geht schief.

von Soeren A. (abraxa)


Lesenswert?

Wenn Seite 12 von 
http://www.apc-plc.co.uk/documents/Bolymin%20BL12896A%20series%20specs.pdf 
stimmt (das Diagramm hat einige Fehler), dann wird auf der positiven 
Flanke gesampled.

von Martin (Gast)


Angehängte Dateien:

Lesenswert?

Ok klar, hatte ich ganz vergessen. Die Beschaltung ist wie folgt:

SS = B2 (wie erwähnt unbenutzt)
MOSI = B3
MISO = B4
SCK = B5
Display D/C = C0
Display RES = C1
Display CS = C2

@Bensch: Doch das Display soll empfangen, aber kann nichts senden. 
Beiliegend noch das Timing-Diagramm aus dem Datenblatt, meiner Meinung 
nach siehts schon so aus als ob bei steigender Flanke gelesen wird.

von Soeren A. (abraxa)


Lesenswert?

1
// The SPI must already be configured before using this driver and
2
// the following pins must already be defined:
3
//
4
// SCK            SPI Clock
5
// MOSI           SPI Data
6
// CS_DISP        Oled chip select, active low
7
// RES_DISP       Oled reset, active low
8
// DC_DISP        Data/command selection, low = command, high = data
9
// OLED_CMD_PORT  Port where the CS_DISP, RES_DISP and DC_DISP lines are connected

Hast du die in hardware.h definiert?

Bitte zeigen :)

von Martin (Gast)


Angehängte Dateien:

Lesenswert?

voilà

von Soeren A. (abraxa)


Lesenswert?

Das Display wird nie resettet (RES_DISP ist unbenutzt). Da du VCC nicht 
ueber den uC steuerst, wirst du die specs nicht einhalten koennen (VDD 
an, Reset, VCC an). Vermutlich nicht tragisch, aber erwaehnenswert.

Schau also bitte mal, ob es schon funktioniert, wenn du vor dem SPI-Init 
das Display resettest (C1 low fuer >3uS, ab dann konstant high).

von Martin (Gast)


Lesenswert?

Geile Sache, vielen Dank für den Hinweis! Ich habe also

OLED_CMD_PORT &= ~(1<<RES_DISP);
_delay_us(10);
OLED_CMD_PORT |= (1<<RES_DISP);

vorne in die SSD1329_Init() geschrieben und siehe da, endlich eine 
Anzeige auf dem Display!

Danke dir und allen anderen für die Hilfe, falls ich später weitere 
Fragen habe melde ich mich natürlich gerne wieder!

Grüsse
Martin

von Soeren A. (abraxa)


Lesenswert?

Freut mich, dass es funktioniert.

Kleiner Hinweis am Rande: meine Aussage, dass der Controller nie 
resettet wird, war falsch - er wird vielmehr staendig resettet, da 
reset invertiert ist und nie auf high gesetzt wird.

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
Noch kein Account? Hier anmelden.