Elektroda.pl
Elektroda.pl
X
Banner Multimetr Fluke 87VBanner Multimetr Fluke 87V
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Obsługa LCD w " C "

03 Lip 2006 20:40 6787 31
  • Poziom 20  
    napisałem sobie króciutki programik który miał ustawić LCD w tryb 4 bit
    ( jednak bez inicjacji ) i wyświetlić "a". Problem w tym że raz wyświetla
    "a" a raz "Σ" czasem nic. Czy błąd może być w tym prymitywnym programiku ?

    //#include <stdio.h>
    #include <mcs51reg.h>
    #include <at89c51ed2.h>



    #define db4 P3_6
    #define db5 P3_7
    #define db6 P3_5
    #define db7 P3_4

    #define en P4_1
    #define rs P4_0



    void _lcd_out(char bajt)
    {
    int i;
    for(i=0;i>1000;i++);
    db4=(bajt & 0x10);
    db5=(bajt & 0x20);
    db6=(bajt & 0x40);
    db7=(bajt & 0x80);
    for(i=0;i>1000;i++);
    en = 1;
    for(i=0;i>1000;i++);
    en = 0;
    for(i=0;i>1000;i++);

    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    for(i=0;i>1000;i++);
    en = 1;
    for(i=0;i>1000;i++);
    en = 0;
    for(i=0;i>1000;i++);
    }

    void _lcd_on(void)
    {
    int i;
    rs = 0;
    for(i=0;i>1000;i++);
    _lcd_out(34);
    _lcd_out(1);
    _lcd_out(2);
    _lcd_out(15);
    for(i=0;i>1000;i++);
    rs = 1;

    }

    void main(void)
    {
    int i;
    for(i=0;i>1000;i++);
    en = 0;
    _lcd_on();
    _lcd_out('a');
    }
  • Banner Multimetr Fluke 87VBanner Multimetr Fluke 87V
  • Pomocny post
    Poziom 28  
    Bez inicjacji LCD pracuje w trybie 8-bitowym wiec nic dziwnego ze nie działa...
  • Banner Multimetr Fluke 87VBanner Multimetr Fluke 87V
  • Pomocny post
    Poziom 22  
    Co do samego lcd (sterownik hd44780 czy jakoś tak) nie będę się wypowiadał bo niewiele pamiętam a i 4-ro bitowego trybu nigdy nie używałem. Jednak wypowiem się na temat opóźnień.
    Otóż pętle nic a nic nie opóźnią bo nie wykonają się ani razu. Zastosowałeś zły warunek i>1000. Powinno być i<1000.

    Ateraz mała dygresja w ramach przestrogi:
    Pętle opóźniające mogą zostać wyrzucone przez kompilator w zależności od rodzaju włączonej optymalizacji. Kompilator może stwierdzić, że nie wnoszą one nic do funkcjonalności programu i sru z programu. Aby temu zapobiec musisz zmienną iteracyjną i zadeklarować jako volatile, czyli volatile int i;. Słowo volatile mówi kompilatorowi żeby pozostawił wszystkie instrukcje odwołujące się do zmiennej. Dzięki temu pętle się wykonają i będzie opóźnienie. W przeciwnym przypadku kompilator pozostawi jedną instrukcję przypisującą wartość do zmiennej z ostatniej iteracji.

    upanie[/url]
  • Pomocny post
    Poziom 39  
    Poproszę o skomentowanie poszczególnych lini z "_lcd_out()" - co one "robią" :?:
    Code:

    void _lcd_on(void)
    {
     int i;
     rs = 0;
     for(i=0;i>1000;i++);
     _lcd_out(34);
     _lcd_out(1);
     _lcd_out(2);
     _lcd_out(15);
     for(i=0;i>1000;i++);
     rs = 1;
    }

    Nijak nie pasują mi do tego co pisze w dokumentacji HD44780 , bo chyba o ten chip chodzi :?:
    Przed zainicjowaniem LCD po włączeniu zasilania , warto odczekać z 15-20 ms.

    Piotrek
  • Pomocny post
    Poziom 33  
    Code:

     _lcd_out(34);
     _lcd_out(1);
     _lcd_out(2);
     _lcd_out(15);


    1. Sterowanie 4 bitowe, znaki 5x7; (0x22)
    2. Czyszczenie ekranu. (0x01)
    3. Zerowanie kursora. (0x02)
    4. Właczenie lcd, kursor jest włączony i miga. (0x0F)

    Ale nie znaczy to , że ma działać bo niewiadomo co robi _lcd_out(); i jak wygląda reszta programu.
  • Pomocny post
    Poziom 22  
    Kompletnie nie rozumiem o co wam chodzi z tym _lcd_out(). Przeca w pierwszym poście jest cały program.
    Zerknąłem na datashita hd44780 to kolega Fajfer2 robi wszystko OK (chyba). Zakładam oczywiście, że linia RS wyświetlacza jest na stałe podłączona do masy. Jeżeli tak i wg markosik20 inicjalizacje też jest OK, to pozostaje jedynie problem opóźnien. W tym programie nie ma ich wcale, ale o tym już pisałem.

    upanie
  • Pomocny post
    Poziom 39  
    upanie napisał:
    Zerknąłem na datashita hd44780 to kolega Fajfer2 robi wszystko OK (chyba).

    No właśnie , chyba.Ja smiem twierdzić , że nic nie jest OK :(
    Jeśli juz nie chce się Wam czytać , to popatrzcie na obrazek , jak zainicjować LCD w trybie 4bit.

    Piotrek
  • Poziom 20  
    34 w zapisie dziesiętnym (mam nadzieję że kompilator "rozumie")
    i wstawia 22h
    Obecnie program wygląda tak i nic się nie dzieje :



    #include <stdio.h>
    #include <mcs51reg.h>
    #include <at89c51ed2.h>



    #define db4 P3_6
    #define db5 P3_7
    #define db6 P3_5
    #define db7 P3_4

    #define en P4_1
    #define rs P4_0

    void _init_disp(void)
    {
    // 1
    int i ;
    unsigned char bajt;

    en=0;
    rs=0;
    for(i=0;i<7000;i++);
    bajt=3;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    for(i=0;i<9000;i++);
    en = 1;
    for(i=0;i<9000;i++);
    en = 0;
    for(i=0;i<9000;i++);
    // 2
    en=1;
    for(i=0;i<9000;i++);
    en=0;
    for(i=0;i<9000;i++);
    // 3
    en=1;
    for(i=0;i<9000;i++);
    en=0;
    for(i=0;i<9000;i++);
    //4
    bajt=2;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    for(i=0;i<9000;i++);
    en = 1;
    for(i=0;i<9000;i++);
    en = 0;
    for(i=0;i<9000;i++);
    //5
    en = 1;
    for(i=0;i<9000;i++);
    en = 0;
    for(i=0;i<9000;i++);
    //6
    bajt=8;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    for(i=0;i<9000;i++);
    en = 1;
    for(i=0;i<9000;i++);
    en = 0;
    for(i=0;i<9000;i++);
    //7
    bajt=0;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    for(i=0;i<5000;i++);
    en = 1;
    for(i=0;i<5000;i++);
    en = 0;
    for(i=0;i<5000;i++);
    //8
    bajt=8;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    for(i=0;i<5000;i++);
    en = 1;
    for(i=0;i<5000;i++);
    en = 0;
    for(i=0;i<5000;i++);
    //9
    bajt=0;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    for(i=0;i<5000;i++);
    en = 1;
    for(i=0;i<5000;i++);
    en = 0;
    for(i=0;i<5000;i++);
    //10
    bajt=1;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    for(i=0;i<5000;i++);
    en = 1;
    for(i=0;i<5000;i++);
    en = 0;
    for(i=0;i<5000;i++);

    //11
    bajt=0;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    for(i=0;i<5000;i++);
    en = 1;
    for(i=0;i<5000;i++);
    en = 0;
    for(i=0;i<5000;i++);
    //12
    bajt=6;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    for(i=0;i<1000;i++);
    en = 1;
    for(i=0;i<1000;i++);
    en = 0;
    for(i=0;i<1000;i++);
    }
    //============================================




    void _lcd_out(unsigned char bajt)
    {
    int i;
    for(i=0;i<2000;i++);
    db4=(bajt & 0x10);
    db5=(bajt & 0x20);
    db6=(bajt & 0x40);
    db7=(bajt & 0x80);
    for(i=0;i<2000;i++);

    en = 1;
    for(i=0;i<2000;i++);
    en = 0;

    for(i=0;i<2000;i++);
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    for(i=0;i<2000;i++);

    en = 1;
    for(i=0;i<2000;i++);
    en = 0;
    for(i=0;i<2000;i++);
    }

    void _lcd_on(void)
    {
    int i;
    rs = 0;
    for(i=0;i<1000;i++);
    _lcd_out(1);
    _lcd_out(2);
    _lcd_out(0x0f);
    for(i=0;i<1000;i++);
    rs = 0;
    }

    void putchar(char znak)
    {
    _lcd_out(znak);
    }


    void main(void)
    {
    int i;
    en=0;
    rs=0;
    i=0;
    for(i=0;i<20000;i++);
    _init_disp;
    for(i=0;i<2000;i++);

    _lcd_on;
    rs=1;
    for(i=0;i<2000;i++);
    _lcd_out('a');
    //printf("pierwszy napis");
    }
  • Pomocny post
    Poziom 22  
    Cytat:
    No właśnie , chyba.Ja smiem twierdzić , że nic nie jest OK Sad
    Jeśli juz nie chce się Wam czytać , to popatrzcie na obrazek , jak zainicjować LCD w trybie 4bit.

    No to Ty chyba też nie czytałeś i w dodatku nie czytałeś załączonego kodu przez kolegę. Jak jeden mąż stwierdzacie, że nie wiecie co robi funkcja _lcd_out() mimo, że kod funkcji jest załączony. Jak sobie spojrzysz na tabelę 12 to zobaczysz, że tu inicjalizacja wygląda inaczej i o dziwo jest bardzo podobna do tego co zrobił Fajfer2. Nie czytałem dokumentacji wnikliwie bo to nie mój problem. Ja mogę wesprzeć w tym co wiem w danej chwili bez studiowania nwych rzeczy. Nie mam poprostu na to czasu. Jeżeli chodzi o inicjalizację to powołałem się na markosik20. Funkcja _lcd_out() wygląda na prawidłową. Nie mogę wszystkiego stwierdzić na 100% bo nie pamiętam prawie nic o 8051 i hd44780.
    Ten algorytm, który zamieściłeś jest cokolwiek dziwny i nie pasuje do przykładu zamieszczonego w tabeli 12. Sprawa generalnie jest prosta jak drut dlatego nie wiem skąd ten problem.

    Fajfer2 W nowej wersji incjalizacji wyświetlacza wszystko jest prawie zgodne z załączonym algorytmem. Ostatnie kroki (od 10 Ci się pomyliły i jednego brakuje). 10 powinno być 8, 11 - 0, 12 - 1, 13 - 0,14 - 6.
    Co to za konstrukcja z _lcd_on; w funkcji main?
    Czy linia R/W napewno jest ustawiona na zero?
    Funkcja _lcd_out() wygląda na prawidłową.

    Powodzenia.

    upanie
  • Pomocny post
    Poziom 39  
    upanie napisał:

    No to Ty chyba też nie czytałeś i w dodatku nie czytałeś załączonego kodu przez kolegę.

    Drogi przyjacielu :D Funkcję o której wspominasz , ja sam napisałem dla Fajfer2 jako odpowiedź na jego wcześniejszy post.
    upanie napisał:

    Jak jeden mąż stwierdzacie, że nie wiecie co robi funkcja _lcd_out() ...

    Nie zrozumiałeś , albo ja zadałem nieprecyzyjne pytanie ;)
    Mnie chodzi co robia (jakie zadania realizują) linie w kodzie ...
    Code:

    _lcd_out(34) ;
    // itp

    ... a odpowiedzi spodziewałem się np. "function set - interface=4 bit,line=2,font=5x7" , czy coś w tym guście.Chciałem sie dowiedzieć , czy Fajfer2 wie co robi :(
    To narazie tyle :)

    Piotrek
  • Pomocny post
    Poziom 22  
    A to przepraszam ;)
    Kiedyś używałem takiego lcdka ale w trybie 8 bitów i nigdy nie miałem najmnieszych problemów. Informacje zaczerpnąłem z pdfa tego wyświetacza. Żadnych specjalnych inicalizacji, poprostu ustawiałem co trzeba i cześć, a tu widzę jakieś kilkukrotne wpisywanie tych samych wartości, różne czasy opóźnień, wewnętrzne resety, itp. Po kiego grzyba? Zatem po co sie silić na 4 bity? No ale jak mus to mus.
    Fajfer2 może zapodaj schemat podłączenia tego lcd. Może podłączyłeś nie te bity interfejsu co trzeba, ale najpierw zrób dokładnie to co jest w tabeli 12 dokumentacji do hd44780.
  • Pomocny post
    Poziom 11  
    Oto mój program wykorzystujący LCD w trybie 4-bitowym, śmiga jak ...
    Jest tam obsługa LCD i 1wire, procedurki LCD łatwo wyłowić :)

    Code:
    // ***********************************************************
    
    // Project:  Obsluga układu DS18B20
    // Author:   Zbigniew Chrobot
    // Module description:  pomiar temperatury z DS18B20 kwarc 4MHz
    //                                                              wyswietlanie na LCD
    // ***********************************************************

    #include <avr\io.h>             
    #include <avr\interrupt.h>   
    #include <avr\signal.h>       
    #include <avr\delay.h>


    // Definicje dotyczace LCD
    #define RS 2                     // wybor rejestru
    #define RW 1                     // 1 - odczyt; 0 - zapis
    #define E 3                      // sygnal zezwalajacy (enable)
    #define PORTLCD PORTB            // port z podlaczanym LCD
    #define DDRLCD DDRB             // port z podlaczanym LCD
    #define PINLCD PINB             // port z podlaczanym LCD
    // Wykorzystujemy tylko cztery linie przesylowe D4-D7 portu PORTLCD

    // Definicje dotyczace 1wire
    #define PORT1W PORTD             // port z podlaczanym 1Wire
    #define DDR1W DDRD              // port z podlaczanym 1Wire
    #define PIN1W PIND              // port z podlaczanym 1Wire
    #define ONEWIRE  0               // bit uzytego wejscia
    // 1wire podlaczony jest do PORTD.0
    #define WIRE_0 sbi(DDR1W, ONEWIRE)  // ustaw 0 na wyjscie WIRE
    #define WIRE_1 cbi(DDR1W, ONEWIRE)  // ustaw 1 na wyjscie WIRE
    // WIRE_0  i WIRE_1 polega na przelaczaniu pinu jako wejscie i wyjscie
    // stan 1 uzyskujemy przez rezystor podciagajacy
    // stan zero uzyskujemy przelaczajac pin jako wyjscie
    // zero jest na stałe wpisane

    // prodedura wytracania czasu
    void czekaj(unsigned long pt)   //procedura wytracania czasu ok. 1ms
    {
            for(;pt>0;pt--)
                    _delay_loop_2(1000);       // obliczone dla 4MHz
    }
    // sprawdzenie zajetosci jesli flaga zero to wolny LCD
    // funkcja bajt odpowiadajacy stanowi bitu BF
    unsigned char lcd_busy(void)
    {
            unsigned char flaga;            // zmienna pomocnicza
            cbi(PORTLCD,RS);                // dostep do rejestru instrukcji
            sbi(PORTLCD,RW);                // tryb odczytu  - ustaw bit RW
            DDRLCD=0x0f;                    // bity D4 - D7 wejsciami       
            sbi(PORTLCD,E);                 // ustawienie linii strobujacej
            asm("nop");                     // krotka przerwa
            flaga = PINLCD&0x80;            // zapamietanie zawartosci bitu BF(D7)
            cbi(PORTLCD,E);
            sbi(PORTLCD,E);                 // generacja pustego impulsu strobujacego
            asm("nop");                     // krotka przerwa
            cbi(PORTLCD,E);
            DDRLCD=0xff;                    // caly port wyjsciami
            return flaga;                   // zwrocenie wartosci odczytanego bitu
    }

    // funkcja wysyla dana lub rozkaz do wyswietlenia
    // litera = 0 oznacza slowo sterujace
    void lcd_trans(unsigned char dana, char litera)
    {
            while (lcd_busy());             // oczekiwanie na zwolnienie wyswietlacza
            cbi(PORTLCD,RW);                // tryb zapisu - kasuj bit RW
            sbi(PORTLCD,E);
            if (litera==0)                  // rodzaj transmisji zalezny od parametru
                    cbi(PORTLCD,RS);        // 0 oznacza slowo sterujace
            else
                    sbi(PORTLCD,RS);        // 1 oznacza znak do wyswietlenia
            sbi(PORTLCD,E);
            PORTLCD=(PORTLCD&0x0f)|(dana&0xf0);  //przygotuj starszy polbajt do LCD
            asm("nop");             // krotka przerwa
            cbi(PORTLCD,E);         //impuls strobujacy
            sbi(PORTLCD,E);
            PORTLCD=(PORTLCD&0x0f)|((dana&0x0f)<<4);
                                    // przygotuj mlodszy polbajt do LCD
            asm("nop");             // krotka przerwa
            cbi(PORTLCD,E);
     }

    // USTAWIANIE KURSORA W ZADANYM MIEJSCU
    void lcd_xy(unsigned char w, unsigned char k)
    {
     lcd_trans((w*0x40+k)|0x80,0);
    }

    // Pisanie tekstu na ekranie
    void lcd_tekst(char *tekst)
    {
            unsigned char i = 0;  while (tekst[i]) lcd_trans(tekst[i++],1);
    }

    // Inicjowanie LCD
    void lcd_init(void)
    {
            unsigned char i;
            DDRLCD=0xff;            // PORTLCD - wyjsciem
            cbi(PORTLCD,RW);
            czekaj(45);             // czekamy okolo 45ms - katalogowo 15ms
       asm("nop");
            for(i=0;i<3;i++)        // 3-krotne wyslanie 3-
                    {
                    sbi(PORTLCD,E);
                    PORTLCD=(PORTLCD&0x0f)|0x30;//wyslij 3- do LCD
                    asm("nop");asm("nop");asm("nop");
                    cbi(PORTLCD,E);
                    czekaj(5);                      // ok. 5ms
                    }
            sbi(PORTLCD,E);
            PORTLCD=(PORTLCD&0x0f)|0x20;  //wyslij 2- do LCD
            asm("nop");asm("nop");asm("nop");
            cbi(PORTLCD,E);
            czekaj(10L);            // od tego momentu sprawdzamy gotowosc LCD
            lcd_trans(0x28,0);      // interfejs 4-bitowy, 2 linie, znak 5x7
            lcd_trans(0x08,0);      // wylacz LCD, wylacz kursor, wylacz mruganie
            lcd_trans(0x01,0);      // czysc LCD nie trzeba czekac !!!
            lcd_trans(0x06,0);      // zwiekszanie pozycji kursora po kazdym znaku
            lcd_trans(0x0c,0);      // wlacz wyswietlacz bez kursora
       }

    // OBSLUGA 1 WIRE
    //opoznienie dla 1wire
    void czekaj_1w(unsigned char delay1w)
    {                               // czekaj (5+5*delay1w)*T
    do {asm("nop");} while (--delay1w!=0);
    }                               // T = okres oscylatora
    //RESET 1WIRE
    unsigned char wire_reset(void)
    {
            unsigned char potwierdzenie;
            WIRE_0;                 // reset urzadzenia
            czekaj_1w(255);czekaj_1w(255);// czekaj okolo 500us
            WIRE_1;
            czekaj_1w(70);          // czekaj okolo 75us

            potwierdzenie = PIN1W & (1<<ONEWIRE); // sprawdz bit ONEWIRE
                                            // zero oznacza OK
                                            // zero wyslane przez urzadzenie
            czekaj(1);                      // czekaj okolo 1ms koniec resetu
                                            // po tym czasie powinna wrócic jedynka
       if (potwierdzenie) potwierdzenie=0x00;
            else potwierdzenie=0x01;// zamien zeby 1 znaczylo OK

            potwierdzenie &= PIN1W & (1<<ONEWIRE);
                                            // ponownie sprawdz powinno teraz byc 1
            return potwierdzenie;           // 1 OK; 0 brak urzadzenia

    }

    // procedura zapisu pojedynczego bitu
    void wire_write_bit(unsigned char bit)
    {
            WIRE_0;
            czekaj_1w(8);
            if (!bit){czekaj_1w(80);WIRE_1;czekaj_1w(2);}
                                            // przedluzenie dla zera
                    else {WIRE_1; czekaj_1w(80);}
                                            // jesli 1 koncz i czekaj
    }
    // procedura zapisu bajtu do urzadzenia
    void wire_write_byte(unsigned char bajt)
    {
            for(unsigned char i = 0; i<8; i++)
                    {
                    wire_write_bit(bajt & 0x01);    // wyslij bit zerowy bajtu
                    bajt>>=1;                       // przesun w prawo i tak osiem bitow
                    }
    }

    // procedura odczytu bitu od urzadzenie 1wire
    unsigned char wire_read_bit(void)
    {
            unsigned char bit;
            WIRE_0;
            czekaj_1w(1);
            WIRE_1;
            czekaj_1w(14);
            bit =  PIN1W & (1<<ONEWIRE);
            czekaj_1w(120);
            return bit;
    }

    //procedura odczytu bajtu z urzadzenia
    unsigned char wire_read_byte(void)
    {
    unsigned char bajt, tmp;
    bajt = 0;
    for(unsigned char i = 0;i<8; i++)
            {
                    tmp = wire_read_bit();
                    tmp = tmp << i;
                    bajt = bajt | tmp;
            }
    return bajt;
    }

    //***************************************************************
    int main (void)
    {
            unsigned char temp1, temp2, tmp1;
            unsigned int ulamek = 0;
            char *tmpint = "              ";
            char *tekst1 = "Temp:  ";
            lcd_init();                                     // inicjujmy LCD
            WIRE_1;                                         // wyslij jeden
            lcd_tekst(tekst1);      // wypisz *tekst1
            lcd_xy(1,0);
    // inicjujemy 1wire
            if (!wire_reset()) lcd_tekst("Brak urzadzenia!");
                    else lcd_tekst("Ok");
            while(1)
       {
            wire_write_byte(0xcc);          // pomin czytanie nr
               wire_write_byte(0x44);       // nakaz pomiar temperatury
                    czekaj(800);            // czekaj na przetworzenie 800 dla 12 bitow
          wire_reset();
          wire_write_byte(0xcc);            // pomin czytanie nr
          wire_write_byte(0xbe);            // zadaj odczytania temperatury
               temp1 = wire_read_byte();    // pierwszy bajt mlodszy
               temp2 = wire_read_byte();    // drugi bajt starszy
    // dla trybu 12 bitowego temeratura jest zapisana w dwoch bitach
    // temp2 - SSSS SHHH;  temp1 - HHHH LLLL
    // gdzie S - znak, H - bity czesci calkowitej
    // L - bity czesci ulamkowej
          tmp1 = temp1;             // w tmp1 bedziemy trzymac czesc ulamkowa
                    tmp1 &= 0x0f;   // wycinamy niepotrzebne bity HHHH
                    temp1 >>= 4;    // przesuwamy HHHH w prawo wycinamy LLLL
                    temp2 <<= 4;    // wycinamy 4 niepotrzebne bity znaku
                    temp2 = temp1 | temp2;  // laczymy i w temp2 mamy czesc calkowita
                    lcd_xy(0,6);
                    if (temp2 > 127)        // gdy temperatura jest ujemna
                            {                    // musimy przeliczyc wynik
                                    temp2 = 255 - temp2; // przeliczamy czesc calkowita
                                    tmp1 = 15 - tmp1; // przeliczamy czesc ulamkowa
                                    lcd_trans('-',1);
                            }
               ulamek = tmp1 * 625;         // ulamek o warosciach do 10000
                    tmp1 = ulamek / 1000;   // tmp1 musi byc w granicach od 0 do 9
                    if (tmp1 ==10) tmp1 = 0;
                    if (temp2<10) lcd_tekst("0");
                    lcd_tekst(utoa(temp2,tmpint,10));
                    lcd_trans('.',1);       // wyswietl kropke
                    lcd_trans(tmp1 + 48,1); // wyswietl cyfre ulamka
                                            // najprostsza zamiana cyfry na ASCII
                    lcd_trans(0xdf,1);      // znak stopni
                    lcd_tekst("C  ");       // duze C - "Celsjusza"  i spacja
            wire_reset();           // zresetuj DS18B20
            }
    }
  • Poziom 20  
    Witam, obecnie program wygląda tak ( i działa ):

    (jak się także w tym programie okazało napisanie " _init_disp; "
    to co innego niż " _init_disp(); " - nawiasy są niezbędne (przy wywołaniu
    funkcji)


    #include <stdio.h>
    #include <mcs51reg.h>
    #include <at89c51ed2.h>



    #define db4 P3_6
    #define db5 P3_7
    #define db6 P3_5
    #define db7 P3_4

    #define en P4_1
    #define rs P4_0

    void _del(int tme)
    {
    int i;
    i=0;
    for (i=0; i<tme; i++);
    }

    void _enable(void)
    {
    _del(1000);
    en=1;
    _del(1000);
    en=0;
    _del(1000);
    }
    //===================================

    void _init_disp(void)
    {

    char bajt;


    rs=0;
    _del(5000);
    //1
    bajt=3;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    _enable();
    // 2
    bajt=3;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    _enable();
    //3
    bajt=3;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    _enable();

    //4
    bajt=2;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    _enable();

    //5
    bajt = 2;
    db4 = (bajt & 0x01);
    db5 = (bajt & 0x02);
    db6 = (bajt & 0x04);
    db7= (bajt & 0x08);
    _enable();
    //6
    bajt=8;
    db4= (bajt & 0x01);
    db5 = (bajt & 0x02);
    db6 = (bajt & 0x04);
    db7 = (bajt & 0x08);
    _enable();
    //7
    bajt=0;
    db4 = (bajt & 0x01);
    db5 = (bajt & 0x02);
    db6 = (bajt & 0x04);
    db7 = (bajt & 0x08);
    _enable();
    //8
    bajt=8;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    _enable();
    //9
    bajt=0;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    _enable();
    //10
    bajt=1;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    _enable();
    //11
    bajt=0;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    _enable();
    //12
    bajt=6;
    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    _enable();

    }
    //============================================




    void _lcd_out(unsigned char bajt)
    {

    db4=(bajt & 0x10);
    db5=(bajt & 0x20);
    db6=(bajt & 0x40);
    db7=(bajt & 0x80);
    _enable();

    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    _enable();
    }

    void _lcd_on(void)
    {
    rs = 0;
    //_lcd_out(34);
    _lcd_out(1); // clear disp
    _lcd_out(2); // home
    _lcd_out(15);// zalaczenie lcd, kursor widoczny i miga
    }

    void putchar(char znak)
    {
    _lcd_out(znak);
    }


    void main(void)
    {
    int i;
    i=0;

    rs=0;

    for(i=0;i<2000;i++);
    _init_disp();
    i=0;
    for(i=0;i<2000;i++);

    _lcd_on();
    rs=1;
    for(i=0;i<20000;i++);
    //putchar('a');
    printf("pierwszy napis");
    }
  • Pomocny post
    Poziom 12  
    Mam taki sam problem jak twóraca tematu. Prgramuje pod WinAvr i mój kompilator "nie rozumie" niektórych fragmentów przytoczonych w tym temacie programów np.
    db4=(bajt & 0x10);
    db5=(bajt & 0x20);
    db6=(bajt & 0x40);
    db7=(bajt & 0x80);
    _enable();

    db4=(bajt & 0x01);
    db5=(bajt & 0x02);
    db6=(bajt & 0x04);
    db7=(bajt & 0x08);
    _enable();

    jeśli ktoś ma coś co powinno mi się skompilować to bardzo proszę, lub proszę o program w pseudokodzie(opis krok po kroku co wysłać do lcd na jakie piny) bo walcze od tygodnia z tym wyświetlaczem i widzę tylko czarną linię, a korzystam juz nawet ze specyfikacji wyświetlacza Hitachi, z której algorytm inicjalizacji był przytoczony wyżej.
    Za pomoc z góry dziękuję.
  • Pomocny post
    Poziom 39  
    grzesiug napisał:
    Mam taki sam problem jak twóraca tematu. Prgramuje pod WinAvr i mój kompilator "nie rozumie" niektórych fragmentów przytoczonych w tym temacie programów np. ...

    A czy kolega był łaskaw zauważyć , że autor tematu uruchamiał LCD na mikroprocesorze z rodziny MCS-51 , a nie AVR :?:
    Mimo że kod jest napisany w C , to jego "przenośność" na inną platformę , nie jest pełna.Np. MCS-51 ma możliwość zaadresowania bitu ,która to możliwość jest wykorzystana np.w linii d4=(bajt & 0x01), a AVR bezpośrednio tego nie potrafi.
    Jest natomiast w tym temacie kod , załączony przez sp3uqw , który jest dedykowany AVR-om i na nim radzę "się oprzeć" ;)

    Piotrek
  • Pomocny post
    Poziom 12  
    Żywcem przepisałem funkcje od sp3uqw zmieniłem tylko porty i ciągle czarna
    linia.Jakieś pomysły?? Wyświetlacz to HY-1602F6 kupiony na Allegro.
  • Poziom 20  
    może masz zbyt krótkie czasy impulsów enable( i/lub zbyt krótko
    pozostawione dane przed i po enable)
    Zwłaszcza komendy czyszczenia i ustawiania wymagają sporo czasu
    i nie można przed zakończeniem ich wykonania coś wpisywać
  • Pomocny post
    Poziom 12  
    a czy może być inny powód (nie programowy np złe napięcie czy coś??) wyświetlania tych czarnych prostokątów w pierwszej lini,bo już nie wiem co jest nie tak.Próbowałem już wszystkiego.Może ktoś ma jakiś prosty sprawdzony program pod AVR (tylko C) to bardzo bym prosił o udostępnienie ,bo nerwy tracę.
  • Poziom 20  
    Np. jak byś miał niewłaściwie podłączone piny.
    Masz tryb 4 bitowy czy 8 bitowy ? Przy 4 bitowym np. wykorzystuje
    się D7..D4 .
    Ale i tak zaskakuje mnie że nie można napisać : db = 1;
    (że kompilator nie przetworzy na właściwe rozkazy
    pomimo braku adresowania pojedyńczych bitów - to tylko kilka
    operacji logicznych AND i OR)
  • Pomocny post
    Poziom 12  
    Tryb jest 4 bitowy(chyba),bo korzystam z programu powyżej kolegi sp3uqw
    piny ma mam podłączone nastepująco PD0->D0.....PD7->D7(atmega8) to chyba nie nie przeszkadza że mam podłączone wszystkie 8 pinów w trybie 4 bitowym??

    a mój program wygląda tak:
    #include <avr/io.h>
    #include "funkcje.c"

    #define RS_ON sbi(DDRC,PC5);sbi(PORTC,PC5)
    #define RS_OFF sbi(DDRC,PC5);cbi(PORTC,PC5)

    #define RW_ON sbi(DDRC,PC4);sbi(PORTC,PC4)
    #define RW_OFF sbi(DDRC,PC4);cbi(PORTC,PC4)

    #define E_ON sbi(DDRC,PC3);sbi(PORTC,PC3)
    #define E_OFF sbi(DDRC,PC3);cbi(PORTC,PC3)

    #define L_ON sbi(DDRC,PC2);sbi(PORTC,PC2)
    #define L_OFF sbi(DDRC,PC2);cbi(PORTC,PC2)


    // Definicje dotyczace LCD

    #define PORTLCD PORTB // port z podlaczanym LCD
    #define DDRLCD DDRB // port z podlaczanym LCD
    #define PINLCD PINB // port z podlaczanym LCD






    // sprawdzenie zajetosci jesli flaga zero to wolny LCD
    // funkcja bajt odpowiadajacy stanowi bitu BF
    unsigned char lcd_busy(void)
    {
    unsigned char flaga; // zmienna pomocnicza
    RS_OFF; // dostep do rejestru instrukcji
    RW_ON; // tryb odczytu - ustaw bit RW
    DDRLCD=0x0f; // bity D4 - D7 wejsciami
    E_ON; // ustawienie linii strobujacej
    asm("nop"); // krotka przerwa
    flaga = PINLCD&0x80; // zapamietanie zawartosci bitu BF(D7)

    E_OFF;
    E_ON; // generacja pustego impulsu strobujacego
    asm("nop"); // krotka przerwa
    E_OFF;
    DDRLCD=0xff; // caly port wyjsciami
    return flaga; // zwrocenie wartosci odczytanego bitu
    }
    // funkcja wysyla dana lub rozkaz do wyswietlenia
    // litera = 0 oznacza slowo sterujace
    void lcd_trans(unsigned char dana, char litera)
    {
    while (lcd_busy()); // oczekiwanie na zwolnienie wyswietlacza
    RW_OFF; // tryb zapisu - kasuj bit RW
    E_ON;
    if (litera==0) // rodzaj transmisji zalezny od parametru
    {RS_OFF;} // 0 oznacza slowo sterujace
    else
    RS_ON; // 1 oznacza znak do wyswietlenia
    E_ON;
    PORTLCD=(PORTLCD&0x0f)|(dana&0xf0); //przygotuj starszy polbajt do LCD
    asm("nop");asm("nop"); // krotka przerwa
    E_OFF; //impuls strobujacy
    E_ON;
    PORTLCD=(PORTLCD&0x0f)|((dana&0x0f)<<4);
    // przygotuj mlodszy polbajt do LCD
    asm("nop"); asm("nop"); // krotka przerwa
    E_OFF;
    }

    void lcd_init(void)
    {
    unsigned char i;
    DDRLCD=0xff; // PORTLCD - wyjsciem
    RW_OFF;
    delayms(50); // czekamy okolo 45ms - katalogowo 15ms
    asm("nop");
    for(i=0;i<5;i++) // 3-krotne wyslanie 3-
    {
    E_ON;
    PORTLCD=(PORTLCD&0x0f)|0x30;//wyslij 3- do LCD
    asm("nop");asm("nop");asm("nop");
    E_OFF;
    delayms(10); // ok. 5ms
    }
    E_ON;
    PORTLCD=(PORTLCD&0x0f)|0x20; //wyslij 2- do LCD
    asm("nop");asm("nop");asm("nop");asm("nop");
    E_OFF;
    delayms(100); // od tego momentu sprawdzamy gotowosc LCD
    lcd_trans(0x28,0); // interfejs 4-bitowy, 2 linie, znak 5x7
    lcd_trans(0x08,0); // wylacz LCD, wylacz kursor, wylacz mruganie
    lcd_trans(0x01,0); // czysc LCD nie trzeba czekac !!!
    lcd_trans(0x06,0); // zwiekszanie pozycji kursora po kazdym znaku
    lcd_trans(0x0c,0); // wlacz wyswietlacz bez kursora

    }

    // Pisanie tekstu na ekranie
    void lcd_tekst(char *tekst)
    {
    unsigned char i = 0; while (tekst[i]) lcd_trans(tekst[i++],1);
    }




    int main(void)

    {

    lcd_init();

    lcd_tekst("lcd");L_OFF;
    while(1) ;

    return(0);
    }
  • Poziom 20  
    Nie przeszkadza pod warunkiem że na D0...D3 nic się nie zmienia
    i są na nich logiczne jedynki.Dobrze by sprawdzić czy cokolwiek jest wysyłane na port (oscyloskopem lub miernikiem częstotliwości,
    teraz w wielu multimetrach jest pomiar f, nawet jak "puścisz"
    wszystko w pętli, to także woltomierzem DC możesz
    wnioskować że są impulsy , bo będzie około 2.5V na pinie który non stop
    zmienia swój stan logiczny.
  • Pomocny post
    Poziom 12  
    Powiedz mi jeszcze co oznacz taki zapis bo wcześniej wszystko robiłem na "piechotę"
    PORTLCD=(PORTLCD&0x0f)|((dana&0x0f)<<4);
    gdzie PORTLCD==
    #define PORTLCD PORTB // port z podlaczanym LCD
  • Poziom 20  
    na AVR-ach się nie znam, ale napisałeś:

    DDRLCD=0x0f; // bity D4 - D7 wejsciami
    mają być : wyjściami

    Dodano po 40 [minuty]:

    PORTLCD=(PORTLCD&0x0f)|((dana&0x0f)<<4);

    Dane z portu są "maskowane" ze stała 00001111 binarnie (logiczne and)
    po to by nie były zamieniane bity "młodsze", po czym wykonywana jest
    "suma logiczna or" z danymi (do wpisu) maskowanymi też z 00001111 binarnie, prze-
    suniętymi w prawo o 4 miejsca.No i na koniec wpis do portu.
  • Pomocny post
    Poziom 12  
    mam taki problem. wczesniej lcd mi dzialal ale cos namieszalem i nie dziala
    procedura uruchomienia
    Code:

    delayms(45);
    set_e;
    PORTD = 0x20;  //tryb 4 biotowy
    clr_e;
    delayms(5);
    //f-set
    set_e;
    PORTD = 0x20;  //2 linie zaki 5x8
    clr_e;
    set_e;
    PORTD = 0xF0;
    clr_e;
    delayms(1);

    //disp on
    set_e;
    PORTD = 0x00;
    clr_e;
    set_e;        //wyswietlacz i kursor wlaczone
    PORTD = 0xE0;
    clr_e;
    delayms(1);

    //entry mode
    set_e;
    PORTD = 0x00;
    clr_e;
    set_e;
    PORTD = 0x60;  // przesuniecie kursora w prawo po napisaniu czegos
    clr_e;
    delayms(1);


    wydaje mi sie ze robie tak jak trzeba (strona 42 datasheeta)
    lcd jest podlaczony tak ze db7-db4 = portd7-portd4 portd3 to E a portD 2 to RS
  • Poziom 20  
    instrukcja lcd "clear display" zajmuje 1.53 ms , podobnie "return home"
    Na początek puść to jak najwolniej (dłuuugie odstępy pomiędzy
    zmianami stanów na RS EN i DATA )
    No tak, zapomniałem że masz sprawdzanie zajętości...
  • Pomocny post
    Poziom 39  
    the_one napisał:
    ...wydaje mi sie ze robie tak jak trzeba (strona 42 datasheeta) ...

    Zgadzam się z Tobą - wydaje Ci się ;)
    Kilka postów wcześniej/wyżej wkleiłem rysunek/diagram , który żywcem wyciąłem z dokumentacji. Popatrz sobie spokojnie jak wygląda inicjalizacja LCD w trybie 4-bit , bo Twoja ma się nijak , do tego co tam jest napisane/narysowane.

    Piotrek
  • Pomocny post
    Poziom 12  
    zrobilem wedlgu rysunku i dalej lipa
    Code:

    DDRD=0xff;
    PORTD=0x00;
    delayms(1000); // czekaj 15ms na ustabilizowanie się napięcia zasilającego
    CLR_E; // E = 0
    CLR_RS; // RS = 0
    char i; // zmianna licznikowa

    for(i = 0; i < 3; i++) // trzykrotne powtórzenie bloku instrukcji
      {
      SET_E; // E = 1
      PORTD = 0x30; //
      CLR_E; // E = 0
      delayms(5); // czekaj 5ms
      }

    SET_E; // E = 1
    PORTD = 0x20; //
    CLR_E; // E = 0

    delayms(10);
    SET_E; // E = 1
    PORTD = 0x20;
    CLR_E; // E = 0
    SET_E; // E = 1
    PORTD = 0x80;
    CLR_E; // E = 0

    delayms(10);
    SET_E; // E = 1
    PORTD = 0x00;
    CLR_E; // E = 0
    SET_E; // E = 1
    PORTD = 0xf0;
    CLR_E; // E = 0

    delayms(10);
    SET_E; // E = 1
    PORTD = 0x00;
    CLR_E; // E = 0
    SET_E; // E = 1
    PORTD = 0x10;
    CLR_E; // E = 0

    delayms(10);
    SET_E; // E = 1
    PORTD = 0x00;
    CLR_E; // E = 0
    SET_E; // E = 1
    PORTD = 0x60;
    CLR_E; // E = 0

    delayms(10);
    SET_E; // E = 1
    PORTD = 0x00;
    CLR_E; // E = 0
    SET_E; // E = 1
    PORTD = 0x20;
    CLR_E; // E = 0

    delayms(10);
    SET_E; // E = 1
    PORTD = 0x00;
    CLR_E; // E = 0
    SET_E; // E = 1
    PORTD = 0x10;
    CLR_E; // E = 0


    dodalem tylko kursor zeby bylo widac czy dziala no i nie dzala.
  • Pomocny post
    Poziom 39  
    Tiaaa....
    Czy wszystkie linie wyświetlacza , masz podłączone do jednego portu :?:
    Jeśli tak jest , to z Twoim programem działać nie będzie :(

    Piotrek
  • Pomocny post
    Poziom 12  
    czyli chodzi o to ze stany d7-d4 opadaja razem z E i wyswietlacz ich nie rozpoznaje? tak mi wyszlo w symulatorze to najprosciej polaczyc linie danych do jednego portu a reszte do innego?
  • Pomocny post
    Poziom 12  
    a co oznacza taki zapis DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN);
    bo próbuje wykorzystać przykłady z symulatora lcd i nie wszystko rozumię