Hallo, ich habe ein 240x128 Display mit T6963C-Controller angesteuert. Da ich eine eigenen Schriftart verwende, kann ich den internen Zeichensatz nicht verwenden. Die Schrift ist tlw. auch höher als 8 Zeilen. Um ein Zeichen darzustellen, muss ich daher mehrere Adressen beschreiben (z.B. 2 untereinander). Damit die einzelnen Zeichen nicht immer erst bei den nächsten 8 Bit einer Zeile beginnen, ver-odere ich die einzelnen Zeichen. Die einzelnen Zeichen werden in einer Funktion beschrieben. Damit das vorige Zeichen nicht tlw. gelöscht wird, lese ich zuert die aktuelle Adresse aus, dann ver-odere ich dieses Datum mit den Daten des aktuellen Zeichens und schreibe das Byte wieder raus. Bisher funktioniert alles gut. Nun habe ich einen neuen Display-Hersteller. Plötzlich flackert das Display, wenn ich das aktuelle Datum auslese!!??!! Gebe ich diese Zeile weg, flackert es nicht mehr, aber die Schrift ist auch nicht vollständig. Hat vielleicht jemand eine Idee, woran das liegen könnte bzw. wie ich mir abhelfen kann?? Das neue Display ist von Winstar (WG240128B). Danke für eure Hilfe. mfg Andreas
1. Wie ist dein Code geschrieben bzgl. der Abfrage des Statusworts des T6963C? Mit TimeOut oder richtige Abfrage vom Status? 2. Hat das Winstar einen kleineren RAM? 3. Sind die Konfigurationspins des T6963C richtig beschalten? Ralf
Hallo Michael, danke für deine Antwort, ich war die letzten Wochen auf Urlaub, deshalb antworte ich etwas verspätet. ad 1. Ich frage das Statusbyte ab, nicht mit Timeout ad 2. das Winstar Display hat 8k RAM, das vorige Display 32k; aber ich verwende nur den Grafikbereich, und der startet bei Adresse 0 => sollte somit bei beiden Displays funktionieren (Auflösung 320 x 240). ad 3. Die Konfigurationspins sind richtig beschaltet. Beide Displays sind pinkompatibel (lt. Datenblatt). Danke für die Hilfe mfg Andreas
Wenn ich eins von den Displays bekomme, verrat ich dir, woran es liegt grins Nein, quatsch, ernsthaft: also wenn ich folgende Rechnung vornehme: 320 * 240 / 8 = 9600 komme ich auf die benötigte Anzahl der Bytes, die nötig sind, um über den vollen Display-Bereich Grafik darzustellen. Bist du sicher dass das neue Display nur 8kB hat? Das könnte nämlich dann den Fehler erklären :-) Ralf
Uje, hier ist mir wohl ein Fehler passiert, das Display hat nämlich eine Auflösung von 240x128 Pixel... Danke für den Tipp. mfg Andreas
Hi, das dachte ich mir schon, dass es wohl nicht sein kann, dass irgendjemand ein Grafikdisplay bastelt, dessen RAM nicht voll ausreicht... Okay, dann bleibt dir nur noch, hier mal den Code zu posten, vielleicht kann man da was erkennen... Welchen Controller und welche Programmiersprache verwendest du? Ralf
Hallo Ralf, den Code werde ich morgen posten. Danke für die Unterstützung. Ich verwende einen ATmega128 und WinAVR. mfg Andreas
Hallo Ralf, hier nun der Source (tlw.). Das Display flackert nicht, wenn die Zeile DataLeft = LCD_ReadCmd_1_Data(LCD_DATA_RD); entfernt wird. LCD_GraphicXY((_PosX / LCD_UNIT_WIDTH), _PosY + idx); subidx = 0; while (1) { if (subidx < CharWidthB) { if (subidx == 0) DataLeft = LCD_ReadCmd_1_Data(LCD_DATA_RD); Temp = pgm_read_byte(UsedFont.fontdata + Offset + subidx + idx * CharWidthB); DisplayData = Temp >> (_PosX % LCD_UNIT_WIDTH); DisplayData |= DataLeft; DataLeft = (Temp << (LCD_UNIT_WIDTH - (_PosX % LCD_UNIT_WIDTH))); } else { if (DataLeft != 0) DisplayData = DataLeft; else break; DataLeft = 0; } subidx++; LCD_WriteCmd_1_Data(LCD_DATA_WR_INC, DisplayData); } //********************************************************************** ******* // read the status byte //********************************************************************** ******* static unsigned char LCD_ReadStatus(void) { CD_CMD; return LCD_ReadLow(); } //********************************************************************** ******* // status check //********************************************************************** ******* static void LCD_StatusCheck(unsigned char Status) { while ((LCD_ReadStatus() & Status) != Status); } //********************************************************************** ******* // Read a data byte using auto write mode //********************************************************************** ******* static unsigned char LCD_ReadDataAuto(void) { LCD_StatusCheck(LCD_STATUS_AUTO_RD); CD_DATA; return LCD_ReadLow(); } //********************************************************************** ******* // Read a data byte + a command byte //********************************************************************** ******* static unsigned char LCD_ReadCmd_1_Data(unsigned char Cmd) { LCD_StatusCheck(LCD_STATUS_READ_WRITE); //CD_CMD; LCD_WriteLow(Cmd); LCD_StatusCheck(LCD_STATUS_READ_WRITE); CD_DATA; return LCD_ReadLow(); } //********************************************************************** ******* // Read a data byte //********************************************************************** ******* static unsigned char LCD_ReadData(void) { LCD_StatusCheck(LCD_STATUS_READ_WRITE); CD_DATA; return LCD_ReadLow(); } //********************************************************************** ******* // read a byte //********************************************************************** ******* static unsigned char LCD_ReadLow(void) { unsigned char byte = 0; LCD_PORT_INPUT; // enable pullups to read data LCD_ENABLE_PU; CE_ENABLE; RD_ENABLE; // wait min. 150ns asm("nop"); byte = LCD_PIN; CE_DISABLE; RD_DISABLE; LCD_PORT_OUTPUT; return byte; } //********************************************************************** ******* // Write a data byte + a command byte //********************************************************************** ******* static void LCD_WriteCmd_1_Data(unsigned char Cmd, unsigned char data) { LCD_StatusCheck(LCD_STATUS_READ_WRITE); CD_DATA; LCD_WriteLow(data); LCD_StatusCheck(LCD_STATUS_READ_WRITE); LCD_WriteLow(Cmd); } //********************************************************************** ******* // Write two data bytes + a command byte //********************************************************************** ******* static void LCD_WriteCmd_2_Data(unsigned char Cmd, unsigned int data) { LCD_StatusCheck(LCD_STATUS_READ_WRITE); CD_DATA; LCD_WriteLow((unsigned char)data); LCD_StatusCheck(LCD_STATUS_READ_WRITE); CD_DATA; LCD_WriteLow((unsigned char)(data >> 8)); LCD_StatusCheck(LCD_STATUS_READ_WRITE); LCD_WriteLow(Cmd); } //********************************************************************** ******* // Write a byte //********************************************************************** ******* static void LCD_WriteLow(unsigned char byte) { CE_ENABLE; WR_ENABLE; LCD_PORT = byte; // wait min. 80ns //asm("nop"); CE_DISABLE; WR_DISABLE; }
>> LCD_GraphicXY
Könntest du die Funktion wenigstens in groben Zügen mal beschreiben?
Ich werd aus deinen Variablennamen nicht schlau...
Wenn ich weiss, was da passiert bzw. passieren soll, wirds einfacher
für mich...
Ralf
Hallo, am besten ich poste den gesamten Code. Danke für die Hilfe. #define LCD_PORT_OUTPUT (LCD_PORT_DDR = 0xFF) #define LCD_PORT_INPUT (LCD_PORT_DDR = 0x00) #define LCD_ENABLE_PU (LCD_PORT = 0xFF) #define WR_OUTPUT sbi(DDRD, LCD_WR) #define WR_ENABLE cbi(PORTD, LCD_WR) #define WR_DISABLE sbi(PORTD, LCD_WR) #define RD_OUTPUT sbi(DDRD, LCD_RD) #define RD_ENABLE cbi(PORTD, LCD_RD) #define RD_DISABLE sbi(PORTD, LCD_RD) #define CE_OUTPUT sbi(DDRA, LCD_CE) #define CE_ENABLE cbi(PORTA, LCD_CE) #define CE_DISABLE sbi(PORTA, LCD_CE) #define CD_OUTPUT sbi(DDRD, LCD_CD) #define CD_DATA cbi(PORTD, LCD_CD) #define CD_CMD sbi(PORTD, LCD_CD) #define RST_OUTPUT sbi(DDRA, LCD_RST) #define RST_LOW cbi(PORTA, LCD_RST) #define RST_HIGH sbi(PORTA, LCD_RST) #define FS_OUTPUT sbi(DDRA, LCD_FS) #define FS_8x8 cbi(PORTA, LCD_FS) #define FS_6x8 sbi(PORTA, LCD_FS) #define MD2_OUTPUT sbi(DDRA, LCD_FS) #define MD2_40COL cbi(PORTA, LCD_FS) #define MD2_32COL sbi(PORTA, LCD_FS) //********************************************************************** ******* // global variables //********************************************************************** ******* static Font_t UsedFont; static unsigned char FontSet = 0; static unsigned char Alignment = ALIGN_LEFT; static unsigned char _PosX = 0; static unsigned char _PosY = 0; //********************************************************************** ******* // Init the display //********************************************************************** ******* void LCD_Init(void) { // init the IO-directions LCD_PORT_OUTPUT; WR_OUTPUT; RD_OUTPUT; CE_OUTPUT; CD_OUTPUT; RST_OUTPUT; FS_OUTPUT; MD2_OUTPUT; // init the IO-lines WR_DISABLE; RD_DISABLE; CE_DISABLE; if (LCD_UNIT_WIDTH == 6) { MD2_40COL; FS_6x8; } else { MD2_32COL; FS_8x8; } // reset LCD RST_LOW; Delay_ms(5); RST_HIGH; // init the display LCD_WriteCmd_2_Data(LCD_SET_TEXT_HOME_ADDR, LCD_TEXT_BASE); LCD_WriteCmd_2_Data(LCD_SET_GRA_HOME_ADDR, LCD_GRA_BASE); LCD_WriteCmd_2_Data(LCD_SET_TEXT_AREA, LCD_COLUMNS); LCD_WriteCmd_2_Data(LCD_SET_GRA_AREA, LCD_COLUMNS); LCD_WriteCmd(LCD_MODE_OR); // set offset register LCD_WriteCmd_2_Data(LCD_SET_OFFSET_REG, 0x1400); // clear the graphic ram LCD_ClearDisplay(); // set address pointer to start of text ram //LCD_WriteCmd_2_Data(LCD_SET_ADDR_POINTER, LCD_TEXT_BASE); // set cursor 1 line //LCD_WriteCmd(LCD_1_LINE_CUR); } //********************************************************************** ******* // set display mode //********************************************************************** ******* void LCD_DisplayMode(unsigned char Mode) { LCD_WriteCmd(Mode); } //********************************************************************** ******* // Write a data byte using auto write mode //********************************************************************** ******* static void LCD_WriteDataAuto(unsigned char data) { LCD_StatusCheck(LCD_STATUS_AUTO_WR); CD_DATA; LCD_WriteLow(data); } //********************************************************************** ******* // Write a cmd byte //********************************************************************** ******* static void LCD_WriteCmd(unsigned char cmd) { LCD_StatusCheck(LCD_STATUS_READ_WRITE); //CD_CMD; LCD_WriteLow(cmd); } //********************************************************************** ******* // Write a data byte //********************************************************************** ******* static void LCD_WriteData(unsigned char data) { LCD_StatusCheck(LCD_STATUS_READ_WRITE); CD_DATA; LCD_WriteLow(data); } //********************************************************************** ******* // Write a data byte + a command byte //********************************************************************** ******* static void LCD_WriteCmd_1_Data(unsigned char Cmd, unsigned char data) { LCD_StatusCheck(LCD_STATUS_READ_WRITE); CD_DATA; LCD_WriteLow(data); LCD_StatusCheck(LCD_STATUS_READ_WRITE); LCD_WriteLow(Cmd); } //********************************************************************** ******* // Write two data bytes + a command byte //********************************************************************** ******* static void LCD_WriteCmd_2_Data(unsigned char Cmd, unsigned int data) { LCD_StatusCheck(LCD_STATUS_READ_WRITE); CD_DATA; LCD_WriteLow((unsigned char)data); LCD_StatusCheck(LCD_STATUS_READ_WRITE); CD_DATA; LCD_WriteLow((unsigned char)(data >> 8)); LCD_StatusCheck(LCD_STATUS_READ_WRITE); LCD_WriteLow(Cmd); } //********************************************************************** ******* // Write a byte //********************************************************************** ******* static void LCD_WriteLow(unsigned char byte) { CE_ENABLE; WR_ENABLE; LCD_PORT = byte; // wait min. 80ns //asm("nop"); CE_DISABLE; WR_DISABLE; } //********************************************************************** ******* // read the status byte //********************************************************************** ******* static unsigned char LCD_ReadStatus(void) { CD_CMD; return LCD_ReadLow(); } //********************************************************************** ******* // status check //********************************************************************** ******* static void LCD_StatusCheck(unsigned char Status) { while ((LCD_ReadStatus() & Status) != Status); } //********************************************************************** ******* // Read a data byte using auto write mode //********************************************************************** ******* static unsigned char LCD_ReadDataAuto(void) { LCD_StatusCheck(LCD_STATUS_AUTO_RD); CD_DATA; return LCD_ReadLow(); } //********************************************************************** ******* // Read a data byte + a command byte //********************************************************************** ******* static unsigned char LCD_ReadCmd_1_Data(unsigned char Cmd) { LCD_StatusCheck(LCD_STATUS_READ_WRITE); //CD_CMD; LCD_WriteLow(Cmd); LCD_StatusCheck(LCD_STATUS_READ_WRITE); CD_DATA; return LCD_ReadLow(); } //********************************************************************** ******* // Read a data byte //********************************************************************** ******* static unsigned char LCD_ReadData(void) { LCD_StatusCheck(LCD_STATUS_READ_WRITE); CD_DATA; return LCD_ReadLow(); } //********************************************************************** ******* // read a byte //********************************************************************** ******* static unsigned char LCD_ReadLow(void) { unsigned char byte = 0; LCD_PORT_INPUT; // enable pullups to read data LCD_ENABLE_PU; CE_ENABLE; RD_ENABLE; // wait min. 150ns asm("nop"); byte = LCD_PIN; CE_DISABLE; RD_DISABLE; LCD_PORT_OUTPUT; return byte; } //********************************************************************** ******* // set the address pointer to graphic area //********************************************************************** ******* void LCD_GotoXY(unsigned char PosX, unsigned char PosY) { _PosX = PosX; _PosY = PosY; LCD_SetAlign(ALIGN_LEFT); } //********************************************************************** ******* // set the address pointer to graphic area //********************************************************************** ******* static void LCD_GraphicXY(unsigned char PosX, unsigned char PosY) { LCD_WriteCmd_2_Data(LCD_SET_ADDR_POINTER, LCD_GRA_BASE + PosY * LCD_COLUMNS + PosX); } //********************************************************************** ******* // Clear the whole graphic ram //********************************************************************** ******* void LCD_ClearDisplay(void) { unsigned int idx = 0; LCD_WriteCmd_2_Data(LCD_SET_ADDR_POINTER, LCD_GRA_BASE); LCD_WriteCmd(LCD_SET_DATA_AUTO_WR); for (idx = 0; idx < LCD_GRA_SIZE; idx++) { LCD_WriteDataAuto(0x00); } LCD_WriteCmd(LCD_AUTO_RESET); } //********************************************************************** ******* // Clear a specified range of the display ram //********************************************************************** ******* void LCD_ClearRange(unsigned char StartX, unsigned char StartY, unsigned char Width, unsigned char Height) { unsigned char idx = 0; // clear line by line while (Height--) { // set the address pointer LCD_GraphicXY((StartX / LCD_UNIT_WIDTH), StartY++); LCD_WriteCmd(LCD_SET_DATA_AUTO_WR); for (idx = 0; idx < (Width / 8); idx++) { LCD_WriteDataAuto(0x00); } LCD_WriteCmd(LCD_AUTO_RESET); } } //********************************************************************** ******* // defines the font to use //********************************************************************** ******* void LCD_SetFont(Font_t font) { FontSet = 1; UsedFont = font; } //********************************************************************** ******* // set the alignment of the text //********************************************************************** ******* void LCD_SetAlign(unsigned char Align) { Alignment = Align; } //********************************************************************** ******* // writes a char //********************************************************************** ******* void LCD_PutChar(unsigned char str) { unsigned char DataLeft = 0; unsigned int Offset = 0; unsigned char CharWidth = 0; unsigned char CharWidthB = 0; unsigned char idx = 0; unsigned char subidx = 0; // calculate the offset to read the font data idx = str - ' '; Offset = pgm_read_byte(UsedFont.fontoffset + idx*2); Offset += (pgm_read_byte(UsedFont.fontoffset + idx*2 + 1) << 8); CharWidth = pgm_read_byte(UsedFont.fontdata + Offset); CharWidthB = ((CharWidth - 1) / LCD_UNIT_WIDTH) + 1; Offset += 1; for (idx = 0; idx < UsedFont.Height; idx++) { unsigned char Temp = 0; unsigned char DisplayData; LCD_GraphicXY((_PosX / LCD_UNIT_WIDTH), _PosY + idx); subidx = 0; while (1) { if (subidx < CharWidthB) { if (subidx == 0) DataLeft = LCD_ReadCmd_1_Data(LCD_DATA_RD); Temp = pgm_read_byte(UsedFont.fontdata + Offset + subidx + idx * CharWidthB); DisplayData = Temp >> (_PosX % LCD_UNIT_WIDTH); DisplayData |= DataLeft; DataLeft = (Temp << (LCD_UNIT_WIDTH - (_PosX % LCD_UNIT_WIDTH))); } else { if (DataLeft != 0) DisplayData = DataLeft; else break; DataLeft = 0; } subidx++; LCD_WriteCmd_1_Data(LCD_DATA_WR_INC, DisplayData); } } _PosX += CharWidth; } //********************************************************************** ******* // puts a hex character //********************************************************************** ******* void LCD_PutHex(unsigned char data) { unsigned char buf[5]; sprintf(buf, "%02x", data); LCD_PutStr(buf); } //********************************************************************** ******* // Prints a long value //********************************************************************** ******* void LCD_PutLong(unsigned long Value, BOOL ShowKomma) { unsigned char Cnt = 0; unsigned char Buf[10]; // umwandeln Cnt = 10; memset(Buf, 0x00, sizeof(Buf)); do { Cnt--; Buf[Cnt] = Value % 10; Value /= 10; } while (Value > 0); // if the value is smaller than 1, also show the komma and a leading "0" if (Cnt >= 8 && ShowKomma) Cnt = 7; // nun ausgeben while (Cnt < 10) { LCD_PutChar(Buf[Cnt] + '0'); Cnt++; if (ShowKomma && (Cnt == 8) ) LCD_PutChar(','); } } //********************************************************************** ******* // writes text to the display at the specified position //********************************************************************** ******* void LCD_PutStr(unsigned char * str) { unsigned char PosX = _PosX; // if no font has been set, return if (FontSet == 0) return; if (Alignment != ALIGN_LEFT) { unsigned char * pstr = str; unsigned int Offset = 0; unsigned char idx = 0; unsigned char TextWidth = 0; while (*pstr >= ' ') { idx = *pstr - ' '; Offset = pgm_read_byte(UsedFont.fontoffset + idx*2); Offset += (pgm_read_byte(UsedFont.fontoffset + idx*2 + 1) << 8); TextWidth += pgm_read_byte(UsedFont.fontdata + Offset); pstr++; } if (Alignment == ALIGN_RIGHT) _PosX = (LCD_PIXELX - TextWidth); else _PosX = (LCD_PIXELX - TextWidth) / 2; } while (*str) { if (*str == '\n') _PosY += UsedFont.Height; else if (*str == '\r') _PosX = PosX; else LCD_PutChar(*str); str++; } } //********************************************************************** ******* // Write a small image //********************************************************************** ******* void LCD_ShowImageSmall(unsigned char PosX, unsigned char Line, unsigned char * image, unsigned char Len) { } //********************************************************************** ******* // Write a full screen display // image is located in flash memory //********************************************************************** ******* void LCD_ShowImage(PGM_P pimage) { } //********************************************************************** ******* // Set a pixel //********************************************************************** ******* void LCD_SetPixel(unsigned char PosX, unsigned char PosY) { // set address pointer LCD_WriteCmd_2_Data(LCD_SET_ADDR_POINTER, LCD_GRA_BASE + PosY * LCD_COLUMNS + PosX / LCD_UNIT_WIDTH); LCD_WriteCmd(LCD_BIT_SET | (LCD_UNIT_WIDTH - 1 - (PosX % LCD_UNIT_WIDTH))); } //********************************************************************** ******* // reset a pixel //********************************************************************** ******* void LCD_ResetPixel(unsigned char PosX, unsigned char PosY) { LCD_WriteCmd_2_Data(LCD_SET_ADDR_POINTER, LCD_GRA_BASE + PosY * LCD_COLUMNS + PosX / LCD_UNIT_WIDTH); LCD_WriteCmd(LCD_BIT_RESET | (LCD_UNIT_WIDTH - 1 - (PosX % LCD_UNIT_WIDTH))); } //********************************************************************** ******* // draw a line //********************************************************************** ******* void LCD_DrawLine(unsigned char X1, unsigned char Y1, unsigned char X2, unsigned char Y2) { unsigned char XStep, YStep, XStart, YStart; unsigned int Tmp; if (X1 > X2) { XStep = X1 - X2; XStart = X2; } else { XStep = X2 - X1; XStart = X1; } if (Y1 > Y2) { YStep = Y1 - Y2; YStart = Y2; } else { YStep = Y2 - Y1; YStart = Y1; } if (XStep > YStep) { for (unsigned char x = 0; x <= XStep; x++) { Tmp = (YStep * 100) / XStep; LCD_SetPixel(x + XStart, Tmp * x / 100 + YStart); } } else { for (unsigned char y = 0; y <= YStep; y++) { Tmp = (XStep * 100) / YStep; LCD_SetPixel(Tmp * y / 100 + XStart, y + YStart); } } } //********************************************************************** ******* // draw a rectangle //********************************************************************** ******* void LCD_DrawRect(unsigned char X1, unsigned char Y1, unsigned char X2, unsigned char Y2) { LCD_DrawLine(X1, Y1, X2, Y1); LCD_DrawLine(X2, Y1, X2, Y2); LCD_DrawLine(X2, Y2, X1, Y2); LCD_DrawLine(X1, Y2, X1, Y1); } //********************************************************************** ******* // draw a circle //********************************************************************** ******* void LCD_DrawCircle(unsigned char PosX, unsigned char PosY, unsigned char Radius) { int tswitch, y, x = 0; y = Radius; tswitch = 3 - 2 * Radius; while (x <= y) { LCD_SetPixel(PosX + x, PosY + y); LCD_SetPixel(PosX + x, PosY - y); LCD_SetPixel(PosX - x, PosY + y); LCD_SetPixel(PosX - x, PosY - y); LCD_SetPixel(PosX + y, PosY + x); LCD_SetPixel(PosX + y, PosY - x); LCD_SetPixel(PosX - y, PosY + x); LCD_SetPixel(PosX - y, PosY - x); if (tswitch < 0) tswitch += (4 * x + 6); else { tswitch += (4 * (x - y) + 10); y--; } x++; } } //********************************************************************** ******* // draw a box //********************************************************************** ******* void LCD_DrawBox(unsigned char PosX, unsigned char PosY, unsigned char Width, unsigned char Height) { if (Width < 17) Width = 17; if (Height < 17) Height = 17; Width -= 17; Height -= 17; LCD_DrawArc(PosX + 8, PosY + 8, 8, 0); LCD_DrawLine(PosX + 8, PosY, PosX + 8 + Width, PosY); LCD_DrawArc(PosX + 8 + Width, PosY + 8, 8, 1); LCD_DrawLine(PosX + 16 + Width, PosY + 8, PosX + 16 + Width, PosY + 8 + Height); LCD_DrawArc(PosX + 8 + Width, PosY + 8 + Height, 8, 2); LCD_DrawLine(PosX + 8, PosY + 16 + Height, PosX + 8 + Width, PosY + 16 + Height); LCD_DrawArc(PosX + 8, PosY + 8 + Height, 8, 3); LCD_DrawLine(PosX, PosY + 8, PosX, PosY + 8 + Height); } //********************************************************************** ******* // draw a arc //********************************************************************** ******* void LCD_DrawArc(unsigned char PosX, unsigned char PosY, unsigned char Radius, unsigned char Dir) { int tswitch, y, x = 0; y = Radius; tswitch = 3 - 2 * Radius; while (x <= y) { switch (Dir) { case 0: // arc left upper LCD_SetPixel(PosX - x, PosY - y); LCD_SetPixel(PosX - y, PosY - x); break; case 1: // arc right upper LCD_SetPixel(PosX + x, PosY - y); LCD_SetPixel(PosX + y, PosY - x); break; case 2: // arc right lower LCD_SetPixel(PosX + x, PosY + y); LCD_SetPixel(PosX + y, PosY + x); break; case 3: // arc left lower LCD_SetPixel(PosX - x, PosY + y); LCD_SetPixel(PosX - y, PosY + x); break; } if (tswitch < 0) tswitch += (4 * x + 6); else { tswitch += (4 * (x - y) + 10); y--; } x++; } }
Das hilft nur bedingt. Ich brauch ne Beschreibung, was das Programm bzw. einzelne Funktionen machen (sollen). Ich werd aus dem Code allein nicht schlau. Jede gute Software ist dokumentiert. Ralf
Hallo, Doku ist sicher nicht schlecht, aber wie immer ist das, was am wenigsten Priorität hat und auch bei diesem Projekt war so gut wie keine Zeit dafür... Prinzipieller Ablauf: LCD_Init() => Initialisieren des Displays + IO-Leitungen LCD_ClearDisplay() => Display-RAM löschen LCD_GotoXY() => Position am Display setzen LCD_PutStr() => String ausgeben mit eingestellter Schriftart (nicht die eingebaute Schriftart, sondern selbst definierter Schriftsatz) LCD_PutStr ruft LCD_PutChar() auf. LCD_PutChar() => Ausgabe eines einzelnen Zeichens auf das Display. Das Zeichen wird Zeile für Zeile je 8Bit ausgegeben. Ist das Zeichen z.B. 23 Pixel hoch, so wird die Schleife 23x durchlaufen. Pro Schreibzyklus können nur 8 Bit in einer Zeile geschrieben werden. Ist das Zeichen z.B. 11 Pixel breit, so muss man 2x schreiben, um eine Zeile des Zeichens richtig anzuzeigen. Das erste Zeichen ist eigentlich kein Problem. Schreibt man aber einen String raus, so schreibe ich nach dem ersten Zeichen das weitere hinten dran. Nehmen wir an, die Zeichen werden durch 2 Leerspalten getrennt. Dann sollte das 2. Zeichen ab Pixel 13 stehen. Da das aber in der Mitte eines Bytes ist, muss ich das Zeichen auslesen, welches an der Adresse steht (hier steht ein Teil des ersten Zeichens). Dann muss ich das aktuelle Zeichen entsprechend verschieben, um die ersten 3 Pixel ((16 - 13) % 8) anzuzeigen. Diese Daten muss ich mit dem Inhalt des Display-RAMs verodern, um das alte Zeichen (2. Teil des ersten Zeichens) nicht zu löschen. Danach wird das Byte wieder geschrieben. usw. Ist die Beschreibung so ok?
Kleiner Tipp am Rande: Man kann sich viel Datenverkehr sparen, wenn man den String im RAM des µC vorbereitet. Ich schreibe eine ganze Zeile (1 Pixel breit) in den RAM (der ist so breit wie das Display, also 32 Bytes) und muss dann nur links und rechts die beiden End-Bytes verodern. Alles andere wird überschrieben - dadurch kann man auch Texte überschreiben, ohne gleich alles löschen zu müssen. Zu Deinem Problem: Ich vermute ein Timing-Problem. Ich würde spaßeshalber in jede Subroutine, die mit dem Display auf Hardwareebene kommuniziert, mit ein paar eingestreuten NOPs verlangsamen. Vielleicht ist irgendwo ein Signal einen Tick zu schnell. Bedingt durch unterschiedliche Layouts könnte es bei einem Display gerade so hinhauen, beim anderen eben nicht...
Danke für den Tipp. Teilweise habe ich schon nops eingefügt, aber ich werde das noch mal erweitern. Wenn ich dadurch den Fehler nicht verhindert kann, muss ich mir auch die Daten vor dem Schreiben im RAM speichern. mfg Andreas
Man könnte das mit dem Verlangsamen auch auf die Spitze treiben: Nach jedem Programmschritt per serieller Schnittstelle den aktuellen Status senden und auf eine Quittierung warten - also eine Art "single-step". Dann sollte man eigentlich den Übeltäter ganz exakt finden.
Hallo, ich habe jetzt die gesamte SW umgeworfen. Nun gebe ich einen String wie thkais gemeint hat Zeile für Zeile aus. Dadurch kann ich die Daten im RAM zwischenspeichern und muss das Display-RAM nicht mehr auslesen. Allerdings flackert das Display jetzt auch ab und zu, aber weit nicht so extrem wie vorher... Danke für eure Hilfe. mfg Andreas
Noch n Tip meinerseits, sorry erstmal dass ich erst jetzt schreibe. Ich habe auch mal einen eigenen Schriftsatz implementiert, und bin dabei so vorgegangen: Jeder Buchstabe war über eine Tabelle im Code hinterlegt (wird bei dir wohl auch so sein). Die ersten beiden Einträge der Tabelle haben die Größe des Buchstabens in X und in Y angegeben. Alle weiteren Einträge waren die Pixel, die den Buchstaben bilden, pro 8 Pixel also ein Byte. Hatte ich z.B. eine Breite von 14 Pixeln, so habe ich das erste Byte komplett und vom zweiten eben die höchstwertigen 6 Bits ausgegeben --> mittels PUTPIXEL. Ich musste aber nicht auslesen, so wie du es machst, sondern habe nur die gesetzten Pixel eingetragen. Wollte ich sicherstellen, dass ein evtl. bereits vorhandener Buchstabe überschrieben wird, so hab ich natürlich auch die nicht gesetzten Pixel ausgegeben... Schließlich hat der T6963C ja eine Pixelfunktion, warum also die nicht nutzen??? Vielleicht kannst du das auch so machen... Ob es allerdings mit byteweisem Schreiben schneller geht, müsste ich mal probieren, dann wäre das ganze nämlich ein Tip von dir an mich ;-) Ralf
Hallo Ralf, danke für den Tipp. Das hatte ich mir auch schon mal überlegt gehabt. Ich dachte mir aber, dass das vielleicht zu langsam werden könnte, da man immer nur 1 Pixel setzen kann. Anbei habe ich den neuen Code, falls es dich interessiert. Auch ich habe mir einige Schriftarten definiert. Mit einem speziellen Tool kann ich Systemfonts umwandeln und gleich als font-Datei speichern. Die Höhe eines Zeichens einer Schriftart ist immer gleich, die Breite des Zeichens steht, wie bei dir, vor den eigentlichen Daten. mfg Andreas
Okay, ich hab demnächst Urlaub, vielleicht probier ich mal die 1-Byte-auf-einmal-Variante... Wie heisst dein Tool bzw. wo kann ich das herunterladen? Ralf
Naja, das Tool zum konvertieren habe ich im Zuge eines Projektes in der Arbeit geschrieben... Das Tool zum Umwandeln der Systemfonts findest du anbei. Etwas komisches Programm, aber es funktioniert und wandelt dir die Fonts in Binäre Daten um. Diese sind aber spaltenweise und müssen erst noch (mit meinem Tool) umgewandelt werden. Andreas
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.