Hallo, um den Thread hier mal wieder ins Leben zu rufen: ich programmiere gerade an einem Display mit T6963C-Chip und habe das ganze an einem AT90CAN128 hängen.. Daten-Port: C; Control-Port: A; JTAG disabled, und die hier angebotene Library in Benutzung. Das ganze funktionierte einwandfrei mit der internen Taktfrequenz des AT90 (8MHz), aber als ich den Chip jetzt auf einen externen 16MHz Quarz umgestellt habe, hat das Display angefangen nur noch Mist anzuzeigen... Fuses zurück auf internen Takt und es funktioniert wieder alles. Ich habe inzwischen gefühlt jedes Elektronikforum 2-mal durchsucht, aber überall wo jemand mal das Problem mit der Taktfrequenz beschreibt, kommt kein befriedigendes Ergebnis heraus. Die Display-Library die ich benutze ist die von einem "Radoslaw Kwiecien", ist sehr übersichtlich und nachvollziehbar programmiert und hat eine "delay"-Funktion, die eine Verzögerung abhängig der Taktfrequenz verursacht. Habe die Dateien und auch meine Projektdateien hier mal in den Anhang gehängt und ein paar Fotos von dem beschriebenen Problem gemacht. Ich hoffe sehr dass mir hier jemand weiterhelfen kann. Sitze inzwischen seit mehreren Wochen nur andem Problem und so langsam hört es auf spaß zu machen... Danke im Voraus!
:
Verschoben durch User
Chesterfield93 schrieb: > und hat eine "delay"-Funktion, die eine Verzögerung abhängig der > Taktfrequenz verursacht. Die wird wohl das Problem sein.
1 | void delay(void) |
2 | {
|
3 | volatile unsigned char i; |
4 | for(i = 0; i < (F_CPU/1000000); i++) |
5 | {
|
6 | asm("nop"); |
7 | }
|
8 | }
|
Ändere die probeweise, indem Du sie langsamer machst. Also entweder den Teiler (1000000) verkleinern oder ein zweites nop in die Schleife einfügen.
void GLCD_WriteData(unsigned char data) { while(!(GLCD_ChceckStatus()&0x03)); GLCD_DATA_PORT = data; GLCD_CTRL_PORT &= ~((1 << GLCD_WR) | (1 << GLCD_CE) | (1 << GLCD_CD)); delay(); GLCD_CTRL_PORT |= ((1 << GLCD_WR) | (1 << GLCD_CD)); // | (1 << GLCD_CE)); } Du kannst auch mal probieren nach der letzten Zeile auch noch ein delay() einzufügen.
Hallo, Danke für die schnellen Antworten! Ich habe alles schon versucht. Ich hab' die Delay-Funktion in der Schleife auch schon bis zu verschiedenen festen Wert zählen lassen, anstatt einen Teiler für F_CPU zu nehmen, habe den Teiler zwischen 10.000 und 32.000.000 variiert - also echt so ziemlich jede denkbar mögliche Zeit abgedeckt - hat alles nichts gebracht. Seltsamerweise funktioniert das ganze mit interner Taktfrequenz tadellos - dann bauen sich zwar die Grafiken einfach leeehr langsam auf oder es haut bei dem 32.000er Teiler (das ist immerhin der 32-fache Wert des originalen) ein paar Pixelfehler rein, aber wirklich kaum... Auch die Idee mit der delay()-Funktion an anderen Stellen hatte ich schon. Leider ebenfalls kein Ergebnis, egal wo ich sie mit ran hänge
:
Bearbeitet durch User
Bist du sicher, dass der Compiler dein delay() nicht weg optimiert? Verwende doch probehalber mal das gcc _delay_us().
Wie lang ist das Kabel zum Display?
Hi >Seltsamerweise funktioniert das ganze mit interner Taktfrequenz tadellos >- dann bauen sich zwar die Grafiken einfach leeehr langsam auf Dann passt was nicht. So ein Display hatte ich schon mit 4MHz betrieben. Da baut sich ein kompletter Screen ohne merkliche Verzögerung auf. Allerdings in Assembler. Bei 11,... MHZ sind an ein paar Stelle ein paar zusätzliche NOPs drin. MfG Spess
Alte Soft durchwühlt und fündig geworden. Bei mir lief ein solches Display mit 16MHz und (fast) der gleichen Lib. Einziger Unterschied, den ich auf die schnelle sehe: void delay(void) { uint8_t i; for(i = 0; i < (F_CPU/1000000L); i++) { asm volatile ("nop\n\t"::); } } Kabellänge übrigens etwa 15cm, normales Flachkabel.
Hi Ups, gerade gesehen: >void GLCD_DrawMap(unsigned char map[32][4], unsigned char px, unsigned char >py) { // Draw Logos > unsigned char l, c, b; > for (l=0;l<32;l++) { > for (c=0;c<4;c++) { > for (b=0;b<8;b++) { > GLCD_SetPixel(c*8+b+px, l+py, map[l][c] & (1<<7-b)); > } > } > } >} das ist natürlich tödlich langsam. Grafiken gebe ich Byteweise aus. Deine Routine dürfte um ein zigfaches langsamer sein. MfG Spess
Habe es gerade ausprobiert und bekomme keine Änderung. Unter 8MHz immernoch alles tip top, unter 16MHz nur Müll. Es gab ja auch unter 8 MHz mit der originalen Funktion keine Probleme mit der Funktion, und durch Veränderung des Teilers in der Schleife wurde der Aufbau des Bildes auch schneller oder langsamer. Ich zweifle inzwischen daran dass es an der delay()-Funktion liegt. Es scheint so als ob der Controller das Bild im Fehlerfall mehrfach versucht aufzubauen und immer wieder abstürzt und von vorne anfängt - manchmal braucht er weit mehr als 10 Anläufe bis sich der "Home-Screen" aufbaut, und dann auch nur mit dem Fehler den ihr ja oben im Bild schon seht.
Kabellänge: ca. 40cm, Flachband. @spess: Danke, habe es mir mal notiert, das wäre natürlich noch ne Möglichkeit der Optimierung. Allerdings muss ich das Display ja erstmal überhaupt zum laufen bringen... Einen Watchdog habe ich nicht am laufen. Soweit ich das verstanden habe ist das ein Auto-Reset, den ich regelmässig nullen muss, der den Zweck hat ungewollte endlosschleifen zu verhindern?
:
Bearbeitet durch User
Hi
>while(!(GLCD_ChceckStatus()&0x03));
Ist eine zusätzliche Bremse. Leg das While in GLCD_ChceckStatus.
MfG Spess
Auf den ersten Blick fällt mir auch nur das delay auf. Bei mir lief das Display mit 40 MHz. Folgenden Kommentar habe ich im Code gefunden:
1 | // wait function for 80 ns (see data sheet)
|
2 | // F_CPU 1MHz 1 NOP = 1000 ns
|
3 | // F_CPU 10MHz 1 NOP = 100 ns
|
4 | // F_CPU 30MHz 1 NOP = 33.3 ns
|
5 | // F_CPU 40MHz 1 NOP = 25 ns
|
Offenbar müssen da irgendow 80 ns eingehalten werden. Bei 16 MHz sollten zwei NOP reichen. Achso. Außerdem werden in meinem Code die Leitungen einzeln angesprochen. Erst CE, dann RD usw. Ich habe jetzt nicht ins Datenblatt geschaut, aber vielleicht spielt das auch noch eine Rolle...
Quentin schrieb: > Offenbar müssen da irgendow 80 ns eingehalten werden. Bei 16 MHz sollten > zwei NOP reichen. Die NOP-Schleife wird pro 10MHz CPU-Frequenz einmal durchlaufen. Dazu kommt die Zeit für Call-Return. Und da es bei mir mit 16MHz gepasst hat, muss der Fehler bei dir an anderer Stelle liegen. Nimm doch einfach mal ein Scope und sieh dir die Signale an. Messen heißt Wissen.
Hallo, vielen Dank für die vielen Ideen und Ratschläge, Im Endeffekt hat es schinbar an einem der Daten-Pins des Microcontrollers gelegen.. ich habe auf Verdacht nochmal alle nach gelötet und jetzt passt es. Das Beinchen hatte wohl einfach einen minimalen Wackelkontakt. Zur Info: mit 'nem Teiler von 2.000.000 in der delay-Funktion passt die Ansteuerung, wenn ich sie noch schneller mache fängt er an hier und da ein paar Pixel zu verhauen.
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.