Hallo, folgendes Problem hier: - Xmega 32A4U mit SSD1306 (OLED) funktioniert (Xprotolab - gekauft..) - Xmega 32A4U (Dev-Board) mit SSD1306 Display (Eigenbau) lässt das Display auch korrekt anzeigen (einfach Xprotolab Software geflasht - prima) - Xmega 64A1 mit selbigem Eigenbau Display: Pixelsuppe - komisch: an der Software nichts geändert, nur Device geändert (Atmel Studio 6.2) ;( Pixelsuppe ist immer statisch, d.h. es gibt statt dem (erwarteten) Logo dieselbe Pixelsuppe zu sehen. Software komplett entkernt (war recht Spagetti), so dass sie nur das Display initialisiert und das Logo anzeigt, so behält man die Ports unter strikter Kontrolle (das nicht irgendwo ungewollte IO passiert, wo man es nicht erwartet/möchte) -> Pixelsuppe Mit/ohne externem Oszillator (16Mhz, per PLL auf 32Mhz) probiert -> Pixelsuppe SPI Baudrate gedrosselt um Faktor 10^7 (war: 8Mhz) -> Pixelsuppe Oszi angeschaut von SPI CLK und SDIN: Clock clockt und Data datat. Works as designed?! Aber (noch) nicht verglichen mit 32A4U Case (wird vermutlich anders aussehen, klar). Auf dem Gebiet bin ich wohl recht Newbie. Mein Latein ist aber hier erst einmal am Ende. Der USART wird per DMA versorgt, evtl. gibt es da noch ein Problem? Aber scheint mir recht eindeutig und funktioniert für alle probierten Ports immer mit identische Pixelsuppe (auf A1) bzw. mit Logo (auf A4U) - hier ists mal PORTD: // Transfer buffer to display void dma_display(void) { clrbit(LCD_CTRL, LCD_CS); // Select clrbit(LCD_CTRL,LCD_RS); // Instruction mode setbit(DMA.CH2.CTRLA,6); // reset DMA CH0 DMA.CH2.ADDRCTRL = 0b00010000; // Increment source, Destination fixed DMA.CH2.TRFCNT = 3; // buffer size DMA.CH2.DESTADDR0 = (((uint16_t) &USARTD0.DATA)>>0*8) & 0xFF; DMA.CH2.DESTADDR1 = (((uint16_t) &USARTD0.DATA)>>1*8) & 0xFF; DMA.CH2.TRIGSRC = DMA_CH_TRIGSRC_USARTD0_DRE_gc; DMA.CH2.SRCADDR0 = (((uint16_t)(Disp_send.display_setup))>>0*8) & 0xFF; DMA.CH2.SRCADDR1 = (((uint16_t)(Disp_send.display_setup))>>1*8) & 0xFF; DMA.CH2.CTRLA = 0b10000100; // no repeat, 1 byte burst _delay_us(4); // Wait for 3 bytes to be sent setbit(LCD_CTRL, LCD_RS); // Data mode DMA.CH2.TRFCNT = 1024; // buffer size DMA.CH2.CTRLB = 0b00010001; // Low priority interrupt on complete DMA.CH2.CTRLA = 0b10000100; // no repeat, 1 byte burst } // DMA done, now at most 2 bytes are left to be sent ISR(DMA_CH2_vect) { _delay_us(3); // Wait for last byte to transfer setbit(LCD_CTRL, LCD_CS); // No Select setbit(DMA.INTFLAGS, 0); } Hat von euch jemand Erfahrung/Tipps? Bin grad was angefressen nach zwei Tagen testen mit (immerhin) reproduzierbaren, aber unerwünschten Ergebnissen. Kann es ein Softwareproblem sein? Wie beschrieben, die identische Software läuft auf dem kleineren Referenz Devboard mit 32A4U ohne Mucken mit demselben Display(-Board). Pins auf Hardwareseite sind getestet (Kontakte + Led-Testprogramm). Identische Pixelsuppe gibts auf verschiedenen verwendeten Ports. Versorgung und Blocking überprüft und erstere getauscht - sollte eigentlich OK sein. Ohnehin: da das Problem auch bei verschiedenen Baudraten in derselben Pixelsuppe mündet, würde ich Hardwareprobleme eher ausschliessen. Wer reinschauen mag in den Source: https://github.com/ganzziani/XScopes-Firmware Will eigentlich die Firmware nutzen, um zu verstehen. Menüstruktur könnte ich gebrauchen und Display (obwohl seriell, aber da DMA) ist rasend schnell - der Mann hat schon gut Ahnung von dem, was er tut :) Vielen Dank fürs Grübeln!
Christian G. schrieb: > ISR(DMA_CH2_vect) { > _delay_us(3); Wer in einer ISR ein delay einbaut, dem ist nicht mehr zu helfen.
Schau mal ob der verwendete spi Modus der richtige hatte da vor kurzem mal ziemlich Probleme. Allerdings mit de D4 Reihe der xmegas.
@NoDelay... das würde ich so nicht pauschalisieren.... Ganz neben bei hat der XMega ja 3 Interrupt Prioritäten... Aber meist geht es trotzdem ohne... kommt halt auf den Aufwand an, den man reingesteckt hat ... Wenn du DMA benutzt musst du die UART zum SPI umbauen... dann ändert sich auch die Pinbelegung SPI <-> USART SPI
Basti schrieb: > Wenn du DMA benutzt musst du die UART zum SPI umbauen... dann ändert > sich auch die Pinbelegung SPI <-> USART SPI Belegung ist korrekt. Code funktioniert einwandfrei im 32A4U (wie geschrieben) eben nur nicht im 64A1. Ich weiss, ist ein Totschlagargument. NoDelayISR schrieb: > Wer in einer ISR ein delay einbaut, dem ist nicht mehr zu helfen. Ist schon recht hemdsärmelig gebaut, das stimmt, nicht nur an dieser Stelle. Sieht mir nach gebliebenem Provisorium aus. Trotzdem danke.
Also diese Pixelsuppe bekommst du auf zwei Wege. Entweder du initialisierst nur das Display, aber schreibst keine Daten in den Grafikspeicher (z.B. dein Controller schmiert ab, bleibt hängen oder sonst was) oder du schreibst Daten aus einem falschen Bereich deines µCs in den Grafikspeicher des Displays. Ich habe das Display schon sehr lange im Einsatz und auch Problemlos auf A4, A4U, A3 etc am laufen gehabt. Lass mal erstmal das DMA-Geschlunse weg und versuche anstatt dma_display() mal folgende Routine:
1 | void show_display(void) { |
2 | uint16_t i; |
3 | uint8_t *p=display_buffer; |
4 | |
5 | clrbit(LCD_CTRL, LCD_CS); // Select |
6 | |
7 | LcdInstructionWrite(LCD_SET_PAGE); |
8 | LcdInstructionWrite(LCD_SET_COL_HI); // Set column at 0 |
9 | LcdInstructionWrite(LCD_SET_COL_LO); |
10 | cli(); |
11 | setbit(LCD_CTRL, LCD_RS); // Data mode |
12 | // Send data to display
|
13 | for(i=0; i<1024; i++) { |
14 | while(!testbit(USARTD0.STATUS,5)); // Wait for DATA empty |
15 | USARTD0.DATA= *p++; |
16 | }
|
17 | |
18 | while(!testbit(USARTD0.STATUS,6)); // Wait until transmit done |
19 | |
20 | setbit(USARTD0.STATUS,6); // Clear flag |
21 | setbit(LCD_CTRL, LCD_CS); // No Select |
22 | sei(); |
23 | }
|
Den Uart musst du natürlich auf deinen Verwendeten verdrehen. "display_buffer" wäre bei dir dann wohl Disp_data.display_data meine PortInit sieht so aus:
1 | void GLCD_LcdPortInit(void){ |
2 | |
3 | // MOSI, CLK
|
4 | PORTD.DIR = (1<<PIN1) | (1<<PIN3); |
5 | PORTD.OUTCLR = (1<<PIN1) | (1<<PIN3); |
6 | |
7 | //Set Pins to output for LCD_RS, LCD_RESET, LCD_CS
|
8 | PORTC.DIR = (1<<PIN5) | (1<<PIN6) | (1<<PIN7); |
9 | PORTC.OUTCLR = (1<<PIN5) | (1<<PIN6) | (1<<PIN7); |
10 | PORTCFG.VPCTRLA = 0x02; |
11 | |
12 | // Initialize USARTD0 for OLED in SPI mode
|
13 | USARTD0.BAUDCTRLA = 0x01; // (SPI clock = 8MHz) |
14 | USARTD0.CTRLC = USART_CMODE_MSPI_gc; // Master SPI mode, |
15 | USARTD0.CTRLB = USART_TXEN_bm; // Enable TX |
16 | |
17 | |
18 | }
|
und meine GLCD Init so
1 | void GLCD_LcdInit(void) { |
2 | // Recommended power up sequence
|
3 | clrbit(LCD_CTRL, LCD_RESET); // Reset Low for 3 uS |
4 | _delay_us(3); |
5 | setbit(LCD_CTRL, LCD_RESET); // Reset Low for 3 uS |
6 | _delay_us(3); |
7 | // Recommended initialization sequence
|
8 | LcdInstructionWrite(LCD_DISP_OFF); |
9 | LcdInstructionWrite(LCD_SET_RATIO_OSC); |
10 | LcdInstructionWrite(0x80); |
11 | LcdInstructionWrite(LCD_MULTIPLEX); |
12 | LcdInstructionWrite(0x3F); |
13 | LcdInstructionWrite(LCD_SET_OFFSET); |
14 | LcdInstructionWrite(0x00); |
15 | LcdInstructionWrite(LCD_SET_LINE); |
16 | LcdInstructionWrite(LCD_CHARGE_PUMP); |
17 | LcdInstructionWrite(LCD_PUMP_ON); |
18 | |
19 | LcdInstructionWrite(LCD_SET_PADS); |
20 | LcdInstructionWrite(0x12); |
21 | LcdInstructionWrite(LCD_SET_CONTRAST); |
22 | LcdInstructionWrite(0x8F); |
23 | LcdInstructionWrite(LCD_SET_CHARGE); |
24 | LcdInstructionWrite(0xF1); |
25 | LcdInstructionWrite(LCD_SET_VCOM); |
26 | LcdInstructionWrite(0x40); |
27 | LcdInstructionWrite(LCD_EON_OFF); |
28 | LcdInstructionWrite(LCD_DISP_NOR); |
29 | LcdInstructionWrite(LCD_MEM_ADDRESSING); |
30 | LcdInstructionWrite(0x00); // Horizontal Addressing mode |
31 | LcdInstructionWrite(LCD_DISP_ON); |
32 | |
33 | }
|
@Timmo: Danke für den konstruktiven Beitrag. Leider habe ich den erst eben gesehen, sonst hätte ich es natürlich gestern schon ausprobiert. So habe ich gestern noch weiter mit der DMA Variante probiert und es auch irgendwann hinbekommen, allerdings könnte ich jetzt nicht mal sagen woran es gelegen hat. Habe mir dazu eine Kopie meines Codes zum Zerspielen gemacht und überall die vorhandenen Delays etwas erhöht, ein zusätzliches clr_display() am Anfang eingebaut (und noch paar Sachen mehr) und dann lief es plötzlich. Allerdings nicht in jedem Fall stabil (Text erscheint schonmal etwas zu hoch, zu tief oder auch gespiegelt nach wiederholten Powerups). Deine Variante habe ich gerade aber auch noch probiert, lief perfekt gleich nach erstem Kompilieren (ist ja recht übersichtlich). Also soweit erstmal vielen Dank! Da ich die nicht funktionierende Variante aber auch noch habe, schaue ich mir spätestens bei weiteren Unstimmigkeiten das Delta im Coding noch genauer an - bin da schon neugierig. Nach zweieinhalb Tagen Hirn Zermartern (und in der Hitze zurzeit in D) mag ich jetzt erstmal ein wenig weiterkommen mit dem eigentlichen Vorhaben. Es wird aber zu seiner Zeit noch einmal ein Update hier geben. Was die Pixelpampe angeht: Ich hatte auch direkt die Idee, dass ich an die falsche Stelle schreibe (oder an falscher Stelle im Speicher lese) - aber das kann es ja irgendwie nicht sein. Auf der anderen Seite: Wenn der Text (in der o.g. besseren aber leicht instabilen Version) an falscher Stelle bzw. gespiegelt erscheint, dann spricht das ja doch für diese Theorie (Spiegeln entsteht dann vielleicht durch "Glitches" innerhalb der 3 Command Bytes). Wird also noch erforscht, wenn die Zeit reif 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.