Hallo erstmal :D
Ich verwende den Arduino Mega 2560 und Atmel Studio für die
Programmierung. Ich will nun einen LCD (HD44780) verwenden und es
funktioniert nun auch alles perfekt. Alle Buchstaben und Zeichen werden
korrekt dargestellt, Cursor durch DDRAM Adressierung auf bestimmte
Positionen setzten, Bildschirm löschen, etc...
Jedoch will ich nun auch eigene Symbole darstellen und die im CGRam
speichern. Die dafür notwendigen Adressen beginnen ja ab 0x40 (Hex) bzw.
64 (Decimal) bzw. 0100 0000 in Bit darstellen (Databit 7 bis Databit 0)
und enden bei Startadresse + 64 Bit. Wenn ich nun aber den Befehl für
"Set CGRam address" dem LCD übergebe, also RS = 0; RW = 0; DB7 = 0; DB6
= 1; DB5 bis DB0 = 0 (für Startadresse des CGRam) dann reagiert der LCD
lediglich mit einem Cursor-Shift auf die Position 64 (Decimal) - Zeile
2, Spalte 1. Ist dies noch jemanden bekannt oder kann man sagen was hier
falsch ist? Wenn es irgendwas mit der Pin Belegung wäre, würden ja auch
die übergebenen Zeichen falsch dargestellt werden, dem aber nicht so
ist. Evntl. liegt es an der Programmierung....
LG
Set Ram Location:
1
// LCD data pin setup for CG RAM line address command
2
voidlcd_setCGRamLocation(int32_tlocation)
3
{
4
// Custom char address start at 64 (decimal) in CG RAM
5
set_HighLowToggle(lcd_db7,"low");
6
set_HighLowToggle(lcd_db6,"high");
7
8
if(location==1)
9
{
10
// Set CG RAM address to custom char 1 address
11
set_HighLowToggle(lcd_db5,"low");
12
set_HighLowToggle(lcd_db4,"low");
13
set_HighLowToggle(lcd_db3,"low");
14
set_HighLowToggle(lcd_db2,"low");
15
set_HighLowToggle(lcd_db1,"low");
16
set_HighLowToggle(lcd_db0,"low");
17
}
18
elseif(location==2)
19
{
20
// Set CG RAM address to custom char 2 address
21
set_HighLowToggle(lcd_db5,"low");
22
set_HighLowToggle(lcd_db4,"low");
23
set_HighLowToggle(lcd_db3,"high");
24
set_HighLowToggle(lcd_db2,"low");
25
set_HighLowToggle(lcd_db1,"low");
26
set_HighLowToggle(lcd_db0,"low");
27
}
28
elseif(location==3)
29
{
30
// Set CG RAM address to custom char 3 address
31
set_HighLowToggle(lcd_db5,"low");
32
set_HighLowToggle(lcd_db4,"high");
33
set_HighLowToggle(lcd_db3,"low");
34
set_HighLowToggle(lcd_db2,"low");
35
set_HighLowToggle(lcd_db1,"low");
36
set_HighLowToggle(lcd_db0,"low");
37
}
38
elseif(location==4)
39
{
40
// Set CG RAM address to custom char 4 address
41
set_HighLowToggle(lcd_db5,"low");
42
set_HighLowToggle(lcd_db4,"high");
43
set_HighLowToggle(lcd_db3,"high");
44
set_HighLowToggle(lcd_db2,"low");
45
set_HighLowToggle(lcd_db1,"low");
46
set_HighLowToggle(lcd_db0,"low");
47
}
48
elseif(location==5)
49
{
50
// Set CG RAM address to custom char 5 address
51
set_HighLowToggle(lcd_db5,"high");
52
set_HighLowToggle(lcd_db4,"low");
53
set_HighLowToggle(lcd_db3,"low");
54
set_HighLowToggle(lcd_db2,"low");
55
set_HighLowToggle(lcd_db1,"low");
56
set_HighLowToggle(lcd_db0,"low");
57
}
58
elseif(location==6)
59
{
60
// Set CG RAM address to custom char 6 address
61
set_HighLowToggle(lcd_db5,"high");
62
set_HighLowToggle(lcd_db4,"low");
63
set_HighLowToggle(lcd_db3,"high");
64
set_HighLowToggle(lcd_db2,"low");
65
set_HighLowToggle(lcd_db1,"low");
66
set_HighLowToggle(lcd_db0,"low");
67
}
68
elseif(location==7)
69
{
70
// Set CG RAM address to custom char 7 address
71
set_HighLowToggle(lcd_db5,"high");
72
set_HighLowToggle(lcd_db4,"high");
73
set_HighLowToggle(lcd_db3,"low");
74
set_HighLowToggle(lcd_db2,"low");
75
set_HighLowToggle(lcd_db1,"low");
76
set_HighLowToggle(lcd_db0,"low");
77
}
78
elseif(location==8)
79
{
80
// Set CG RAM address to custom char 8 address
81
set_HighLowToggle(lcd_db5,"high");
82
set_HighLowToggle(lcd_db4,"high");
83
set_HighLowToggle(lcd_db3,"high");
84
set_HighLowToggle(lcd_db2,"low");
85
set_HighLowToggle(lcd_db1,"low");
86
set_HighLowToggle(lcd_db0,"low");
87
}
88
}
Send Command to LCD:
1
// Entry write and command mode
2
set_HighLowToggle(lcd_rw,"low");
3
set_HighLowToggle(lcd_rs,"low");
4
5
// Set CG RAM address
6
lcd_setCGRamLocation(location);
7
8
// Flush pin to set address
9
set_HighLowToggle(lcd_es,"high");
10
set_HighLowToggle(lcd_es,"low");
Falls es noch Fragen gibt, einfach stellen... :D
Die Methode set_HigLowToggle ist lediglich zum Arduino Register
setzen....
> set_HighLowToggle(lcd_db7, "low");
Ich hab ja schon viele umständliche Routinen gesehen
die nichts anderes tun sollten als einen IO Pin zu setzen,
aber das ist echt der Hammer.
holger schrieb:>> set_HighLowToggle(lcd_db7, "low");>> Ich hab ja schon viele umständliche Routinen gesehen> die nichts anderes tun sollten als einen IO Pin zu setzen,> aber das ist echt der Hammer.
bitte auf mein Anliegen eingehen, solch Kommentare sind nicht sehr
produktiv oder weiß der "Profi" etwa warum das so gemacht wurde bzw. so
ausschaut?
Schmidolin schrieb:> holger schrieb:>>> set_HighLowToggle(lcd_db7, "low");>>>> Ich hab ja schon viele umständliche Routinen gesehen>> die nichts anderes tun sollten als einen IO Pin zu setzen,>> aber das ist echt der Hammer.>> bitte auf mein Anliegen eingehen, solch Kommentare sind nicht sehr> produktiv oder weiß der "Profi" etwa warum das so gemacht wurde bzw. so> ausschaut?
Nein.
Aber der Profi weiss, das man sich mit möglichst komplexen dubiosen
Funktionen immer nur selbst ins Knie schiesst.
Der Profi würde deine komplette Funktion so schreiben
1
lcd_command(LCD_SET_CGADR|(code<<3));
(code ist der Zeichencode für den die Bits definiert werden sollen)
und gut ists.
Tu dir selbst einen Gefallen und schreib dir erst mal ein paar
Hilfsfunktionen wie zb eine Funktion, der du ein Commandobyte übergibst
und welche dann die erforderlichen Aktionen ausführt um ein Kommando
(egal welches) an das LCD zu übergeben.
Dann ist schon mal der ganze Themenkreis "was kann ich bei der Übergabe
eines Kommandos alles falsch machen" insofern vom Tisch, als man das
einmalig richtig hinkriegt und egal ob das Kommando dann "Clear Screen"
oder eben "Set CGRAM Address" lautet, die Funktion, die ein Kommando
überträgt macht das dann richtig ohne dass man sich in jeder Funktion
wieder neu darum kümmern muss.
Organisation ist in der Programmierung das halbe Leben. Wer sich in
jeder Funktion wieder neu um den ganzen Kleinkram kümmern muss, hat
irgendwas nicht richtig verstanden.
int32_t?
Hast du auch nur den leistens Hauch eines Schimmers, was du deinem Mega
damit antust?
Es ist ja jetzt nicht wirklich so, dass LCD Routinen für ein
Standard-LCD rar gesäht wären. Warum studierst du nicht mal, wie andere
Leute so etwas programmieren? Durch Codestudium anderer kann man viel
lernen!
Die hier sind zwar nicht unbedingt der Weisheit letzter Schluss, aber an
und für sich ganz ordentlich aufgebaut.
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
Sieh dir vor allen Dingen an, wie sich die Verarbeitung in einzelne
Funktionshierarchien gliedert. Wie 'komplexere' Funktionen auf
'einfachere' Funktionen zurückgreifen um die Drecksarbeit erledigen zu
lassen und diese einfacheren Funktionen dann wieder auf noch tiefer
liegende Funktionen zurückgreifen um Aktionsblöcke ausführen zu lassen.
Und noch ein Tip:
Strings willst du nicht wirklich als 'Aktionscode' verwenden. Derartige
Kommandos benutzt man, wenn man über I/O Schnittstellen (zb UART) mit
einem anderen Computer kommunizert. Aber innerhalb eines Programms ist
so etwas unnötig. Da kostet dich die ganze Stringauswerterei mehr an
Laufzeit als alles andere zusammengenommen.
Wenn du in einem Programm sprechende Namen haben willst (was
grundsätzlich gut ist), dann versteck den Zahlenwert hinter einem
#define und gut ists.
Durch
1
#define LOW 0
2
#define HIGH 1
3
4
....
5
6
set_HighLowToggle(lcd_db7,LOW);
7
8
...
9
10
voidset_HighLowToggle(uint8_tbitNr,uint8_tvalue)
11
{
12
...
13
}
kannst du deinen µC schon mal massiv entlasten. Abgesehen davon, dass
eine derartige Unterscheidung nicht wirklich notwendig ist. Du weisst an
dieser Stelle, dass du den Pin auf Low haben willst. Es gibt keinen
Grund das unnötig zu verkomplizieren
1
set_PinLow(lcd_db7);
ist völlig ausreichend. Es erspart dir das Nachdenken darüber, wie du
der eierlegenden Wollmilchsau beibringst, dass du den Pin auf Low haben
willst und es erspart der Routine die Analyse darüber, was der Aufrufer
eigentlich will.
Thx für die antworten, das war sowieso das aller erste Programm mit dem
ich die Funktionsweise herausfinden wollte (das das nicht gerade sehr
effizient geschrieben ist, ist mir dabei schon klar) - so wie ich das
jetzt herausgefunden hab, macht man beim setzten der CG Ram Adresse
einen Cursor shift genau auf diese Adresse und kann den CG Ram
beschreiben. Setzt man nun das Bitmuster für die 8x5 lcd Zeilen springt
der Cursor natürlich pro gesetzter Zeile mit, da ja automatisch
inkrementiert wird. Das CG Ram Zeichen ist aber richtig gespeichert und
kann über vorheriges setzen der DD Ram Adresse und anschließendes
beschreiben wieder aufgerufen und dargeatellt werden. Das ein Cursor
shift beim setzen der CG Ram Adresse durchgeführt wird hat mich nur
verwirrt, da das nirgendwo beschrieben wird. Muss ich dann noch testen
ob das nur bei mir jetzt ein Fehler ist, oder auch bei anderen so ist.