Seltsame Ausgabe auf 16X2 JHD162A LCD-Display

Ich lerne die Schnittstelle von Atmega 16a mit 16X2 LCD. Ich habe eine Header-Datei für Routinen geschrieben, die häufig verwendet werden, und jedes Mal, wenn ich mit Atmega 16a eine Schnittstelle mit LCD herstellen möchte, verwende ich diese Header-Datei.

Hier ist meine LCD-Header-Datei:

#include<stdlib.h>
#include<avr/io.h>
#include<util/delay.h>
int cx=1;
int cy=1;
void LCD_Send(unsigned char c,unsigned char DC)
{

    if(DC==0)
    {
        PORTC=0x0F & (c>>4);
        PORTC=PORTC|(1<<5);
        _delay_ms(1);
        PORTC=PORTC & (~(1<<5));
        _delay_ms(1);
        PORTC=0x0F & (c);
        PORTC=PORTC | (1<<5);
        _delay_ms(1);
        PORTC=PORTC & (~(1<<5));
        _delay_ms(1);
    }
    else if(DC==1)
    {
        PORTC=0x0F & (c>>4);
        PORTC=PORTC | (1<<7);
        PORTC=PORTC|(1<<5);
        _delay_ms(1);
        PORTC=PORTC & (~(1<<5));
        _delay_ms(1);
        PORTC=0x0F & (c);
        PORTC=PORTC | (1<<7);
        PORTC=PORTC | (1<<5);
        _delay_ms(1);
        PORTC=PORTC & (~(1<<5));
        _delay_ms(1);
    }
    return ;
}
void LCD_init(void)
{
    DDRC=0b11101111;
    LCD_Send(0x01,0);
    LCD_Send(0x0F,0);
    LCD_Send(0x28,0);
    cx=1;cy=1;
    return ;
}
void LCD_Send_String(char* s)
{
    for(int i=0;s[i]!='\0';i++)
    {
        LCD_Send(s[i],1);
        if(cx==16)
        {
            cx=1;cy++;
            LCD_Send(0xC0,0);
        }
        else
        cx++;
    }
    return ;
}
void LCD_GotoXY(unsigned int x,unsigned int y)
{
    if(y==1)
    {
        char addr=0x80;
        addr=addr+(x-1);
        LCD_Send(addr,0);
    }
    else if(y==2)
    {
        char addr=0xC0;
        addr=addr+(x-1);
        LCD_Send(addr,0);
    }    
    cx=x; cy=y;
    return ;
}
void LCD_Print(int data,unsigned int x,unsigned int y)
{
    char string[10];
    LCD_GotoXY(x,y);
    itoa(data,string,10);
    LCD_Send_String(string);
    return ;
}

Hier sind RS, R/W und E jeweils PC7, PC6 und PC5, DB4, DB5, DB6, DB7 sind jeweils PC0, PC1, PC2, PC3. Ich verwende den 4-Bit-Modus für die Eingabe.

Hier ist meine main.c-Datei (der Code, der auf dem Mikroprozessor ausgeführt wird):

#include"lcd.h"
int main(void)
{
    LCD_init();
    char s[20]="1234567890123456789";
    LCD_Send_String(s);
    return 0;
}

Wenn ich den Speicher mit der HEX-Datei flashe und dann zurücksetze, zeigt das LCD gut an

Abbildung 1

Wenn ich dann später zurücksetze, werden Zufallsvariablen angezeigt (tatsächlich kann ich sehen, dass sich die zweite Zeile überhaupt nicht ändert, was bedeutet, dass der Bildschirm nicht gelöscht wird, aber ein Befehl geschrieben wurde, um den Bildschirm zu löschen) LCD_init().

Figur 2

Ich bin mir ziemlich sicher, dass mit dem Board und den Verbindungen nichts falsch ist, da es mit anderen Header-Dateien funktioniert. Ich bin mir ziemlich sicher, dass es sich um einen Fehler in meinem Code handelt. Ich wäre wirklich dankbar, wenn mir jemand helfen würde, diesen Code zu reparieren. Wenn ich ihn wieder zurücksetze, wird die richtige Sequenz wie im ersten Bild angezeigt

Was und wie setzt du es zurück?
Mit Reset meine ich, ich habe einen Kaltstart.
Sobald ich diese Werid-Ausgabe bekomme und dann wieder zurücksetze, kann ich den Bildschirm klar sehen und sehen, dass die richtige Sequenz wieder erscheint.
Sie sagen also, dass es nicht funktioniert, wenn Sie die Stromversorgung entfernen und wieder anschließen, aber wenn Sie nur das Mikro zurücksetzen, funktioniert es?
Nein, wenn ich es anschließe, funktioniert es richtig, wenn ich es zurücksetze, funktioniert es nicht und wenn ich es wieder zurücksetze, funktioniert es wieder. es funktioniert tatsächlich und funktioniert nicht im alternativen Muster
Versuchen Sie, als erstes in Ihrem Code eine Verzögerung von 100 ms hinzuzufügen, und sehen Sie, ob es funktioniert
Es funktioniert nicht, es hat den gleichen Fehler

Antworten (3)

Ihr Problem ist, dass das Display seinen Zustand während des MCU-Resets beibehält. Beim Kaltstart ist der anfängliche Datenmodus 8-Bit, den Sie sofort auf 4-Bit umschalten, der Daten mit einem Paar EN-Impulsen liest.

Wenn Sie die MCU zurücksetzen, wissen Sie nicht, ob gerade oder ungerade Anzahl von EN-Impulsen gesendet wurden. Sie müssen also das Display irgendwie zurücksetzen, auch wenn es keinen Reset-Pin hat.

Dies kann durch Senden von 0x33 0x33 erfolgen (im 8-Bit-Modus bedeutet dies, dass 4-mal auf 8-Bit umgeschaltet wird, im 4-Bit-Modus bedeutet dies, dass ein- oder zweimal auf 8-Bit umgeschaltet wird). Dann können Sie sicher sein, dass Sie immer vom gleichen Stand aus starten.

Fahren Sie dann mit dem regulären 0x32 (oder 4-Bit 0x02, wenn Sie eine einzelne 4-Bit-Schreibfunktion haben), 0x28 fort, um in den 4-Bit-2-Zeilen-Modus zu gelangen.

Wollen Sie LCD_Send(0x33,0) zweimal vor LCD_Send(0x01,0) schreiben?
Wie ich das HD44780-Datenblatt (S. 46) gelesen habe, müssen Sie 0x3 senden? (die ?-Bits spielen keine Rolle) 3 Mal, dann senden Sie 0x2?, und danach können Sie mit dem Senden von 8-Bit-Befehlen als zwei Nibbles beginnen. Dies entspricht dem Senden von 0x33 0x32 als Nibbles.
@WoutervanOoijen Ja, ich wollte nur zwei Dinge (in den 8-Bit-Modus zurückkehren und den 4-Bit-Modus einstellen) in zwei Testabsätze aufteilen.
@Aditya Wie andere bereits gesagt haben, müssen Sie auch eine Verzögerung hinzufügen: _delay_ms(100);LCD_Send(0x33,0);LCD_Send(0x32,0);LCD_Send(0x28,0);LCD_Send(0x0f,0);LCD_Send( 0x01,0);_delay_ms(5);LCD_Send(0x06,0);. Das 0x33 wird nur einmal benötigt, wenn es von 0x32 gefolgt wird.
Wie ich interpretiere, was Sie geschrieben haben, senden Sie das 0x3-Nibble 5 Mal, während das Datenblatt 3 Mal sagt. Vielleicht spielt das keine Rolle. Wie auch immer, @Anditya: Das ist sicher dein Problem. Und lesen Sie das Datenblatt, es sind einige extra lange Wartezeiten bei dieser Initialisierung erforderlich.

LCDs neigen dazu, wenn der Datenstrom irgendwie desynchronisiert wird, z. B. durch Anschließen während der Datenübertragung oder durch Zurücksetzen des Bildschirms oder des Mikrocontrollers, aber nicht beider.

Ich merke aus Ihrem Code, dass es keine Startverzögerung gibt. LCDs benötigen oft eine kurze Zeit zum "Hochfahren", bevor Sie mit dem Senden von Daten beginnen können. Fügen Sie dem Start Ihres Codes eine kleine Verzögerung hinzu. Sehen Sie im LCD-Datenblatt nach, wie viel.

Das ist ein sehr guter Punkt. ESD-Zaps können diese Dinge oft desynchronisieren, daher ist es für kommerzielle Produkte (die die ESD-Injektion für Komplikationen überleben müssen) eine gute Idee, diese LCDs regelmäßig neu zu initialisieren.

Überprüfen Sie das Datenblatt für das LCD. Oft müssen Sie nach dem Einschalten eine bestimmte Zeit warten, bevor Sie die Init-Sequenz senden. Vielleicht ist dein Problem folgendes:

Wenn Sie das Gerät programmieren, war es bereits eine Weile eingeschaltet, sodass Ihre Init-Sequenz funktioniert. Wenn Sie es kalt starten, gibt es keine Verzögerung, sodass das LCD noch nicht für die Init-Sequenz bereit ist.

Bitte poste auch einen Link zum Datenblatt

itron.com.cn/PDF_file/JHD162A%20SERIES.pdf Dies ist der Link zu dem von mir verwendeten LCD
Wenn ich es das zweite Mal zurücksetze, zeigt es das richtige Ergebnis. Ich verstehe nicht, wie die Erklärung, die Sie dafür gegeben haben, dafür verantwortlich ist.
Wahrscheinlich hat es noch genug Energie, um für Ihre Init-Sequenz bereit zu sein. Versuchen Sie, vor dem zweiten Neustart länger zu warten. Das Datenblatt ist nicht sehr klar, aber es sagt, dass der Controller einem Samsung-Teil entspricht: lcd-module.de/eng/pdf/zubehoer/ks0066.pdf Das Samsung-Teil sagt, dass es beim Start eine Verzögerung von 30 ms benötigt.
Ich habe die Verzögerung eingestellt, aber das Problem besteht weiterhin