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
Passen CPOL und CPGHA zum Empfänger? Senden und empfangen auf der gleichen CLK-Flanke geht im allgemeinen schief.
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.
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
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 :)
> @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.
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.
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.
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 :)
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).
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.