Mikrocontroller – Ein Leitfaden für Anfänger – Zahlen auf dem LCD anzeigen
Teilen
Microcontroller – Ein Leitfaden für Anfänger – Zahlen auf dem LCD-Display anzeigen
Wir wissen also, wie man Zeichen und sogar Zeichenketten auf dem LCD anzeigt. Das Nützlichste, was man auf dem LCD anzeigen könnte, wäre eine Zahl. Ich bin sicher, Sie denken jetzt, wir könnten einfach eine Zahl in Anführungszeichen übergeben, wie diese: "632" mit dem Befehl Send_A_String (den wir im letzten Tutorial erstellt haben)! Sicher, aber was ist, wenn es eine Zahl von einem Sensor ist, die in einer Variablen gespeichert ist, oder etwas Ähnliches! Wir wollen die Zahl tatsächlich in diesen Anführungszeichen haben, aber wie wir sie dorthin bekommen, ist, wo die Magie ins Spiel kommt... und es ist WIRKLICH einfach.
Wenn wir möchten, dass die Zahlen jedes Mal an denselben Stellen angezeigt werden (und nicht nur den gesamten Bildschirm mit einer Liste von Zahlen füllen), müssen wir den Cursor jedes Mal an die gewünschten Stellen verschieben, wenn wir die Zahl an das LCD senden möchten. Dies kann auch verwendet werden, um Zeichenketten und Zeichen zu lokalisieren.
Die Magie, den Cursor an jede beliebige Position auf dem LCD-Display zu bewegen, liegt in der Zahl 0x80. Diese Zahl repräsentiert die erste Position auf dem Display, in der oberen linken Ecke. Wenn Sie dem Binär-Tutorial aufmerksam gefolgt sind, wissen Sie, dass 0x80 im Binärsystem 0b10000000 darstellt. Die "1" befindet sich an der 8. Stelle, sodass volle 7 Ziffern für etwas Wunderbares übrig bleiben. 7 Binärziffern können 128 Zahlen (0-127) speichern.
Wie Sie bereits wissen, sind LCD-Bildschirme in viele Spalten und Zeilen unterteilt. Für das LCD im Tutorial gibt es 4 Zeilen und 20 Spalten, daher die 20x4, die normalerweise in der Beschreibung angezeigt wird. Addieren Sie sie alle, und Sie haben insgesamt 80 Positionen auf dem LCD. Hmm... 80 ist weniger als 128. Das sagt uns, dass es LCDs geben könnte, die mehr Zeilen und Spalten haben, da es so viele Möglichkeiten mit diesem Befehl gibt.
Wenn Sie einen Befehl mit Send_A_Command gesendet und 0x80 zur Verarbeitung durch das LCD eingefügt hätten, würde die Cursorposition oben links erscheinen. Wenn Sie 0x8A eingefügt hätten, wäre der Cursor 10 Leerzeichen rechts von der oberen linken Ecke positioniert. Er würde tatsächlich in der Mitte sein, da das LCD 20 Spalten breit ist. Aber es gibt einen Haken! Man könnte meinen, dass, wenn diese Zahl weiter ansteigen würde, der Cursor in die nächste Zeile umbrechen würde, aber das tut er nicht. Der Cursor springt stattdessen in die dritte Zeile. Dies liegt daran, wie die 128 reservierten Speicherplätze verwendet werden. Aufgrund der verschiedenen LCD-Anzeigen mit unterschiedlichen Zeilen- und Spaltenanzahlen beginnt die erste Zeile bei "0" und füllt die Zeilen 1 und 3 bis zur Zahl 63, was 1 minus der Hälfte von 128 ist. Jetzt fügt es sich zusammen, nicht wahr? Die 2. und 4. Zeile beginnen bei 64 und gehen bis zum Ende. Die Hälfte der 128 ist also für die erste und dritte Zeile reserviert, und die andere Hälfte ist für die zweite und vierte Zeile reserviert. Auf diese Weise beginnen alle LCDs auf der ersten Zeile bei 0 und auf der zweiten Zeile bei 64, selbst bei 2-Zeilen-LCDs.
Das macht viel Sinn, denn wenn Sie ein LCD mit nur zwei Zeilen hätten, die 64 Spalten lang wären (unter Verwendung aller 128 reservierten Positionen), wäre das LCD immer noch kompatibel mit einem LCD mit 2 Zeilen, aber nur 20 oder so Spalten. Sie könnten erwarten, dieselben Informationen auf dem LCD zu sehen, zumindest soweit das ausgewählte LCD betroffen ist.
Allerdings ist es so einfach, den Cursor an einer gewünschten Stelle zu positionieren, indem man eine Zahl zwischen 0 und 64 und 64 und 128 verwendet, ohne wirklich zu wissen, welche Zeile man beeinflusst. Wir können eine neue Routine erstellen, die es Ihnen ermöglicht, einfach die x- und y-Koordinaten anzugeben. Wenn Sie etwas auf der 4. Zeile und 6 Leerzeichen vom Anfang der Zeile anzeigen möchten, könnte dies wie folgt geschrieben werden: GotoLocation(6, 4); Das ist einfacher als die Angabe der Position in dieser Form: Send_A_Command(90); 90 (im Dezimal-, nicht im Hexadezimalsystem) ist zufällig diese Position auf einem 20x4 LCD-Display. 90 ergibt sich wie folgt: 64 ist die 2. Zeile. Die 2. Zeile bricht in die 4. Zeile um, indem 20 zu 64 addiert wird (20+64 = 84). Da Sie wissen, dass Sie sich in der 4. Zeile befinden, addieren Sie einfach 6 und Sie haben die Zahl 90. Aber vergessen Sie das alles, denn wir werden den einfachen Weg implementieren.
Das Erstellen einer Routine, bei der Sie nur die X- und Y-Komponente eingeben können, ist ziemlich einfach. Zuerst müssen Sie eine Variable erstellen, die alle anfänglichen Spaltennummern speichert. Im Falle des 20x4 LCDs sind die Zahlen 0 für die erste Zeile, 64 für die zweite Zeile, 20 für die dritte Zeile und 84 für die vierte Zeile. Die Variablendeklaration könnte so aussehen:
Ich verwende den Datentyp "char", da die Zahlen nicht so groß sind. Der Datentyp "char" kann von 0 bis 128 reichen. Der Variablenname "firstColumnPositionsForMrLCD" ist LANG. Dies ist tatsächlich beabsichtigt. Erstens für bewährte Programmierpraktiken und Lesbarkeit, und zweitens, damit die Möglichkeit, diesen Namen für eine andere Verwendung zu verwenden, später sehr unwahrscheinlich wäre. Denken Sie daran, wir werden diese Variable in einer anderen Datei als Bibliothek haben und wir werden sie nicht sehen (während wir in unserer Haupt-.c-Datei arbeiten), aber sie wird vorhanden sein. Die Zahlen zwischen den geschweiften Klammern sind die Anfangspositionen für jede Zeile. Auf diese Weise müssen wir nur die "Y"-Komponente in dieses Array einfügen, und es wird uns die Anfangsposition für diese Zeile mitteilen. Dann addieren wir die "X"-Komponente zu dieser Zahl, und wir haben die richtige Position auf dem LCD.
Das Array könnte auch etwas systematischer sein und so aussehen:
char firstColumnPositionsForMrLCD[4] = {0, 64, numberOfColumns , 64 + numberOfColumns };
Auf diese Weise müssten Sie nur die Anzahl der Spalten des LCDs angeben und Sie müssten nicht zu diesem unübersichtlichen Datenblatt (oder sollte ich sagen DatenBUCH) gehen. Nun, bewaffnet mit diesen glorreichen Anweisungen und neuem Wissen, von dem Sie dachten, Sie würden es nie erfahren, wie könnte die tatsächliche GotoLocation-Routine aussehen? Nun, hier ist sie:
{
Beachten Sie das 0x80... Das muss immer noch in Send_A_Command enthalten sein, da es der Befehl ist, der die erste Position darstellt. Dann ruft das Array die richtige Zahl auf und dann wird das "X" hinzugefügt. Sie haben vielleicht auch das y-1 und x-1 bemerkt. Dies wird hinzugefügt, weil das Array von 0 indiziert ist und die Bildschirmpositionen ebenfalls von 0 und nicht von 1 indiziert sind. Die kleine Subtraktion dient lediglich dazu, Zeile Nr. 1 "1" anstelle von "0" und Zeile Nr. 2 "2" anstelle von "1" und so weiter nennen zu können. Für das "X" nenne ich die erste Spalte gerne "1" und nicht "0". Es ist wie in Paris, alle ersten Stockwerke werden als Erdgeschoss oder "0"-Etage betrachtet und die Etage direkt darüber wird als erstes Stockwerk betrachtet. Nicht dass es falsch wäre, aber ich bin es einfach nicht gewohnt. Wenn Sie Ihre erste Spalte und erste Zeile als "0" bezeichnen möchten, entfernen Sie einfach die Subtraktion und Sie sind fertig.
Nun, zum Nachtisch. Eine numerische Variable auf dem LCD-Bildschirm anzeigen. Das Geheimnis
dabei ist, eine Funktion zu haben, die eine Zahl (numerische Variable) in
eine Zeichenfolge umwandelt. Wir wissen bereits, wie man eine Zeichenfolge auf dem LCD anzeigt, jetzt brauchen wir nur noch
eine Zeichenfolge, die die Zahl in einer Variablen darstellt. Glücklicherweise gibt es eine Funktion,
die bereits dafür erstellt wurde. Sie heißt
itoa und
dtostrf. Das "i" in itoa steht für Integer. Das "d" in dtostrf steht für double.
Sie wissen bereits, was ein Integer ist. Falls nicht, ist es einfach eine Zahl, die
keine Dezimalstellen hat. Sie haben vielleicht erraten, dass Double eine Zahl ist, die
Dezimalstellen enthalten kann. Double bezieht sich auf doppelte Genauigkeit. Beide Funktionen
konvertieren einen Wert in eine Zeichenfolge und erfordern die Einbindung der stdlib.h-Bibliothek ( #include
dtostr(double precision value, width, precision, string that will store the numbers);
Value ist entweder ein direkter Wert, der an dieser Stelle eingesetzt wird, oder eine Variable, die einen Wert enthält.
Width, das mit dtostrf verwendet wird, ist die Anzahl der Zeichen in der Zahl, die das Minuszeichen (-) enthält. Wenn die Zahl beispielsweise -532.87 ist, wäre die Breite 7, einschließlich des Minuszeichens und des Dezimalpunkts.
Precision ist die Anzahl der Zahlen nach dem Dezimalpunkt in der dtostrf-Verwendung.
Basis ist die maximale Anzahl der Werte pro Ziffer. Zum Beispiel steht 2 für die binäre Darstellung (2 mögliche Werte für jede Ziffer – 0 oder 1); 10 steht für das gebräuchliche menschliche Zahlensystem (10 mögliche Werte für jede Ziffer – 0, 1, 2, 3, 4, 5, 6, 7, 8 oder 9); 16 steht für Hexadezimal, wobei es 16 mögliche Werte für jede Ziffer gibt – 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E oder F. Es sollte verstanden werden, dass wenn die Basis größer ist, das Alphabet einfach größer wird.
String ist die Variable, die alphanumerische Zeichen wie ein Char-Array akzeptiert. Nachdem die Funktion ausgeführt wurde, enthält der String die Zahl, die im Array gespeichert ist. Wenn beispielsweise eine Integer-Variable die Zahl 643 enthält, enthält die String-Variable "634".
Diese Deklaration würde irgendwo im Programm stehen.
int x = 432;
Hier würden Sie die Zahl in die Zeichenfolge konvertieren:
Hier würden Sie die Zahl auf dem LCD anzeigen wollen:
Hier ist das gesamte Programm, das so ziemlich alle Routinen enthält, die wir für das LCD benötigen:
#include
#include
#define MrLCDsCrib PORTB
#define DataDir_MrLCDsCrib DDRB
#define MrLCDsControl PORTD
#define DataDir_MrLCDsControl DDRD
#define LightSwitch 5
#define ReadWrite 7
#define BiPolarMood 2
char firstColumnPositionsForMrLCD[4] = {0, 64, 20, 84};
void Check_IF_MrLCD_isBusy(void);
void Peek_A_Boo(void);
void Send_A_Command(unsigned char command);
void Send_A_Character(unsigned char character);
void Send_A_String(char *StringOfCharacters);
void GotoMrLCDsLocation(uint8_t x, uint8_t y);
int main(void)
{
Send_A_Command(0x01); //Clear Screen 0x01 = 00000001
_delay_ms(2);
Send_A_Command(0x38);
_delay_us(50);
Send_A_Command(0b00001110);
_delay_us(50);
char positionString[4];
while(1)
{
{
{
itoa(x, positionString, 10);
GotoMrLCDsLocation(12, 3);
Send_A_String("X = ");
Send_A_String(positionString);
itoa(y, positionString, 10);
GotoMrLCDsLocation(12, 4);
Send_A_String("Y = ");
Send_A_String(positionString);
GotoMrLCDsLocation(x, y);
Send_A_String("x");
_delay_ms(50);
GotoMrLCDsLocation(x, y);
Send_A_String(" ");
itoa(x, positionString, 10);
GotoMrLCDsLocation(12, 3);
Send_A_String(" ");
itoa(y, positionString, 10);
GotoMrLCDsLocation(12, 4);
Send_A_String(" ");
void Check_IF_MrLCD_isBusy()
{
MrLCDsControl |= 1<
while (MrLCDsCrib >= 0x80)
{
DataDir_MrLCDsCrib = 0xFF; //0xFF means 0b11111111
void Peek_A_Boo()
{
asm volatile ("nop");
MrLCDsControl &= ~1<
void Send_A_Command(unsigned char command)
{
MrLCDsCrib = command;
MrLCDsControl &= ~ ((1<
MrLCDsCrib = 0;
void Send_A_Character(unsigned char character)
{
MrLCDsCrib = character;
MrLCDsControl &= ~ (1<
MrLCDsCrib = 0;
void Send_A_String(char *StringOfCharacters)
{
{
void GotoMrLCDsLocation(uint8_t x, uint8_t y)
{