Forum: Mikrocontroller und Digitale Elektronik Grafik-Display mit T6963C Darstellungsfehler


von Anubis (Gast)


Lesenswert?

Hallo,

ich habe bereits einige Zeit investiert, um auf meinem Grafik-Display 
VARITRONIX MGLS-12864T etwas vernüftig darzustellen.
Das Problem ist, dass nur in einer Zeile (etwas unterhalb der Mitte) 
etwas vernüftig angezeigt wird. Siehe hierzu Dateianhang!

Angeschlossen ist das Display an einem PIC16F877. Die Kontrastspannung 
beträgt -5V.
Mein Programm-Code sieht folgendermaßen aus:
1
/*******************************************************************************
2
********************                    ********************
3
********************         M O D U L K O P F    ********************
4
********************                    ********************
5
********************            (C)          ********************
6
********************                    ********************
7
********************************************************************************
8
------------------------------- Organisatorisches ------------------------------
9
                
10
    Modulname  :  LCD_T69693
11
    Projekt    :  LCD-Ansteuerung
12
    Compiler  :  CC5X (Freeware)
13
    Autor    :    
14
    Version    :  1.1
15
    Datum    :  29.03.20008
16
    
17
--------------------------------- Funktionales ---------------------------------
18
    Zweck
19
                    
20
    End_Zweck 
21
*******************************************************************************/
22
23
//Header-Datei für PIC 16F876 einbinden
24
#include <16f877.h>  
25
26
#define NotWR  PORTD.0        //Write LOW aktiv
27
#define NotRD  PORTD.1        //Read LOW aktiv
28
#define NotCE  PORTD.2        //Chip Enable LOW aktiv
29
#define NotCD  PORTD.3        //LOW = Data   HIGH = Command
30
#define NotRST  PORTD.4        //Reset LOW aktiv
31
#define FontSel  PORTD.5        //Font Select HIGH = 6x8  LOW = 8x8
32
33
void Delay_ms(uns8);
34
void Delay_us(uns16);
35
void InitLCD(void);
36
void CheckBusy(void);
37
void WriteCommand(uns8);
38
void WriteData(uns8);
39
void ClearLCD(void);
40
void Anzeigen_Test(void);
41
42
/*******************************************************************************
43
********************       Hauptprogramm          ***********************
44
********************************************************************************
45
    ProcName       :   main
46
    Autor        :    
47
    Datum        :  27.03.2008
48
    Sichtbarkeit  :  
49
    Funktion       :  Hauptprogramm
50
    
51
    Parameter       :  keine  
52
    Rückgabe       :  keine
53
*******************************************************************************/
54
55
void main()
56
{
57
 TRISD = 0;              //Port D als Ausgang
58
 PORTD = 255;
59
 T1CON = 0;              //Timer 1 Vorteiler 1:1
60
 NotRST = 0;
61
 Delay_ms(2);
62
 NotRST = 1;
63
 FontSel = 0;
64
 InitLCD();              //Display initialisieren
65
 Anzeigen_Test();
66
 while(1);
67
}
68
69
/*******************************************************************************
70
********************       Unterprogramm          ***********************
71
********************************************************************************
72
    ProcName       :   InitLCD
73
    Autor        :    
74
    Datum        :  28.03.2008
75
    Sichtbarkeit  :  
76
    Funktion       :  Initialisierung des Displays
77
    
78
    Parameter       :  keine  
79
    Rückgabe       :  keine
80
*******************************************************************************/
81
82
void InitLCD(void)
83
{
84
 TRISC = 0xFF;            //Port C als Eingang (D0 bis D7)
85
 
86
 /*Text Home Set*/
87
 WriteData(0x00);
88
 WriteData(0x00);
89
 WriteCommand(0x40);
90
 
91
 /*Text Area Set*/
92
 WriteData(0x10);          //16 Zeichen pro Zeile
93
 WriteData(0x00);
94
 WriteCommand(0x41);
95
 
96
 /*Grafik Home Adresse*/
97
 WriteData(0x00);
98
 WriteData(0x20);          //Adresse = 0x2000h
99
 WriteCommand(0x42);
100
 
101
 /*Grafik Area Set*/
102
 WriteData(0x10);
103
 WriteData(0x00);
104
 WriteCommand(0x43);
105
 
106
 /*Display im OR-Mode*/
107
 WriteCommand(0x80);
108
 
109
 /*Text an, Grafik an, Cursor aus*/
110
 WriteCommand(0x94);
111
 
112
 /*Adress-Pointer auf 0x0000h setzen*/
113
 WriteData(0x00);
114
 WriteData(0x00);
115
 WriteCommand(0x24);
116
 
117
 
118
 /*Offset Register setzen*/
119
 /*WriteData(0x00);
120
 WriteData(0x20);
121
 WriteCommand(0x22);*/
122
 
123
 /*Display löschen*/
124
 ClearLCD();
125
 
126
 /*Adress-Pointer auf 0x0000h setzen*/
127
 WriteData(0x40);
128
 WriteData(0x00);
129
 WriteCommand(0x24);
130
}
131
132
/*******************************************************************************
133
********************       Unterprogramm          ***********************
134
********************************************************************************
135
    ProcName       :   ClearLCD
136
    Autor        :    
137
    Datum        :  28.03.2008
138
    Sichtbarkeit  :  
139
    Funktion       :  Displays löschen
140
    
141
    Parameter       :  keine  
142
    Rückgabe       :  keine
143
*******************************************************************************/
144
145
void ClearLCD(void)
146
{
147
 uns16 Counter;
148
 
149
 /*Adress-Pointer auf 0x0000h setzen*/
150
 WriteData(0x00);
151
 WriteData(0x00);
152
 WriteCommand(0x24);
153
 
154
 /*Auto-Write aktivieren*/
155
 WriteCommand(0xB0);
156
 
157
 /*es müssen 8 Zeilen mit je 30 Zeichen gelöscht werden --> 8*16=240)*/
158
 for(Counter = 0; Counter < 240; Counter++)
159
 {
160
  WriteData(0x10);          //0x00 == kein Zeichen
161
 }
162
163
 /*Auto-Write deaktivieren*/
164
 WriteCommand(0xB2);
165
 
166
 
167
}
168
169
/*******************************************************************************
170
********************       Unterprogramm          ***********************
171
********************************************************************************
172
    ProcName       :   Delay_ms
173
    Autor        :    
174
    Datum        :  27.03.2008
175
    Sichtbarkeit  :  
176
    Funktion       :  Wartezeit in Millisekunden
177
    
178
    Parameter       :  Anzahl Millisekunden (uns8)  
179
    Rückgabe       :  keine
180
*******************************************************************************/
181
182
void Delay_ms(uns8 Milli)
183
{
184
 uns8 Durchgang;
185
 
186
 TMR1ON = 0;
187
 for(Durchgang = 0; Durchgang < Milli; Durchgang++)
188
 {
189
  TMR1H = 0xFC;
190
  TMR1L = 0x18;          //Timer 1 mit 64536 vorladen (1000 Durchgänge)
191
  TMR1IF = 0;
192
  TMR1ON = 1;
193
  while(!TMR1IF);
194
  TMR1ON = 0;
195
 }
196
}
197
198
/*******************************************************************************
199
********************       Unterprogramm          ***********************
200
********************************************************************************
201
    ProcName       :   Delay_us
202
    Autor        :    
203
    Datum        :  27.03.2008
204
    Sichtbarkeit  :  
205
    Funktion       :  Wartezeit in Mykrosekunden
206
    
207
    Parameter       :  Anzahl Mykrosekunden (uns8)  
208
    Rückgabe       :  keine
209
*******************************************************************************/
210
211
void Delay_us(uns16 Mykro)
212
{
213
 uns8 Wert1, Wert2, Counter;
214
 uns16 Temp, Zeit;
215
 
216
 TMR1ON = 0;
217
 Zeit = 65536 - Mykro;
218
 Temp = Zeit & 0xFF00;      //oberes Nibble isolieren
219
 Wert1 = Temp >> 4;        //Rechtsverschiebung um 4 Bit
220
 Temp = Zeit & 0x00FF;      //unteres Nibble isolieren
221
 Wert2 = Temp;
222
 
223
 for(Counter = 0; Counter < Mykro; Counter++)
224
 {
225
  TMR1H = Wert1;
226
  TMR1L = Wert2;
227
  TMR1IF = 0;
228
  TMR1ON = 1;
229
  while(!TMR1IF);
230
  TMR1ON = 0;
231
 }
232
}
233
234
/*******************************************************************************
235
********************       Unterprogramm          ***********************
236
********************************************************************************
237
    ProcName       :   CheckBusy
238
    Autor        :    
239
    Datum        :  28.03.2008
240
    Sichtbarkeit  :  
241
    Funktion       :  Statusabfrage des Displays
242
              Warten solange Stauts = Busy ist
243
    
244
    Parameter       :  keine  
245
    Rückgabe       :  keine
246
*******************************************************************************/
247
248
void CheckBusy(void)
249
{
250
 uns8 Status;
251
 
252
 TRISC = 255;
253
 do
254
 {
255
  NotCD = 1;
256
  NotCE = 1;
257
  NotRD = 1;
258
  NotWR = 1; 
259
  NotCE = 0;
260
  NotRD = 0;
261
  Delay_us(3);
262
  Status = PORTC;
263
  Status &= 0x03;
264
 }while(Status != 0x03);
265
 NotRD = 1;
266
 NotCE = 1;
267
 TRISC = 0;
268
}
269
270
/*******************************************************************************
271
********************       Unterprogramm          ***********************
272
********************************************************************************
273
    ProcName       :   WriteCommand
274
    Autor        :    
275
    Datum        :  28.03.2008
276
    Sichtbarkeit  :  
277
    Funktion       :  Kommando ins Display schreiben
278
    
279
    Parameter       :  Kommando (uns8)
280
    Rückgabe       :  keine
281
*******************************************************************************/
282
283
void WriteCommand(uns8 Command)
284
{
285
 TRISC = 0;
286
 CheckBusy();
287
 PORTC = Command;
288
 NotCD = 1;
289
 NotRD = 1;
290
 NotWR = 0;
291
 NotCE = 0;
292
 Delay_us(2);
293
 NotWR = 1;
294
 NotCE = 1;
295
}
296
297
/*******************************************************************************
298
********************       Unterprogramm          ***********************
299
********************************************************************************
300
    ProcName       :   WriteData
301
    Autor        :    
302
    Datum        :  28.03.2008
303
    Sichtbarkeit  :  
304
    Funktion       :  Daten ins Display schreiben
305
    
306
    Parameter       :  Daten (uns8)
307
    Rückgabe       :  keine
308
*******************************************************************************/
309
310
void WriteData(uns8 Data)
311
{
312
 TRISC = 0;
313
 CheckBusy();
314
 PORTC = Data;
315
 NotCD = 0;
316
 NotRD = 1;
317
 NotWR = 0;
318
 NotCE = 0;
319
 Delay_us(2);
320
 NotWR = 1;
321
 NotCE = 1;
322
}
323
324
/*******************************************************************************
325
********************       Unterprogramm          ***********************
326
********************************************************************************
327
    ProcName       :   Anzeigen_Test
328
    Autor        :    
329
    Datum        :  29.03.2008
330
    Sichtbarkeit  :  
331
    Funktion       :  Test der Ausgabe 
332
              gesammtes display mit 'A' füllen
333
              
334
    Parameter       :  keine
335
    Rückgabe       :  keine
336
*******************************************************************************/
337
338
void Anzeigen_Test(void)
339
{
340
 uns16 Counter;
341
 
342
 /*Adress-Pointer auf 0x0000h setzen*/
343
 WriteData(0x00);
344
 WriteData(0x00);
345
 WriteCommand(0x24);
346
 
347
 /*Auto-Write aktivieren*/
348
 WriteCommand(0xB0);
349
 
350
 /*es müssen 8 Zeilen mit je 30 Zeichen gelöscht werden --> 8*16=240)*/
351
 for(Counter = 0; Counter < 240; Counter++)
352
 {
353
  WriteData(0x21);          //Zeichen = 'A'
354
 }
355
356
 /*Auto-Write deaktivieren*/
357
 WriteCommand(0xB2);
358
 
359
}

Eigentlich müsste das Display komplett mit 'A' gefüllt sein, aber leider 
ist das Ergebnis wie auf dem Foto zu sehen.

Ist mein Code fehlerhaft, bzw. die Initialisierung des Displays? Oder 
ist das Display einfach nur defekt?

von Michael U. (amiga)


Lesenswert?

Hallo,

Bild???
Nur kurz reingeschaut:

Wieviel Ram hat das TEil denn? Du setzt die Grafikarea aud 0x2000, das 
ist 8k. Die kleinen haben doch meist nur 8k Ram drauf, damit würde die 
Grafikarea bei 0x0000 landen und da hast Du ihm schon Text gesagt?

Gruß aus Berlin
Michael

von Anubis (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

okay 2.Versuch mit dem Dateianhang.

Das Ding hat ein 8k-RAM.

Der Text-Modus ist eingestellt.

von die ??? (Gast)


Lesenswert?

Das sieht aber schwer nach Grafikmodus aus.

von die ??? (Gast)


Lesenswert?

Edit: Will sagen, die Daten scheinen im Grafikbereich zu liegen. 
Allerdings wundert mich die Regelmäßigkeit. Hab deinen Code jedoch nicht 
beaugapfelt.

von Michael U. (amiga)


Lesenswert?

Hallo,

mich stört immernoch etwas der Start Grafik auf 0x2000. Bei 8k Ram liegt 
dann Grafik. und Text Ram auf den gleichen Adressen. Keine Ahnung, was 
der T6963C da macht.
Setz doch mal Grafikram auf einen sinnvollen Wert, 0x0400 oder so, Du 
brauchst doch erstmal nur 16x8 Byte für den Textram.
Einfach, um das mal auszuschließen.

Gruß aus Berlin
Michael

von Anubis (Gast)


Lesenswert?

Hallo,

so, ich habe mal den Adressbereich für die Grafik verändert (0x0400). 
Ohne Erfolg - Display zeigt immer noch den selben Murks.

Hat noch jemand eine Ideee? Oder kann ich davon ausgehen, dass das 
Display hin ist?

von Benedikt K. (benedikt)


Lesenswert?

Du löschst nur den Textbereich. Im Grafikbereich bleibt dann noch 
irgendwas zufälliges drin, was vorher schon drin stand. Lösch doch mal 
alle 8192 Bytes in der Initialisierungsroutine.

von holger (Gast)


Lesenswert?

>Hat noch jemand eine Ideee? Oder kann ich davon ausgehen, dass das
>Display hin ist?

Sieht so aus als wären die Zeilentreiber hin. Was man
sieht sind ja alles Reste von den 'A'.

von Anubis (Gast)


Lesenswert?

Hallo,

ich habe gerade gesehn, dass in Code in kleiner Fehler drinsteckt.
1
/*Text an, Grafik an, Cursor aus*/
2
 WriteCommand(0x94);

Bei 0x94 ist nur der Text-Modus aktiv!

von Benedikt K. (benedikt)


Lesenswert?

holger wrote:

> Sieht so aus als wären die Zeilentreiber hin. Was man
> sieht sind ja alles Reste von den 'A'.

Stimmt. Er verwendet den OR Modus, von daher würden Daten im 
Grafikbereich zusätzliche Pixel ergeben. Es fehlen aber welche.

Wobei ich nicht auf die Zeilentreiber tippe, sondern auf die Leitgummis 
die das LCD mit der Platine verbinden.

von Anubis (Gast)


Lesenswert?

Hallo,

so, ich habe gestern noch ein wenig experiemntiert. Der Fehler wird 
durch das Flachbandkabel (das LCD mit der Platine verbindet), das für 
die Zeilenansteuerung da ist.

von Rick Dangerus (Gast)


Lesenswert?

Warum macht Ihr den Code nicht lesbarer?
Hier mal ein Beispiel (Auszug):

1
#define T6963_SET_CURSOR_POINTER        0x21
2
#define T6963_SET_OFFSET_REGISTER       0x22
3
#define T6963_SET_ADDRESS_POINTER       0x24
4
5
#define T6963_SET_TEXT_HOME_ADDR        0x40
6
#define T6963_SET_TEXT_AREA             0x41
7
#define T6963_SET_GRAPHIC_HOME_ADDR     0x42
8
#define T6963_SET_GRAPHIC_AREA          0x43
9
10
#define T6963_MODE_SET          0x80
11
#define MS_OR                   0
12
#define MS_EXOR                 1
13
#define MS_AND                  3
14
#define MS_TEXT_ATTR            4
15
#define MS_INTERNAL_CG          0       // char 128..255 userdefined
16
#define MS_EXTERNAL_CG          8       // all char userdefined
17
18
#define T6963_DISPLAY_MODE      0x90
19
#define DM_OFF                  0
20
#define DM_CURSOR_BLINK         1
21
#define DM_CURSOR_ON            2
22
#define DM_TEXT_ON              4
23
#define DM_GRAPH_ON             8
24
25
#define T6963_SET_CURSOR_PATTERN        0xA0
26
27
#define T6963_DATA_AUTO_WRITE           0xB0
28
#define T6963_DATA_AUTO_READ            0xB1
29
#define T6963_AUTO_MODE_RESET           0xB3
30
31
#define T6963_DATA_WRITE_INCREMENT      0xC0
32
#define T6963_DATA_READ_INCREMENT       0xC1
33
#define T6963_DATA_WRITE_DECREMENT      0xC2
34
#define T6963_DATA_READ_DECREMENT       0xC3
35
#define T6963_DATA_WRITE                0xC4
36
#define T6963_DATA_READ                 0xC5
37
38
#define T6963_BIT_RESET         0xF0
39
#define T6963_BIT_SET           0xF8
40
41
42
...
43
44
void T6963_InitDisplay (void)
45
{
46
  INIT_CONTROL_PINS ();         //WR,CE,RD,C/D auf Ausgang
47
48
  CE_ON();
49
  WR_ON();
50
  RD_ON();
51
52
  T6963_WriteData2( TEXT_AREA, T6963_SET_TEXT_HOME_ADDR);
53
  T6963_WriteData2( BYTES_PER_ROW, T6963_SET_TEXT_AREA);
54
55
  T6963_WriteData2( GRAPH_AREA, T6963_SET_GRAPHIC_HOME_ADDR);
56
  T6963_WriteData2( BYTES_PER_ROW, T6963_SET_GRAPHIC_AREA);
57
58
  T6963_WriteData2( (CHARGEN_AREA >> 11), T6963_SET_OFFSET_REGISTER);
59
60
  T6963_ClearScreen ();
61
  T6963_ClearTextScreen();
62
63
  T6963_WriteCommand (T6963_MODE_SET + MS_INTERNAL_CG + MS_EXOR);
64
  T6963_WriteCommand (T6963_DISPLAY_MODE + DM_GRAPH_ON + DM_TEXT_ON);
65
66
}

von Michael U. (amiga)


Lesenswert?

Hallo,

@ Rick Dangerus: kann Dir nur zustimmen, mache ich auch so ähnlich.
Wenn man den Code wiederbenutzt, ist man sich spätestens nach ein paar 
Monaten selbst dankbar dafür, weil man es so noch versteht und viel Zeit 
spart. :-)

Gruß aus Berlin
Michael

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.