Display mit Chip ST7789V Startprobleme

OP #7419205
Lesenswert?

Hallo, ich brauche eure Hilfe, bekomme das Dispay mit dem Chip ST7789V nicht ans laufen. Den u.g. Initialisierungscode kommt vom Displayliefgerant.

Ich möchte zum Anfang einfach mal nur ein paart Pixels setzen..... Ja ich weiß, es gibt libs, aber ich möchte erst mal sehen, ob das Display überhaut etwas macht. Die Hintergrundbeleuchtung geht an. Sonst passiert aber nichts auf dem Display. Hier der Code:

1
void lcdput (unsigned char reg, unsigned char dat)
2
{
3
LCD_RS_Clear();                 // RS Pin Low = Command
4
SPI2Put (reg);                  // 1 Byte Command schreiben
5
LCD_RS_Set();                   // RS Pin High = Data
6
SPI2Put (dat);                  // 1 Byte Daten schreiben
7
}
8

9
void lcddata (unsigned char dat)
10
{
11
LCD_RS_Set();                   // RS Pin High = Data
12
SPI2Put (dat);                  // 1 Byte Daten schreiben
13
}
14

15
void display_initialize (void)     // TFT Touch SPI2  display Init
16
{
17
    
18
LCT_LIGHT_Set();                // Beleuchtung ein
19
        
20
LCD_RST_Clear();                // Reset LCD
21
delay_ms (120);  
22
LCD_RST_Set(); 
23
delay_ms (120);
24
           
25
SS_LCD_Clear();                 // Slave select Display on (low)
26

27
lcdput (0x36,0x00);             // Resister, Data
28

29
//------------------------------------------------------------------------------
30
                                // Data 03= RGB-4-4-4-bit input)
31
                                // Data 05= RGB-5-6-5-bit input)
32
                                // Data 06= RGB-6-6-6-bit input)
33
lcdput (0x3a,0x05);             // Resister, Data, 
34

35

36
lcdput (0xb2,0x0c);             // Resister, Data
37
lcdput (0xb2,0x0c);             // Resister, Data 
38
lcdput (0xb2,0x00);             // Resister, Data 
39
lcdput (0xb2,0x33);             // Resister, Data 
40
lcdput (0xb2,0x33);             // Resister, Data 
41

42
lcdput (0xb7 ,0x35 );             // Resister, Data
43
lcdput (0xbb ,0x2b );             // Resister, Data
44
lcdput (0xc0 ,0x2c );             // Resister, Data
45
lcdput (0xc2 ,0x01 );             // Resister, Data
46
lcdput (0xc3 ,0x11 );             // Resister, Data
47
lcdput (0x04 ,0x20 );             // Resister, Data
48
lcdput (0xc6 ,0x0f );             // Resister, Data
49
lcdput (0xd0 ,0xa4 );             // Resister, Data
50
lcdput (0xd0 ,0xa1);              
51

52
lcdput (0xe0 ,0xd0);             // Resister, Data
53
lcdput (0xe0 ,0x00);              // Resister, Data 
54
lcdput (0xe0 ,0x05);              // Resister, Data 
55
lcdput (0xe0 ,0x0e);              // Resister, Data 
56
lcdput (0xe0 ,0x0d);              // Resister, Data 
57
lcdput (0xe0 ,0x37);              // Resister, Data 
58
lcdput (0xe0 ,0x43);              // Resister, Data 
59
lcdput (0xe0 ,0x47);              // Resister, Data 
60
lcdput (0xe0 ,0x09);              // Resister, Data 
61
lcdput (0xe0 ,0x15);              // Resister, Data 
62
lcdput (0xe0 ,0x12);              // Resister, Data 
63
lcdput (0xe0 ,0x16);              // Resister, Data 
64
lcdput (0xe0 ,0x19);              // Resister, Data 
65
lcdput (0xe0 ,0x11);              // Resister, Data 
66

67
lcdput (0xe1 ,0xd0);              // Resister, Data 
68
lcdput (0xe1 ,0x00);              // Resister, Data 
69
lcdput (0xe1 ,0x05);              // Resister, Data 
70
lcdput (0xe1 ,0x0d);              // Resister, Data 
71
lcdput (0xe1 ,0x0c);              // Resister, Data 
72
lcdput (0xe1 ,0x2d);              // Resister, Data 
73
lcdput (0xe1 ,0x44);              // Resister, Data 
74
lcdput (0xe1 ,0x40);              // Resister, Data 
75
lcdput (0xe1 ,0x0e);              // Resister, Data 
76
lcdput (0xe1 ,0x1c);              // Resister, Data 
77
lcdput (0xe1 ,0x18);              // Resister, Data 
78
lcdput (0xe1 ,0x16);              // Resister, Data 
79
lcdput (0xe1 ,0x19);              // Resister, Data 
80

81
lcdput (0xe7 ,0x10);              // Resister, Data 
82
//lcdput (0x11 ,0x00);              // ? Resister, Data 
83
lcddata (0x11);              // ? Resister, Data 
84

85
delay_ms (120);
86
// lcdput (0x29 ,0x00);              // Display on  command 29
87
lcddata (0x29 );              // Display on  command 29
88
delay_ms (120);
89

90
//----------------Test-----------------------------------
91

92
int i;
93
lcddata  (0x2c); // Memory write
94
for (i=0;i<100;i++)
95
    {
96
    lcddata (0xf9);              // irgendwelche daten
97
    }
98

99

100

101
SS_LCD_Set();                    // SLave select Display off (high)
102
}
#7419633
Lesenswert?

Mal abgesehen von deiner - hmmm, sagen wir ambitionierten - Initialisierung fällt zunächst Folgendes auf:

Dirk F. schrieb:

lcddata (0x2c); // Memory write

RAMWR ist ein Command und sollte nicht als Data gesendet werden.

Ich bin gerade fertig mit dem Schreiben eines Treibers für einen ST7735, der braucht als Initialisierung nur: SLPOUT, INVOFF, DISPON, NORON.

Deine

1
lcdput (0xe0 ,0xd0);             // Resister, Data
2

Orgie ist höchstwahrscheinlich sowohl unnötig, als auch fehlerhaft. Nach GMCTRP1 und GMCTRP2 Command kommen normalerweise ganze Säcke voller Daten. Am Stück! Nicht Byteweise.

#7419779
Lesenswert?

Norbert schrieb:

Zumindest beim ST7735 muss CS nicht dynamisch gesetzt werden. Es reicht wenn man CS zum Anfang des Jahres auf Low setzt und im Anschluss kontinuierlich CMDs und DATA sendet. Gegen Silvester dann CS wieder auf High.

Das kann man zwar so machen, spart aber kaum Zeit und erschwert im Fehlerfall die Fehlersuche ganz erheblich, da CS nicht nur als ChipSelect dient, sondern auch die Controller-interne State-Machine in einen definierten Zustand zwingt.

Daher ist es best-Practice CS lt. Datenblatt zu verwenden.

#7419827
Lesenswert?

Harry L. schrieb:

spart aber kaum Zeit

Jaaaaa, ich weiß worauf du hinaus willst. Das Problem ist aber das man erst den kompletten SPI FIFO bzw. dessen Entleerung abwarten muss bevor man CS hoch hebt. Das kann sich als durchaus lästig erweisen wenn man etwas wirklich Schnelles bauen möchte. Deshalb lohnt es sich über einen Zwischenweg nachzudenken, eine komplette Zeichenoperation bestehend aus einem Sack voller CMDs und DATA zusammen zu fassen und diese Sequenz in /CS und CS zu kapseln. Das Beste aus beiden Welten sozusagen.

OP #7419913
Lesenswert?

Hallo, vielen Dank für die bisherigen Hinweise, die ich versucht habe umzusetzen. Hier ist der neue Code. Leider immer noch keine Reaktion im Display.... Bitte um weitere Hinweise.

1
void lcdcmd (unsigned char cmd)
2
{
3
LCD_RS_Clear();                   // RS Pin High = Data
4
SPI2Put (cmd);                  // 1 Byte Daten schreiben
5
}
6

7
void lcddat (unsigned char dat)
8
{
9
LCD_RS_Set();                   // RS Pin High = Data
10
SPI2Put (dat);                  // 1 Byte Daten schreiben
11
}
12

13
void lcd_cs_hi (void)
14
{
15
SS_LCD_Set();
16
delay_ms (1);
17
}
18

19
void lcd_cs_lo (void)
20
{
21
SS_LCD_Clear();
22
delay_ms (1);
23
}
24

25

26
void display_initialize (void)     // TFT Touch SPI2  display Init
27
{
28
LCT_LIGHT_Set();                // Beleuchtung ein
29
LCD_RST_Clear();                // Reset LCD
30
delay_ms (120);  
31
LCD_RST_Set(); 
32
delay_ms (120);
33
           
34
lcd_cs_lo ();
35
lcdcmd (0x36); lcddat(0x00);             
36
lcd_cs_hi ();
37

38
//------------------------------------------------------------------------------
39
                                // Data 03= RGB-4-4-4-bit input)
40
                                // Data 05= RGB-5-6-5-bit input)
41
                                // Data 06= RGB-6-6-6-bit input)
42
lcd_cs_lo (); 
43
lcdcmd (0x3a);lcddat(0x05);              
44
lcd_cs_hi ();
45

46
lcd_cs_lo ();
47
lcdcmd (0xb2);
48
lcddat(0x0c);             
49
lcddat(0x0c);              
50
lcddat(0x00);              
51
lcddat(0x33);              
52
lcddat(0x33);              
53
lcd_cs_hi ();
54

55
lcd_cs_lo (); lcdcmd (0xb7 ); lcddat(0x35 ); lcd_cs_hi ();            
56
lcd_cs_lo (); lcdcmd (0xbb ); lcddat(0x2b ); lcd_cs_hi ();            
57
lcd_cs_lo (); lcdcmd (0xc0 ); lcddat(0x2c ); lcd_cs_hi ();            
58
lcd_cs_lo (); lcdcmd (0xc2 ); lcddat(0x01 ); lcd_cs_hi ();            
59
lcd_cs_lo (); lcdcmd (0xc3 ); lcddat(0x11 ); lcd_cs_hi ();            
60
lcd_cs_lo (); lcdcmd (0x04 ); lcddat(0x20 ); lcd_cs_hi ();            
61
lcd_cs_lo (); lcdcmd (0xc6 ); lcddat(0x0f ); lcd_cs_hi ();            
62
lcd_cs_lo (); lcdcmd (0xd0 ); lcddat(0xa4 ); lcd_cs_hi ();            
63
lcd_cs_lo (); lcdcmd (0xd0 ); lcddat(0xa1);  lcd_cs_hi ();            
64

65
lcd_cs_lo ();
66
lcdcmd (0xe0);
67
lcddat(0xd0);             
68
lcddat(0x00);               
69
lcddat(0x05);               
70
lcddat(0x0e);               
71
lcddat(0x0d);               
72
lcddat(0x37);               
73
lcddat(0x43);               
74
lcddat(0x47);               
75
lcddat(0x09);               
76
lcddat(0x15);               
77
lcddat(0x12);               
78
lcddat(0x16);               
79
lcddat(0x19);               
80
lcddat(0x11);               
81
lcd_cs_hi (); 
82

83
lcd_cs_lo ();
84
lcdcmd (0xe1 ); 
85
lcddat(0xd0);               
86
lcddat(0x00);               
87
lcddat(0x05);               
88
lcddat(0x0d);               
89
lcddat(0x0c);               
90
lcddat(0x2d);               
91
lcddat(0x44);               
92
lcddat(0x40);               
93
lcddat(0x0e);               
94
lcddat(0x1c);               
95
lcddat(0x18);               
96
lcddat(0x16);               
97
lcddat(0x19);               
98
lcd_cs_hi (); 
99

100
lcd_cs_lo (); lcdcmd (0xe7 ); lcddat(0x10);lcd_cs_hi ();               
101
lcd_cs_lo (); lcdcmd (0x11 );  lcd_cs_hi ();                    
102

103
delay_ms (120);
104
lcd_cs_lo (); lcdcmd (0x29 ); lcd_cs_hi ();   // Display on  command 29
105
delay_ms (120);
106

107
//----------------Test-----------------------------------
108
lcd_cs_lo ();
109
lcdcmd(0x2a);   // 0x2a = Spaltenadresse
110
lcddat(0x00);   // XS8..15 
111
lcddat(0x10);   // XS0..7
112
lcddat(0x00);   // XE8..15 
113
lcddat(0x20);   // XE0..7 
114
lcd_cs_hi ();
115

116
lcd_cs_lo ();
117
lcdcmd(0x2b);   // 0x2b = Zeilenadresse
118
lcddat(0x00);   // YS8..15 
119
lcddat(0x10);   // YS0..7
120
lcddat(0x00);   // YE8..15 
121
lcddat(0x20);   // YE0..7 
122
lcd_cs_hi ();
123

124
lcd_cs_lo ();
125
lcdcmd (0x2c );  // 2c = Memory write
126
int i;
127
for (i=0;i<100;i++)
128
    {
129
    lcddat (0xf9);              // irgendwelche daten
130
    }
131
lcd_cs_hi ();
132
}
#7419919
Lesenswert?

Norbert schrieb:

Das Problem ist aber das man erst den kompletten SPI FIFO bzw. dessen Entleerung abwarten muss bevor man CS hoch hebt.

Hättest du das nicht schon letzte Woche schreiben können? ;-)

Hab gerade angefangen einen Textausgabe für ILI9341 auf einem STM32 zu schreiben (gibts schon, aber ich will es selber lernen). Dabei bin ich über 2h genau an diesem Problem festgehangen: Auf dem DSO habe ich mir den Anfang der SPI-Kommunikation angesehen - passt eigentlich alles. Bis irgendwann mal zum Ende der Sequenz gescrollt habe und dort auf CS gestoßen bin.

Norbert schrieb:

eine komplette Zeichenoperation bestehend aus einem Sack voller CMDs und DATA zusammen zu fassen und diese Sequenz in /CS und CS zu kapseln.

Mal sehen wie ich das noch einbauen kann. Das wird dann wohl auf unterschiedliche Senderoutinen rauslaufen...

#7419924
Lesenswert?

Dirk F. schrieb:

Bitte um weitere Hinweise.

1
lcd_cs_lo (); lcdcmd (0xb7 ); lcddat(0x35 ); lcd_cs_hi ();

Die Klammern gehören bei Funktionen immer direkt ohne Leerzeichen an den Namen.

Wirst du nach Zeichanzahl bezahlt? Schon mal was von einem Array gehört? Das löst zwar nicht dein Problem, verbessert deinen Programmierstil aber sichtbar. Eher so.

1
uint8_t sequence1[] = {0xe1, 0xd0, 0x00, 0x05, 0x0d, 0x0c, 0x2d, 0x44, 0x40, 0x0e, 0x1c, 0x18, 0x16, 0x19};
2

3
lcdcmd_long(sequence1, sizeof(sequence1)); 
4

5
void lcdcmd_long(const uint8_t *data, uint16_t cnt) {
6
    
7
    lcd_cs_lo();
8
    lcdcmd(*data++);
9
    for(cnt--; cnt > 0; cnt--) {
10
        lcddat(*data++);
11
    }
12
    lcd_cs_hi();
13
}
OP #7419944
Lesenswert?

Danke Falk. Ja stimmt. Wollte nur erst mal "quick and dirty" sehen, ob das Display überhaupt etwas macht, um Layoutfehler auszuschließen. Jetzt ist es ansprechbar, dann kommt Optiomierung.

Noch was:

geht nicht:

1
for (i=0;i<62000;i++)
2
    {
3
    lcddat(0xff);              // Bildschirm löschen
4
    }

funktioniert:

1
for (i=0;i<62000;i++)
2
    {
3
    lcd_cs_lo();               // Slave select low
4
    lcddat(0xff);              // Bildschirm löschen
5
    lcd_cs_hi();               // Slave select high
6
    }
#7419949
Lesenswert?

Dirk F. schrieb:

funktioniert:for (i=0;i<62000;i++) { lcd_cs_lo(); // Slave select low lcddat(0xff); // Bildschirm löschen lcd_cs_hi(); // Slave select high }

Ist aber Unfug! Man muss nicht für jedes Byte einen komplette CS-Zyklus durchlaufen, schon gar nicht, wenn du bei jedem CS Wechsel 1ms wartest! Warum machst du nicht das Offensichtliche?

1
lcd_cs_lo();
2
for (i=0; i<62000; i++) lcddat(0xff);
3
lcd_cs_hi();
OP #7420716
Lesenswert?

Falk B. schrieb:

Wieso? Das ist elementar und einfach und man baut das gleich ein.

Habs jetzt so gemacht. Funktioniert:

1
void lcdput (unsigned char dat)
2
{
3
int dummy;
4
SS_LCD_Clear();                 // Slave select low
5
SPI2Put (dat);                  // 1 Byte Daten schreiben
6
while(SPI2STATbits.SPIRBE);     // Warten so lange wie Empfangspuffer leer ist
7
dummy = SPI2BUF;                // Puffer leeren 
8
dummy = dummy;                  // sonst meckert compiler
9
SS_LCD_Set();                   // Slave select high
10
}

Komisch ist, dass die Sache mit dem !SPI2STATbits.SPITBE (Transmit Puffer nicht Empty) nicht funktioniert..

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren