Forum: Mikrocontroller und Digitale Elektronik ILI9486L in Betrieb nehmen


von Martin (Gast)


Lesenswert?

Moin,
ich hab mir vor längerer Zeit mal folgendes LCD mit ILI9486 Treiber 
besorgt:
https://www.ebay.de/itm/Display-3-5-Zoll-TFT-LCD-Anzeigmodul-480x320-ILI9486-16-bit-fur-Mega2560/143547189141?_trkparms=aid%3D1110004%26algo%3DSPLICE.COMP%26ao%3D1%26asc%3D225116%26meid%3D4f4de6aac671467a883ee6248760d6eb%26pid%3D100008%26rk%3D1%26rkt%3D12%26mehot%3Dlo%26sd%3D323552931467%26itm%3D143547189141%26pmt%3D1%26noa%3D0%26pg%3D2047675%26algv%3Ddefault%26brand%3DMarkenlos&_trksid=p2047675.c100008.m2219

Im folgenden Beitrag kommt noch ein Bild mit den Pin Bezeichnungen auf 
der Platine.

Das Ganze steckt auf einem Mega2560, die Pin Bezeichnungen entsprechen 
leider nicht dem Datenblatt: 
https://www.displayfuture.com/Display/datasheet/controller/ILI9486L.pdf

Hier ist mein Code der das Display ausschalten sollte: (Nach einstecken 
ist es komplett weiß)
1
#define F_CPU 16000000
2
#define DB0 PC0
3
#define DB1 PC1
4
#define DB2 PC2
5
#define DB3 PC3
6
#define DB4 PC4
7
#define DB5 PC5
8
#define DB6 PC6
9
#define DB7 PC7
10
#define DB8 PA0
11
#define DB9 PA1
12
#define DB10 PA2
13
#define DB11 PA3
14
#define DB12 PA4
15
#define DB13 PA4
16
#define DB14 PA5
17
#define DB15 PA6
18
#define WRX PG2
19
#define RDX PD7
20
#define RST PG0
21
#define DCX PG1
22
23
#include <avr/io.h>
24
#include <util/delay.h>
25
void writeCmd(uint16_t *Data);
26
void readInternal(uint16_t *Data);
27
void writePar(uint16_t *Data);
28
void readPar(uint16_t *Data);
29
void setData(uint16_t *Data);
30
31
int main(void)
32
{
33
  DDRC = 0xff; //Databus
34
  DDRA = 0xff; //Databus
35
  DDRG = 0x07; // RST, DCX, WRX
36
  DDRD = 0x80; //RDX 
37
  
38
  //Resetdevice
39
  PORTG |= (1<<RST);
40
  _delay_ms(100);
41
  PORTG &=~ (1<<RST);
42
  _delay_ms(300);
43
  
44
  //Alle Signale auf High
45
  PORTG |= (1<<RST);
46
  PORTG |= (1<<DCX);
47
  PORTG |= (1<<WRX);
48
  PORTD |= (1<<RDX);
49
  
50
  uint16_t command;
51
  uint16_t dataSend;
52
  
53
  command = 0x01; //Softwarereset
54
  writeCmd(&command);
55
  _delay_ms(5);
56
  
57
    while (1) 
58
    {
59
    command = 0x28; //display off
60
    writeCmd(&command);
61
    }
62
}
63
64
void writeCmd(uint16_t *Data){
65
  //WRX steigende Flanke, RDX High, DCX low
66
  PORTG &=~ (1<<DCX);
67
  PORTG &=~ (1<<WRX);
68
  setData(Data);
69
  _delay_ms(2);
70
  PORTG |= (1<<WRX);
71
  _delay_ms(2);
72
  PORTG |= (1<<DCX);
73
}
74
void readInternal(uint16_t *Data){
75
  //WRX high, RDX steigende Flanke, DCX high
76
  PORTD &=~ (1<<RDX);
77
  setData(Data);
78
  _delay_ms(2);
79
  PORTD |= (1<<RDX);
80
  _delay_ms(2);
81
}
82
void writePar(uint16_t *Data){
83
  //WRX steigende Flanke, RDX high, DCX high
84
  PORTG &=~ (1<<WRX);
85
  setData(Data);
86
  _delay_ms(2);
87
  PORTG |= (1<<WRX);
88
  _delay_ms(2);
89
}
90
void readPar(uint16_t *Data){
91
  //WRX High, RDX steigende Flanke, DCX high
92
  PORTD &=~ (1<<RDX);
93
  setData(Data);
94
  _delay_ms(2);
95
  PORTD |= (1<<RDX);
96
  _delay_ms(2);
97
}
98
99
void setData(uint16_t *Data){
100
  PORTC = (*Data & 0xff);
101
  PORTA = ((*Data >> 8) & 0xff);
102
}


Ich hoffe auf Tipps und gute Ratschläge.

Viele Grüße
Martin

von M. (Gast)


Angehängte Dateien:

Lesenswert?

Die Belegung.

von Arduinoquäler (Gast)


Lesenswert?

Martin schrieb:
> Ich hoffe auf Tipps und gute Ratschläge.

Selbst wenn dein Display hell (weiss?) ist muss es nicht
eingeschaltet sein, da die Hintergrund-LEDs immer leuchten.
Ein einfaches Off-Kommando muss also nichts bewirken.

Versuche dich erst mal an einer korrekten Initialisierungs-
Sequenz und danach ein wechselweises Ein- und Aussschalten,
dann wirst du (bei korrekter Ansteuerung) einen leichten
Helligkeits-Wechsel im Leuchtschimmern erkennen können.

von Arduinoquäler (Gast)


Lesenswert?

Die
1
_delay_ms(2);

solltest du zu _delay_us machen sonst wirst du irgendwann ewig warten.

Diese kurzen Delays sind für das Display durchaus ausreichend.

von Arduinoquäler (Gast)


Lesenswert?

M. schrieb:
> Die Belegung.

Die Pins abzuzählen bin ich zu faul. Es ist nicht klar wo Pin 1 ist.

Bei dir fehlt offensichtlich die Bedienung des CS (Chip Select)
Pins, allerdings kann ich mich täuschen da nicht alle Bezeichnungen
auf deinen Foto mit denen im Programmcode übereinstimmen.

Bringe mal die Pin-Bezeichnungen mit dem Programmcode zusammen
und zeige nochmals einen Update.

von Martin (Gast)


Lesenswert?

Arduinoquäler schrieb:

> Versuche dich erst mal an einer korrekten Initialisierungs-
> Sequenz und danach ein wechselweises Ein- und Aussschalten,
> dann wirst du (bei korrekter Ansteuerung) einen leichten
> Helligkeits-Wechsel im Leuchtschimmern erkennen können.

Was ist denn die richtige Initialisierungssequenz? Im DS konnte ich nur 
entdecken, dass der Resetpin einmal auf Low und dann wieder high gezogen
werden soll. Gibts da irgendwo ein Kapitel was nicht gerade Init.. 
heißt?

Arduinoquäler schrieb:
> Die
> _delay_ms(2);
>
> solltest du zu _delay_us machen sonst wirst du irgendwann ewig warten.
>
> Diese kurzen Delays sind für das Display durchaus ausreichend.

Ist bewusst länger um auf jeden Fall die richtigen Pegel anliegend zu 
haben, wenn es dann richtig benutzt wird werden aus den ms auch us

Arduinoquäler schrieb:
> M. schrieb:
>> Die Belegung.
>
> Die Pins abzuzählen bin ich zu faul. Es ist nicht klar wo Pin 1 ist.
>
> Bei dir fehlt offensichtlich die Bedienung des CS (Chip Select)
> Pins, allerdings kann ich mich täuschen da nicht alle Bezeichnungen
> auf deinen Foto mit denen im Programmcode übereinstimmen.
>
> Bringe mal die Pin-Bezeichnungen mit dem Programmcode zusammen
> und zeige nochmals einen Update.

Unten nochmal mit den kommentierten Pins, ich habe mich in der SW an die 
Bezeichnungen aus dem DS gehalten. (Steht jetzt hinter den Defines 
dabei) der Chipselect wird gesetzt. Die Pinbezeichnung steht im Define 
(PG0, PG1, PG2, PD7 und die kompletten A und C Ports.

1
#define F_CPU 16000000
2
#define DB0 PC0
3
#define DB1 PC1
4
#define DB2 PC2
5
#define DB3 PC3
6
#define DB4 PC4
7
#define DB5 PC5
8
#define DB6 PC6
9
#define DB7 PC7
10
#define DB8 PA0
11
#define DB9 PA1
12
#define DB10 PA2
13
#define DB11 PA3
14
#define DB12 PA4
15
#define DB13 PA4
16
#define DB14 PA5
17
#define DB15 PA6
18
#define WRX PG2 //WR
19
#define RDX PD7 //RS
20
#define RST PG0 //RST
21
#define DCX PG1 //CS
22
23
#include <avr/io.h>
24
#include <util/delay.h>
25
void writeCmd(uint16_t *Data);
26
void readInternal(uint16_t *Data);
27
void writePar(uint16_t *Data);
28
void readPar(uint16_t *Data);
29
void setData(uint16_t *Data);
30
31
int main(void)
32
{
33
  DDRC = 0xff; //Databus
34
  DDRA = 0xff; //Databus
35
  DDRG = 0x07; // RST, DCX, WRX
36
  DDRD = 0x80; //RDX 
37
  
38
  //Resetdevice
39
  PORTG |= (1<<RST);
40
  _delay_ms(100);
41
  PORTG &=~ (1<<RST);
42
  _delay_ms(300);
43
  
44
  //Alle Signale auf High
45
  PORTG |= (1<<RST);
46
  PORTG |= (1<<DCX);
47
  PORTG |= (1<<WRX);
48
  PORTD |= (1<<RDX);
49
  
50
  uint16_t command;
51
  uint16_t dataSend;
52
  
53
  command = 0x01; //Softwarereset
54
  writeCmd(&command);
55
  _delay_ms(5);
56
    while(1){
57
    command = 0x28; //display off
58
    writeCmd(&command);
59
    }
60
}
61
62
void writeCmd(uint16_t *Data){
63
  //WRX steigende Flanke, RDX High, DCX low
64
  PORTG &=~ (1<<DCX);
65
  PORTG &=~ (1<<WRX);
66
  setData(Data);
67
  _delay_ms(2);
68
  PORTG |= (1<<WRX);
69
  _delay_ms(2);
70
  PORTG |= (1<<DCX);
71
}
72
void readInternal(uint16_t *Data){
73
  //WRX high, RDX steigende Flanke, DCX high
74
  PORTD &=~ (1<<RDX);
75
  setData(Data);
76
  _delay_ms(2);
77
  PORTD |= (1<<RDX);
78
  _delay_ms(2);
79
}
80
void writePar(uint16_t *Data){
81
  //WRX steigende Flanke, RDX high, DCX high
82
  PORTG &=~ (1<<WRX);
83
  setData(Data);
84
  _delay_ms(2);
85
  PORTG |= (1<<WRX);
86
  _delay_ms(2);
87
}
88
void readPar(uint16_t *Data){
89
  //WRX High, RDX steigende Flanke, DCX high
90
  PORTD &=~ (1<<RDX);
91
  setData(Data);
92
  _delay_ms(2);
93
  PORTD |= (1<<RDX);
94
  _delay_ms(2);
95
}
96
97
void setData(uint16_t *Data){
98
  PORTC = (*Data & 0xff);
99
  PORTA = ((*Data >> 8) & 0xff);
100
}

von Andreas S. (Gast)


Lesenswert?


von Arduinoquäler (Gast)


Lesenswert?

Martin schrieb:
> Unten nochmal mit den kommentierten Pins, ich habe mich in der SW an die
> Bezeichnungen aus dem DS gehalten. (Steht jetzt hinter den Defines
> dabei) der Chipselect wird gesetzt. Die Pinbezeichnung steht im Define
> (PG0, PG1, PG2, PD7 und die kompletten A und C Ports.

Martin schrieb:
> #define RDX PD7 //RS

Es gibt bei deinem Modul kein Read-Signal, das Modul ist nur
beschreibbar (das was dein Foto an Information hergibt).

In diesem Define ist das Signal C/D (Command/Data), hier auch
RS (Register Select) versteckt (wir mal so, mal so bezeichnet).

Dieses RS musst du bei Command und Data Write Vorgängen korrekt
bedienen, zusätzlich zum CS-Signal.

Ich sehe das RDX bei dir allerdings benutzt um zu lesen.

von Martin (Gast)


Lesenswert?

Andreas S. schrieb:
> Schau mal hier:
>
> http://www.lcdwiki.com/3.5inch_Arduino_Display-Mega2560
> 
https://www.yourduino.ru/product/32-tft-lcd-displey-ultra-hd-320x480-dlya-mega-2560-r3-3

Also demnach ist meine Pinbelegung richtig.
Eine Initialisierungsroutine kann ich dort aber auch nicht finden, evtl. 
verbirgt sie sich irgendwo in den Arduino samples, aber ich wollte es 
schon gerne ohne die Arduino Umgebung hinbekommen. Im DS müsste es ja 
auch eig einen Hinweis dazu geben, den ich leider nicht finde.

von Arduinoquäler (Gast)


Lesenswert?

Martin schrieb:
> Was ist denn die richtige Initialisierungssequenz?

Das ist ein Schlauch von Kommando- und Datenbytes wie er
an verschiedenen Stellen im Internet zu finden ist.

von Arduinoquäler (Gast)


Lesenswert?

Martin schrieb:
> Also demnach ist meine Pinbelegung richtig.

Aber das RS Handling nicht!

von Arduinoquäler (Gast)


Angehängte Dateien:

Lesenswert?

Arduinoquäler schrieb:
> Das ist ein Schlauch von Kommando- und Datenbytes wie er
> an verschiedenen Stellen im Internet zu finden ist.

So wie im Anhang z.B. ....

von Martin (Gast)


Lesenswert?

Arduinoquäler schrieb:
> Martin schrieb:
>> Was ist denn die richtige Initialisierungssequenz?
>
> Das ist ein Schlauch von Kommando- und Datenbytes wie er
> an verschiedenen Stellen im Internet zu finden ist.

Ich finde keinen, kannst gerne einen Link hier rein stellen, du scheinst 
ja zu wissen wo es die gibt?

Arduinoquäler schrieb:
> Martin schrieb:
>> Also demnach ist meine Pinbelegung richtig.
>
> Aber das RS Handling nicht!

Woran machst du das fest? Laut DS S. 27 ist bei write befehlen RS high. 
Ich setze vor der While alle Signale auf High. In der void writecmd und 
void writePar wird daher RS garnicht erst angefasst. Nach verlassen der 
voids sind immer alle Pegel wieder auf high.

von Arduinoquäler (Gast)


Lesenswert?

Martin schrieb:
> Woran machst du das fest?

Solange du dich weigerst in deiner Source die Pin-Bezeichnungen
deines Modules zu verwendet reden wir aneinander vorbei.

Ich halte daran fest dass du RS (Register Select) und/oder
CS (Chip Select) nicht richtig bedienst.

Register Select unterscheidet Command und Data.
Chip Select beginnt einen Schreib-Zylklus und beendet ihn.

Martin schrieb:
> Ich finde keinen,

[ ] Du liest alle meine Beiträge
[ ] Dir ist egal was ich sonst schreibe

Wenn man eine Suchmaschine bemüht findet man jede Menge
"ili9486 init sequence"

von Martin (Gast)


Angehängte Dateien:

Lesenswert?

Arduinoquäler schrieb:
> Martin schrieb:
>> Woran machst du das fest?
>
> Solange du dich weigerst in deiner Source die Pin-Bezeichnungen
> deines Modules zu verwendet reden wir aneinander vorbei.
>
> Ich halte daran fest dass du RS (Register Select) und/oder
> CS (Chip Select) nicht richtig bedienst.
>
> Register Select unterscheidet Command und Data.
> Chip Select beginnt einen Schreib-Zylklus und beendet ihn.
>
> Martin schrieb:
>> Ich finde keinen,
>
> [ ] Du liest alle meine Beiträge
> [ ] Dir ist egal was ich sonst schreibe
>
> Wenn man eine Suchmaschine bemüht findet man jede Menge
> "ili9486 init sequence"

Ich hab dir jetzt nochmals das Signal umbenannt, in CSX. Also wie im DS.
1
#define WRX PG2 //WR <- Bezeichnung Platine
2
#define RDX PD7 //RS <- Bezeichnung Platine
3
#define RST PG0 //RST <- Bezeichnung Platine
4
#define CSX PG1 //CS <- Bezeichnung Platine

Hier siehst du auch wie sie auf der Platine genannt sind und wie sie eig 
heißen sollten laut Datenblatt.

und die Voids dazu:
1
void writeCmd(uint16_t Data){
2
  //WRX steigende Flanke, RDX High, CSX low
3
  PORTG &=~ (1<<CSX);
4
  PORTG &=~ (1<<WRX);
5
  setData(Data);
6
  _delay_us(2);
7
  PORTG |= (1<<WRX);
8
  _delay_us(2);
9
  PORTG |= (1<<CSX);
10
}
11
void readInternal(uint16_t Data){
12
  //WRX high, RDX steigende Flanke, CSX high
13
  PORTD &=~ (1<<RDX);
14
  setData(Data);
15
  _delay_us(2);
16
  PORTD |= (1<<RDX);
17
  _delay_us(2);
18
}
19
void writePar(uint16_t Data){
20
  //WRX steigende Flanke, RDX high, CSX high
21
  PORTG &=~ (1<<WRX);
22
  setData(Data);
23
  _delay_us(2);
24
  PORTG |= (1<<WRX);
25
  _delay_us(2);
26
}
27
void readPar(uint16_t Data){
28
  //WRX High, RDX steigende Flanke, CSX high
29
  PORTD &=~ (1<<RDX);
30
  setData(Data);
31
  _delay_us(2);
32
  PORTD |= (1<<RDX);
33
  _delay_us(2);
34
}
35
36
void setData(uint16_t Data){
37
  PORTC = (Data & 0xff);
38
  PORTA = ((Data >> 8) & 0xff);
39
}

Außerdem habe ich nochmal den DS angehängt, ich würde weiterhin sagen, 
dass dort kein Fehler ist.
Die Pegel von RST, RDX, CSX, WRX werden vor dem ersten Aufruf auf High 
gesetzt.

Ich habe jetzt 2 Initalisierungsabläufe ausprobiert (die sich sehr 
unterscheiden), funktionieren beide nicht.

von Andreas S. (Gast)


Lesenswert?

Dann nimm doch die Sourcen als Beispiele und schau Dir dort
an wie es gemacht wird.
Man muss das Rad nicht zweimal erfinden.

von Martin (Gast)


Lesenswert?

Andreas S. schrieb:
> Dann nimm doch die Sourcen als Beispiele und schau Dir dort
> an wie es gemacht wird.
> Man muss das Rad nicht zweimal erfinden.

Ich finde dort leider keine Initialisierung. Alles mögliche zum Zeichnen 
aber keine Init. Kannst du mir bitte einen genaueren Ort nennen?

von Franz M. (elmo64)


Lesenswert?

Martin schrieb:
> Ich finde dort leider keine Initialisierung. Alles mögliche zum Zeichnen
> aber keine Init. Kannst du mir bitte einen genaueren Ort nennen?

Appnote mit initialisierung:
https://www.jameco.com/Jameco/Products/ProdDS/2278271.pdf

Im Forum müssten für dich relevannte Threats vorhanden sein.


Arduinoquäler schrieb:
> Die
> _delay_ms(2);
>
> solltest du zu _delay_us machen sonst wirst du irgendwann ewig warten.
>
> Diese kurzen Delays sind für das Display durchaus ausreichend.

Ich kann zwar nur zum ILI9341 (sind alle ähnlich) eine Aussage machen, 
aber der kommt bei mir mit einem Atmega328@20MHz, wenn man von der 
Initialisierung absieht, sogar ganz ohne delays zurecht.

Martin schrieb:
> Woran machst du das fest? Laut DS S. 27 ist bei write befehlen RS high.

Ich rate dir eher zu den detailierteren Grafiken, wie zum Beispiel auf 
S.28/29.

: Bearbeitet durch User
von Arduinoquäler (Gast)


Lesenswert?

Martin schrieb:
> Ich finde dort leider keine Initialisierung. Alles mögliche zum Zeichnen
> aber keine Init. Kannst du mir bitte einen genaueren Ort nennen?

Es ist wirklich unglaublich was da abgeht. Entweder bist du blind
oder völlig beratunsgresistent.

Arduinoquäler schrieb:
> So wie im Anhang z.B. ....

-----------------------------------------------------------------

Martin schrieb:
> Woran machst du das fest? Laut DS S. 27 ist bei write befehlen RS high.

Das ist auch so eine beratunsgresistente Darstellung, und sie
ist auch falsch. Ein einzelnes nacktes Kommando wird mit RS=1
geschrieben. Wenn das Kommando jedoch noch Daten als Folge-
parameter braucht dann wird danach noch RS=0 zum Schreiben
von Daten verlangt!

Ich schlage vor du schreibst nach deinem Gusto genau zwei
Funktionen WriteCmd() und WriteData() in denen du explizit die
Signale CS, WR, und RS korrekt in Abfolge setzt und diese beiden
Funktionen dann in einer Initialisierung verwendest.

Ich jedenfalls sehe in deinen Darstellungen von Sourcen keinerlei
Veränderung am Signal RS wenn du eine Abfolge von Kommando und
wechselweise Daten schreiben willst/sollst.

Deine readPar und writePar Funktionen löschst du einfach mal ganz.
Und lasse endlich das RDX weg, dieses Signal gibt es bei deinem
Display nicht.

Oh my god!

von Michael U. (amiga)


Lesenswert?

Hallo,

vielleicht mal allgemein: diese Displaycontroller sind sich ziemlich 
ähnlich,was die Ansteuerung betriftt. Datenpins, 8 oder 16, die 16Bit 
können auch oft im 8Bit-Mode betrieben werden, um Pins zu sparen.
CS als ChipSelect, manchmal auch CE ChipEnable zur Aktivierung des 
Controllers, fall mehrere am Bus hängen. mUß fast immer bedient werden, 
weil der Displaycontroller mit inaktiv werden von CS/CE erst die 
Abarbeitung macht. RS (RegisterSelect), auch C/D für Command/Daten 
Auswahl, ob ein Command- oder Datenbyte anliegt. Rd, WR oder RD/WR kann 
einzeln oder kombiniert oder garnicht vorhanden sein, Wenn der 
Controllertyp nicht gelesen werden kann, gibt es das auch nicht, ob RW 
unbd WR einzeln oder kombiniert hängt davon ab, on der alte 8080 oder 
der 6800 Bus Pate gestanden hat.
Für die genaue Abfolge gibt es in den Datenblättern immer 
Timingdiagramme, für das ILI9486L in meinem Datenblatt z.B. auf Seite 
212 für das 18/16/9( Bit Timing im 8080 Mode.

D/C richtig setzen, CS auf Low, Daten anlegen, WR auf Low, WR auf H (ab 
hier werden die Daten übernommen), CS auf H Zyklus Ende.
Lesezyklus ist auch angeben.
Zeiten beachten, besonders der Lesezyklus ist recht langsam.
Der ILI9486L kann auch SPI, spart Pins, hängt aber davon ab, ob man das 
Display als Board hat und alles Pins entsprechend beschalten kann oder 
ob es z.B. ein Arduino Shiled ist, wo der Hersteller schon vorverdrahtet 
hat und man die Betriebsart nehmen muß, die er gern wollte.
Parallelbeteieb macht an den kleinen AVR Sinn, damit es halbwegs schnell 
bedient werden kann, an einen ESP8266/ESP32 nehme ich generell nur SPI, 
das kann da schnell genug.
Der Kommandosatz ist im Datenblatt beschrieben, hilft aber nur bedingt, 
weil es viele Abhängigkeiten der Einstellung gibt, um es überhautpt 
erstmal in einen sinnvollen Zusatand zu bringen.
Irgendwo hat der Hersteller normalerweise auch Applikations-Dokus, mit 
Beispielen, sind teilweise schwer zu finden, so das man meist auf das 
zurückgreift, was ein anderer schon gemacht hat.
Ich habe mich vor Ewigleiten mal durch den T6963C gewühlt, weil es für 
die AVR noch nicht viel dafür gab. Vorteil für mich ist: ich finde mich 
heute relativ schnell durch ein Controller-Datenblatt durch, um was 
bestimmtes zu finden.
Freiwillig nochmal würde ich das aber bei einem Controller wie dem 
ILI9486L heutzutage nicht mehr machen, was kleines wie die einfarbigen 
OLED ja, aber das kostet auch schon mehr Zeit als mir lieb ist.

Gruß aus Berlin
Michael

von Martin (Gast)


Lesenswert?

A. M. schrieb:
> Martin schrieb:
> Ich finde dort leider keine Initialisierung. Alles mögliche zum Zeichnen
> aber keine Init. Kannst du mir bitte einen genaueren Ort nennen?
>
> Appnote mit initialisierung:
> https://www.jameco.com/Jameco/Products/ProdDS/2278271.pdf
>

> Das ist auch so eine beratunsgresistente Darstellung, und sie
> ist auch falsch. Ein einzelnes nacktes Kommando wird mit RS=1
> geschrieben. Wenn das Kommando jedoch noch Daten als Folge-
> parameter braucht dann wird danach noch RS=0 zum Schreiben
> von Daten verlangt!

Das steht doch auch beides in der Grafik die aus dem Datenblatt stammt! 
Da ist einmal Commando und Parameter. Wo sich RDX unterscheidet.

> Ich schlage vor du schreibst nach deinem Gusto genau zwei
> Funktionen WriteCmd() und WriteData() in denen du explizit die
> Signale CS, WR, und RS korrekt in Abfolge setzt und diese beiden
> Funktionen dann in einer Initialisierung verwendest.
>
> Ich jedenfalls sehe in deinen Darstellungen von Sourcen keinerlei
> Veränderung am Signal RS wenn du eine Abfolge von Kommando und
> wechselweise Daten schreiben willst/sollst.
>
> Deine readPar und writePar Funktionen löschst du einfach mal ganz.
> Und lasse endlich das RDX weg, dieses Signal gibt es bei deinem
> Display nicht.
>
> Oh my god!

Natürlich gibt es RDX, es gibt kein RS, das hat sich irgendwer 
ausgedacht, der die Platine beschriftet hat. Im Datenblatt ist immer von 
RDX die Rede, daher wird es auch weiterhin so in der SW heißen. RS gibt 
es nicht, ob my god! Lass es doch bitte einfach hier zu schreiben, 
bisher warst du 0 hilfreich.

von Martin (Gast)


Lesenswert?

A. M. schrieb:
> Martin schrieb:
> Ich finde dort leider keine Initialisierung. Alles mögliche zum Zeichnen
> aber keine Init. Kannst du mir bitte einen genaueren Ort nennen?
>
> Appnote mit initialisierung:
> https://www.jameco.com/Jameco/Products/ProdDS/2278271.pdf
>

Danke, der Link sieht hilfreich und offiziell aus. Merkwürdig dass zum 
Beispiel F2 nicht im Datenblatt als Kommando auftritt.

von Arduinoquäler (Gast)


Lesenswert?

Martin schrieb:
> Natürlich gibt es RDX, es gibt kein RS, das hat sich irgendwer
> ausgedacht, der die Platine beschriftet hat.

Oh my god!

Martin schrieb:
> Natürlich gibt es RDX

Ein RDX Signal (das ist der Lese-Strobe) ist auf deinem Board
nicht nach aussen geführt da du das Display nicht lesen kannst.
Die Buffer auf dem Board haben keine Richtungsumschaltung für
die Datenleitungen.


Martin schrieb:
> es gibt kein RS

Ein RS Signal (das ist der Data/Command Selector) brauchst du damit
du beim Schreiben in die Display-Register zwischen Daten und
Kommando unterscheiden kannst. Dieses Signal ist auch vorhanden.


Martin schrieb:
> Lass es doch bitte einfach hier zu schreiben,

Den Gefallen tu ich dir gerne.
Bei soviel Starrsinn und Beratungsresistenz bin ich dann mal weg.
Das hab ich schon lang nicht mehr erlebt.

von Martin (Gast)


Lesenswert?

Moin,
ich hab mich gerade nochmal rangesetzt und nun auch meinen Fehler 
gemerkt. Sorry für die harschen Worte vorher @Arduinoquäler, mir gehts 
momentan nicht so mega gut.

Ich hab nun verstanden das RSX ungleich RS und der RS im DS als DCX 
benannt ist. Ich habe nun die beiden write funktionen angepasst, laut 
http://www.lcdwiki.com/3.5inch_Arduino_Display-Mega2560 ist der RS/ DCX 
invertiert gegenüber dem Datenblatt. Ich habe beide Richtungen probiert, 
da passiert leider garnichts.

Folgend der aktuelle Stand, ich erwarte eigentlich 2000 farbige Pixel, 
davon ist leider nichts zu sehen. Auf den Signalleitungen ist allerdings 
viel traffic, die Timingzeiten überschreite ich auch bei weitem.
Als Initsequenz habe ich die erste aus der Appnote 
https://www.jameco.com/Jameco/Products/ProdDS/2278271.pdf übernommen. 
Testweise auch die 2. für den Treiber, macht aber bisweilen keinen 
Unterschied.
1
#define F_CPU 16000000
2
#define DB0 PC0
3
#define DB1 PC1
4
#define DB2 PC2
5
#define DB3 PC3
6
#define DB4 PC4
7
#define DB5 PC5
8
#define DB6 PC6
9
#define DB7 PC7
10
#define DB8 PA0
11
#define DB9 PA1
12
#define DB10 PA2
13
#define DB11 PA3
14
#define DB12 PA4
15
#define DB13 PA4
16
#define DB14 PA5
17
#define DB15 PA6
18
#define WRX PG2 //WR <- Bezeichnung Platine
19
#define DCX PD7 //RS <- Bezeichnung Platine invertiert zum DS
20
#define RST PG0 //RST <- Bezeichnung Platine
21
#define CSX PG1 //CS <- Bezeichnung Platine
22
23
#include <avr/io.h>
24
#include <util/delay.h>
25
void writeCmd(uint16_t Data);
26
void writePar(uint16_t Data);
27
void setData(uint16_t Data);
28
void init_ili9486();
29
30
int main(void)
31
{
32
  DDRC = 0xff; //Databus
33
  DDRA = 0xff; //Databus
34
  DDRG = 0x07; // DCXT, CSX, WRX
35
  DDRD = 0x80; //DCX 
36
  
37
  
38
  
39
  //Alle Signale auf High
40
  PORTG |= (1<<RST);
41
  PORTG |= (1<<CSX);
42
  PORTG |= (1<<WRX);
43
  PORTD |= (1<<DCX);
44
  _delay_ms(1);
45
  
46
  init_ili9486();
47
  
48
  
49
    while(1){
50
    PORTG |= (1<<CSX);
51
    PORTG |= (1<<WRX);
52
    PORTD |= (1<<DCX);
53
    _delay_ms(10);
54
    writeCmd(0x2c);
55
    for(int i = 0; i < 4000; i++){
56
      writePar(0x001f);
57
    }
58
    }
59
}
60
61
void init_ili9486(){
62
  //Reset LCD Driver
63
  PORTG &=~ (1<<RST); //Reset low
64
  _delay_ms(10);
65
  PORTG |= (1<<RST); //Reset high
66
  _delay_ms(120);
67
  
68
  
69
  //Initial Sequence https://www.jameco.com/Jameco/Products/ProdDS/2278271.pdf
70
  writeCmd(0xf2);
71
  writePar(0x18);
72
  writePar(0xA3);
73
  writePar(0x12);
74
  writePar(0x02);
75
  writePar(0xB2);
76
  writePar(0x12);
77
  writePar(0xff);
78
  writePar(0x10);
79
  writePar(0x00);
80
  
81
  writeCmd(0xF8);
82
  writePar(0x21);
83
  writePar(0x04);
84
  
85
  writeCmd(0xF9);
86
  writePar(0x00);
87
  writePar(0x08);
88
  
89
  writeCmd(0x36);
90
  writePar(0x08);
91
  
92
  writeCmd(0xb4);
93
  writePar(0x00);
94
  
95
  writeCmd(0xc1);
96
  writePar(0x41);
97
  
98
  writeCmd(0xc5);
99
  writePar(0x00);
100
  writePar(0x53);
101
  
102
  writeCmd(0xE0);
103
  writePar(0x0f);
104
  writePar(0x1B);
105
  writePar(0x18);
106
  writePar(0x0B);
107
  writePar(0x0E);
108
  writePar(0x09);
109
  writePar(0x47);
110
  writePar(0x94);
111
  writePar(0x35);
112
  writePar(0x0A);
113
  writePar(0x13);
114
  writePar(0x05);
115
  writePar(0x08);
116
  writePar(0x03);
117
  writePar(0x00);
118
  
119
120
  writeCmd(0xE1);
121
  writePar(0x0f);
122
  writePar(0x3A);
123
  writePar(0x37);
124
  writePar(0x0B);
125
  writePar(0x0C);
126
  writePar(0x05);
127
  writePar(0x4A);
128
  writePar(0x24);
129
  writePar(0x39);
130
  writePar(0x07);
131
  writePar(0x10);
132
  writePar(0x04);
133
  writePar(0x27);
134
  writePar(0x25);
135
  writePar(0x00);
136
  
137
  writeCmd(0x11);
138
  _delay_ms(120);
139
  writeCmd(0x29);    
140
}
141
142
143
144
void writeCmd(uint16_t Data){
145
// CS  Low, DCX  high -> command, WRX from low to high
146
  PORTG &=~ (1<<CSX);
147
  PORTG |= (1<<DCX); //high Level command 
148
  PORTG &=~ (1<<WRX);
149
  setData(Data);
150
  _delay_us(2);
151
  PORTG |= (1<<WRX);
152
  _delay_us(2);
153
}
154
155
void writePar(uint16_t Data){
156
//CS low, DCX low -> register, WRX from low to high
157
  PORTG &=~ (1<<CSX);
158
  PORTG &=~ (1<<DCX); //low level register
159
  PORTG &=~ (1<<WRX);
160
  setData(Data);
161
  _delay_us(2);
162
  PORTG |= (1<<WRX);
163
  _delay_us(2);
164
}
165
166
void setData(uint16_t Data){
167
  PORTC = (Data & 0xff);
168
  PORTA = ((Data >> 8) & 0xff);
169
}

von Franz M. (elmo64)


Lesenswert?

DCX

von Martin (Gast)


Lesenswert?

Für die Nachwelt, so funktioniert es. Vielen Dank an alle Tipps!

1
#define F_CPU 16000000
2
#define DB0 PC0
3
#define DB1 PC1
4
#define DB2 PC2
5
#define DB3 PC3
6
#define DB4 PC4
7
#define DB5 PC5
8
#define DB6 PC6
9
#define DB7 PC7
10
#define DB8 PA0
11
#define DB9 PA1
12
#define DB10 PA2
13
#define DB11 PA3
14
#define DB12 PA4
15
#define DB13 PA4
16
#define DB14 PA5
17
#define DB15 PA6
18
#define WRX PG2 //WR <- Bezeichnung Platine PG2
19
#define DCX PD7 //RS <- Bezeichnung Platine invertiert zum DS PD7
20
#define RST PG0 //RST <- Bezeichnung Platine PG0
21
#define CSX PG1 //CS <- Bezeichnung Platine PG1
22
23
#include <avr/io.h>
24
#include <util/delay.h>
25
void writeCmd(uint16_t Data);
26
void writePar(uint16_t Data);
27
void setData(uint16_t Data);
28
void init_ili9486();
29
30
int main(void)
31
{
32
  DDRC = 0xff; //Databus
33
  DDRA = 0xff; //Databus
34
  DDRG = 0x07; // RST, CSX, WRX
35
  DDRD = 0x80; //DCX 
36
  
37
  
38
  
39
  //Alle Signale auf High
40
  PORTD |= (1<<DCX);
41
  PORTG |= (1<<CSX);
42
  PORTG |= (1<<WRX);
43
  PORTG |= (1<<RST);
44
  _delay_ms(1);
45
  
46
  init_ili9486();
47
  _delay_ms(1000);
48
  writeCmd(0x2c);
49
  for(unsigned long i = 0; i < 100000; i++){
50
      writePar(0xf0f0);
51
    }
52
53
    while(1){
54
55
    }
56
}
57
58
void init_ili9486(){
59
  //Reset LCD Driver
60
  PORTG &=~ (1<<RST); //Reset low
61
  _delay_ms(30);
62
  PORTG |= (1<<RST); //Reset high
63
  _delay_ms(120);
64
  
65
  
66
  //Initial Sequence https://www.jameco.com/Jameco/Products/ProdDS/2278271.pdf
67
  writeCmd(0xf2);
68
  writePar(0x18);
69
  writePar(0xA3);
70
  writePar(0x12);
71
  writePar(0x02);
72
  writePar(0xB2);
73
  writePar(0x12);
74
  writePar(0xff);
75
  writePar(0x10);
76
  writePar(0x00);
77
  
78
  writeCmd(0xF8);
79
  writePar(0x21);
80
  writePar(0x04);
81
  
82
  writeCmd(0xF9);
83
  writePar(0x00);
84
  writePar(0x08);
85
  
86
  writeCmd(0x36);
87
  writePar(0x08);
88
  
89
  writeCmd(0xb4);
90
  writePar(0x00);
91
  
92
  writeCmd(0xc1);
93
  writePar(0x41);
94
  
95
  writeCmd(0xc5);
96
  writePar(0x00);
97
  writePar(0x53);
98
  
99
  writeCmd(0xE0);
100
  writePar(0x0f);
101
  writePar(0x1B);
102
  writePar(0x18);
103
  writePar(0x0B);
104
  writePar(0x0E);
105
  writePar(0x09);
106
  writePar(0x47);
107
  writePar(0x94);
108
  writePar(0x35);
109
  writePar(0x0A);
110
  writePar(0x13);
111
  writePar(0x05);
112
  writePar(0x08);
113
  writePar(0x03);
114
  writePar(0x00);
115
  
116
117
  writeCmd(0xE1);
118
  writePar(0x0f);
119
  writePar(0x3A);
120
  writePar(0x37);
121
  writePar(0x0B);
122
  writePar(0x0C);
123
  writePar(0x05);
124
  writePar(0x4A);
125
  writePar(0x24);
126
  writePar(0x39);
127
  writePar(0x07);
128
  writePar(0x10);
129
  writePar(0x04);
130
  writePar(0x27);
131
  writePar(0x25);
132
  writePar(0x00);
133
  
134
  writeCmd(0x11);
135
  _delay_ms(120);
136
  writeCmd(0x29);    
137
}
138
139
140
141
void writeCmd(uint16_t Data){
142
// CS  Low, DCX  high -> command, WRX from low to high
143
  PORTG &=~ (1<<CSX);
144
  PORTD &=~ (1<<DCX); //high Level command 
145
  PORTG &=~ (1<<WRX);
146
  setData(Data);
147
  PORTG |= (1<<WRX);
148
}
149
150
void writePar(uint16_t Data){
151
//CS low, DCX low -> register, WRX from low to high
152
  PORTG &=~ (1<<CSX);
153
  PORTD |= (1<<DCX); //low level register
154
  PORTG &=~ (1<<WRX);
155
  setData(Data);
156
  PORTG |= (1<<WRX);
157
}
158
159
void setData(uint16_t Data){
160
  PORTC = (Data & 0xff);
161
  PORTA = ((Data >> 8) & 0xff);
162
}

von leo (Gast)


Lesenswert?

Martin schrieb:
> #define DB12 PA4
> #define DB13 PA4

Aha. Listen und Schleifen verwenden ist wohl zu viel Aufwand. Dann schon 
lieber einfache C&P-Fehler.

leo

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.