logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Programowanie LCD w C na AT89S52 - nieprawidłowe wyświetlanie danych

cristof_w 29 Mar 2007 00:05 1325 9
REKLAMA
  • #1 3729503
    cristof_w
    Poziom 17  
    Posty: 338
    Pomógł: 3
    Ocena: 9
    Witam.
    Poniżej przedstawiam program w C do LCD, napisany w środowisku M-IDE, programowany Issprogr'iem z wykorzystaniem AT89S52.
    Ogólnie na LCD coś się pokazuje, czsami jakieś bzdedy a czsami to czego żądam.
    Czy ktoś z Was może to przetestować u siebie i sprawdzić jak to działa?
    Ewentualnie co tutaj powinno byc poprawione i jak, żeby działało w 100% prawidłowo.
    Pozdrawiam

    #pragma SMALL
    #include <8051.h>
    #include <stdio.h>

    //definicje znakow specjalnych dla wyswietlacza LCD
    char code CGRom[65]=
    {0xAA,0x55};

    #define PORT P1
    #define LcdEnable P1_3
    #define LcdRead P1_0
    #define LcdReg P1_2


    //opoznienie wielokrotnosc 1ms
    void Delay(unsigned int time)
    {
    unsigned int j;
    while (time >=1)
    {
    for (j=0;j<20;j++);
    time--;
    }
    }

    //zapis bajtu do LCD
    void WriteByteToLcd(char X)
    {
    LcdEnable=1;
    PORT |=0xF0;
    PORT &=(X | 0x0F);

    LcdEnable=0;
    LcdEnable=1;
    X<<=4;
    PORT |=0xF0;
    PORT &=(X | 0x0F);

    LcdEnable=0;
    Delay(1);
    }


    //zapis bajtu do rejestru kontrolnego LCD
    void WriteToLcdCtrlRegister(char X)
    {
    LcdReg=LcdRead=0; //ustawienie sygnalow sterujacych
    WriteByteToLcd(X);
    }

    //zapis bajtu do pamieci obrazu
    void LcdWrite(char X)
    {
    LcdReg=1; //ustawienie sygnalow sterujacych
    LcdRead=0;
    LcdEnable=1;
    WriteByteToLcd(X);
    }

    //czyszczenie ekranu LCD
    void LcdClrScr(void)
    {
    WriteToLcdCtrlRegister(0x01);
    }

    //inicjalizacja wysiwetlacza LCD w trybie 4 bity
    void LcdInitialize(void)
    {
    char i;

    Delay(15);
    P0=0x0F; //zerowanie linii LcdReg.LcdRead,LcdEnable
    for (i=0; i<3; i++)
    {
    LcdEnable=1; //impuls na E
    PORT &=0x3F; //ustawienie wartosci inicjujacej
    LcdEnable=0;
    Delay(5);
    }
    LcdEnable=1;
    PORT &=0x2F;
    LcdEnable=0;
    Delay(1);
    WriteToLcdCtrlRegister(0x28);
    WriteToLcdCtrlRegister(0x08);
    WriteToLcdCtrlRegister(0x01);
    WriteToLcdCtrlRegister(0x06);
    WriteToLcdCtrlRegister(0x0C);
    }

    //ustawia kursor na wspolrzednych x,y
    void GotoXY(char x, char y)
    {
    /* switch (y)

    {
    case 0:
    x +=0x80;
    break;
    case 1:
    x +=0xC0;
    break;
    case 2:
    x +=0x94;
    break;
    case 3:
    x +=0xD4;
    break;
    }*/

    WriteToLcdCtrlRegister(x);
    }

    //wyswietla tekst na wspolrzednych x,y
    void WriteTextXY(char x, char y, char *S)
    {
    while (*S)
    {
    GotoXY(x,y);
    LcdWrite(*S);
    x++;
    S++;
    if (x>19)
    {
    x=0;
    y++;
    }
    }
    }

    //wyswietla tekst rozpoczynajac od aktualnego polozenia kursora
    void Writetext(char *S)
    {
    while (*S)
    {
    LcdWrite(*S);
    S++;
    }
    }

    //definiowanie znakow z tablicy CGRom
    void DefineSpecialCharacters(char *ptr)
    {
    WriteToLcdCtrlRegister(0x40);

    while (*ptr !=0)

    {
    LcdWrite(*ptr);
    ptr++;
    }
    WriteToLcdCtrlRegister(0x80);
    }


    //program glowny
    void main(void)
    {
    char ix=1, iy=1, x, y, i=0;
    LcdInitialize();
    DefineSpecialCharacters(&CGRom);
    while (1)
    {
    WriteTextXY(x, y, " " );
    if (ix ==1 ) x++; else x--;
    if (iy ==1 ) y++; else y--;
    if (x ==19 ) ix = 0;
    if (x ==0 ) ix = 1;
    if (y ==3 ) iy = 0;
    if (y ==0 ) iy = 1;
    WriteTextXY(x, y, "4444");
    Delay(50);
    }
    }
  • REKLAMA
  • #2 3731371
    cristof_w
    Poziom 17  
    Posty: 338
    Pomógł: 3
    Ocena: 9
    Jest ktoś w stanie pomóc w tej kwestii?
    Pozdrawiam.
  • #3 3739557
    karol123
    Poziom 16  
    Posty: 228
    Pomógł: 2
    Ocena: 10
    A w jakim kompilatorze to napisałeś kolego ?
  • REKLAMA
  • #4 3740031
    cristof_w
    Poziom 17  
    Posty: 338
    Pomógł: 3
    Ocena: 9
    Witam.
    Do pisania kodu źródłowego używam M-IDE, natomiast procesor programuję za pomoca issprog.
    Pozdrawiam.
    P.S
    Zauważyłem dziwną przypadłość. Ściągnąłem z sieci sobie gotowy program, przerobiłem iodpowiednio i zadziałał...ale tylko raz. Jeżeli zmienie w kodzie to co ma wyswietlać, to wtedy tak samo się sypie jak ten program i nie wiem w czym jest rzecz.

    Dodano po 2 [godziny] 51 [minuty]:

    Inaczej...teraz przedstawiam trochę uproszczony program, wklejam poniżej, tylko takie uwagi:
    program się kompiluje, działa, po wgraniu do LCD wyświetla się to co chcę, jednak problem w tym, że dzieje się tak tylko za pierwszym razem, później się już nie chce wyświetlać. I teraz nadal nie wiem w czym jest problem? Srodowisko M-IDE, programator Issprog, kwarc 6 MHz. Mam podejrzenie co do funkcji Delay, że dla tego kwarcu trzebaby tam inne wartości wstawić, tak jakby było coś nie tak z czasami albo może dlatego, że nie ma czyszczenia? Pomóżcie.

    #include <8051.h>
    #include <stdio.h>

    #define PORT P1
    #define RS P1_2
    #define E P1_3
    #define D4 P1_4
    #define D5 P1_5
    #define D6 P1_6
    #define D7 P1_7

    void Delay(unsigned int k)
    {
    unsigned int i,j;
    for (j=0;j<k;j++)
    for (i=0; i<=296;i++);
    }

    void WriteToLcd(char X)
    {
    E = 1;
    PORT |= 0xF0;
    PORT &= (X | 0x0F);
    E = 0;
    E = 1;
    X <<= 4;
    PORT |= 0xF0;
    PORT &= (X | 0x0F);
    E = 0;
    Delay(1);
    }

    void WriteCommand(char X)
    {
    RS = 0;
    WriteToLcd(X);
    }

    void WriteChar(char X)
    {
    RS = 1;
    WriteToLcd(X);
    }



    void WriteText(char *S)
    {
    while(*S)
    {
    WriteChar(*S);
    S++;
    }
    }


    void LcdInit(void)
    {
    char i;
    Delay(15);
    PORT = 0x0F;
    for (i = 0; i<3; i++)
    {
    E = 1;
    PORT &= 0x3F;
    E = 0;
    Delay(5);
    }
    E = 1;
    PORT &= 0x2F;
    E = 0;
    Delay(1);
    WriteCommand(0x28);
    WriteCommand(0x08);
    WriteCommand(0x01);
    WriteCommand(0x06);
    WriteCommand(0x0C);
    }



    void main(void)
    {
    LcdInit();
    WriteText("ASDF");
    Delay(50);
    }
  • #5 3743544
    eP
    Poziom 27  
    Posty: 797
    Pomógł: 115
    Ocena: 21
    A moze Ci sie gdzies program wiesza po prostu ?
    Pokaz swoj program w calosci.
    Bo chyba nie chcesz powiedziec ze ten programik tylko 1 raz po zaprogramowaniu dziala (wyswietli tekst), a po kolejnym zalaczeniu zasilania juz nie.

    Jezeli masz jakis wiekszy program i wyswietlanie tylko zadziala w nim raz na poczatku to sprobuj uruchomic wyswietlanie po raz pierwszy dopiero gdzies dalej i wtedy sie przekonasz czy zadziala czy nie.
    Inaczej mozesz szukac bledu w miejscu gdzie go nie ma.
  • REKLAMA
  • #6 3744208
    cristof_w
    Poziom 17  
    Posty: 338
    Pomógł: 3
    Ocena: 9
    Jeżeli chodzi o LCD, to jest to cały program. Jak zadziała wyświetlanie poprawnie, to wtedy będzie to tylka pewna część do czegoś innego, co jest w trakcie pisania.
    I za demona nie wiem dlaczego nie chce działać, skoro wyświetla się raz, znaczy działa, a później już nie. Bez sensu. Jeszcze jakieś sugestie? Pozdrawiam.
  • #7 3744262
    eP
    Poziom 27  
    Posty: 797
    Pomógł: 115
    Ocena: 21
    cristof_w napisał:

    I za demona nie wiem dlaczego nie chce działać, skoro wyświetla się raz, znaczy działa, a później już nie. Bez sensu. Jeszcze jakieś sugestie? Pozdrawiam.


    Przyznam sie ze nie bardzo rozumiem Twoje wyjasnienie.
    Tzn. co rozumiesz pod terminem pozniej ?
    Czy chodzi o to ze po wylaczeniu zasilania i ponownym jego wlaczeniu ten uklad juz nie wyswietla tego tekstu ?
    Moze masz po prostu jakis problem ze wstawaniem procka i nie zawsze on chce wstac ?
    Moze napisz cos do sygnalizacji przy pomocy diody lub wskaznika 7-segm. LED i wtedy bedziesz wiedzial czy twoj procek wstal i nie chce pisac na LCD czy po prostu nie wstaje.
  • #8 3744338
    cristof_w
    Poziom 17  
    Posty: 338
    Pomógł: 3
    Ocena: 9
    Posprawdzam, może wrzucę inny procek.
    Póki co podam taki przykład wariacji.
    Zamiast np. wyświetlić XYZ, wyświetla PQR . I skąd niby to się bierze? Nie mam pomysła, nie mam tak szerokiej wiedzy. Skąd takie kwiatki?
  • REKLAMA
  • Pomocny post
    #9 3744362
    eP
    Poziom 27  
    Posty: 797
    Pomógł: 115
    Ocena: 21
    cristof_w napisał:
    Zamiast np. wyświetlić XYZ, wyświetla PQR . I skąd niby to się bierze?


    To akurat wyglada na zwarcie bitu 3 do masy (z portu wysylajacego dane).
    Zamiast 88,89,8A LCD otrzymuje 80,81,82 (oczywiscie w hexie)
    To by moglo tez tlumaczyc ze LCD nie reaguje poprawnie na wszystkie wysylane do niego komendy.

    Pozdrawiam
  • #10 3744433
    cristof_w
    Poziom 17  
    Posty: 338
    Pomógł: 3
    Ocena: 9
    Dziękuję za całą pomoc.
    Dałem inny procesor zamiast tamtego i wszystko wydaje się działać już poprawnie. Po podłączeniu na now ozasilania i wciśnięciu resetu, na LCD wyświetla się poprawnie to co powino.
    Dzięki.

Podsumowanie tematu

✨ Dyskusja dotyczy problemów z wyświetlaniem danych na LCD sterowanym przez mikrokontroler AT89S52, programowany w języku C w środowisku M-IDE i programatorem Issprog. Użytkownik zgłasza, że wyświetlacz LCD pokazuje poprawne dane tylko za pierwszym razem po zaprogramowaniu, a później wyświetlanie jest nieprawidłowe lub pojawiają się losowe znaki. Podejrzenia padają na funkcję opóźnienia Delay, która może nie być dostosowana do kwarcu 6 MHz, co wpływa na timing sygnałów. Wskazano również możliwość zawieszenia się programu lub problemów z inicjalizacją mikrokontrolera po restarcie. Jeden z uczestników zasugerował zwarcie bitu 3 portu danych, co powoduje, że LCD otrzymuje niepoprawne wartości (np. zamiast 0x88, 0x89, 0x8A pojawiają się 0x80, 0x81, 0x82), co tłumaczy błędne reakcje wyświetlacza. Ostatecznie wymiana mikrokontrolera na inny egzemplarz rozwiązała problem i wyświetlanie działa poprawnie po każdym restarcie.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA