Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Atmega8 LCD 4-bitowa magistrala program C nie dziala

31 May 2009 22:40 1563 20
  • Level 14  
    Witam
    Mam problem z wysterowaniem wyswietlacza. Kombinacja podlaczenia pinow do procka jest nastepujaca:
    DB4->PORTC.0,
    DB5->PORTC.1,
    DB6->PORTC.2,
    DB7->PORTC.3,

    E->PORTC.4
    RS->PORTC.5

    Na ekranie nic sie nie pojawia, a polaczenia sprawdzane byly dokladnie. Oto kod wyslania instrukcji do LCD.
    Code:


    void piszlcd(unsigned char instr)
    {
       PORTC.5 = 0;
       PORTC.4 = 1;
       PORTC = (PORTC&0Xf0) | (instr&0xf0);
       delay_ms(1);
       PORTC.4 = 0;
       delay_us(50);
       PORTC.4 = 1;
       PORTC = (PORTC&0xf0) | ((instr&0x0f)<<4);
       delay_us(50);
       PORTC.4 = 0;
       delay_us(50);
       
    }

    void piszdlcd(char dana)
    {
       PORTC.5 = 1;
       PORTC.4 = 1;
       PORTC = (PORTC&0XF0) | (dana&0xF0);
       delay_ms(1);
       PORTC.4 = 0;
       delay_us(50);
       PORTC.4 = 1;
       PORTC = (PORTC&0xF0) | ((dana&0x0F)<<4);
       delay_us(100);
       PORTC.4 = 0;
       delay_us(50);
       
    }



    Code:


    piszlcd(0x28);
    piszlcd(0x08);
    piszlcd(0x01);
         
    piszlcd(0x0f);   

    piszdlcd('A');




    Z gory dziekuje za pomoc i pozdrawiam

    Dodano po 1 [minuty]:

    Piecia wrote:
    Witam
    Mam problem z wysterowaniem wyswietlacza. Kombinacja podlaczenia pinow do procka jest nastepujaca:
    DB4->PORTC.0,
    DB5->PORTC.1,
    DB6->PORTC.2,
    DB7->PORTC.3,

    E->PORTC.4
    RS->PORTC.5

    Na ekranie nic sie nie pojawia, a polaczenia sprawdzane byly dokladnie. Oto kod wyslania instrukcji do LCD.
    Code:


    void piszlcd(unsigned char instr)
    {
       PORTC.5 = 0;
       PORTC.4 = 1;
       PORTC = (PORTC&0Xf0) | (instr&0xf0);
       delay_ms(1);
       PORTC.4 = 0;
       delay_us(50);
       PORTC.4 = 1;
       PORTC = (PORTC&0xf0) | ((instr&0x0f)<<4);
       delay_us(50);
       PORTC.4 = 0;
       delay_us(50);
       
    }

    void piszdlcd(char dana)
    {
       PORTC.5 = 1;
       PORTC.4 = 1;
       PORTC = (PORTC&0XF0) | (dana&0xF0);
       delay_ms(1);
       PORTC.4 = 0;
       delay_us(50);
       PORTC.4 = 1;
       PORTC = (PORTC&0xF0) | ((dana&0x0F)<<4);
       delay_us(100);
       PORTC.4 = 0;
       delay_us(50);
       
    }



    Code:


    void main(void)


    ////////////////konf portow   /////////////////////
    PORTC = 0xff;   
    PORTB = 0x03;
    DDRD = 0x00;
    DDRC = 0xff;

    piszlcd(0x28);
    piszlcd(0x08);
    piszlcd(0x01);
         
    piszlcd(0x0f);   

    piszdlcd('A');

    }



    Z gory dziekuje za pomoc i pozdrawiam
    Trendy 2021 w branży Internetu rzeczy [Webinar 02.07.2021, g.12.00]. Zarejestruj się za darmo
  • Level 16  
    Witam,

    Chcesz operować danymi na młodszych bitach portu C:
    Quote:
    DB4->PORTC.0,
    DB5->PORTC.1,
    DB6->PORTC.2,
    DB7->PORTC.3,


    Tu ustawiasz starsze bity tego portu:
    Quote:
    Code:
       PORTC = (PORTC&0Xf0) | (instr&0xf0);
    
    ...
       PORTC = (PORTC&0xf0) | ((instr&0x0f)<<4);


    Proponuje spróbować:
    Code:
       PORTC = (PORTC&0Xf0) | ((instr&0xf0)>>4);
    
    ...
       PORTC = (PORTC&0xf0) | (instr&0x0f);
  • Level 14  
    Zrobilem tak jak napisales i bez skutku... Przesylam caly kod programu
    Code:

    #include <mega8.h>
    #include <delay.h>
    #include <stdlib.h>
    #include <io.h>
    #include <string.h>


    #define lcd_rs 6
    #define lcd_e 5
    #define CR 0x0a
    #define tau0 247
    #define vliczt0 113


    unsigned char wiersz = 0;
    unsigned char kolumna = 0;
    unsigned char liczt0;
    unsigned char licznik = 0;

    // Declare your global variables here

    int i, a, b;





    //da - portd, st - portc


    void czekaj(unsigned long pt)
    {
       #define tau 10.38
       unsigned char tp1;
       for(; pt>0; pt--)
          for(tp1=255; tp1!=0; tp1--);
         
    }

       
    void piszlcd(unsigned char instr)
    {
       PORTC.5 = 0;
       PORTC.4 = 1;
       PORTC = (PORTC&0Xf0) | ((instr&0x0f)>>4);
       delay_ms(1);
       PORTC.4 = 0;
       delay_ms(1);
       PORTC.4 = 1;
       PORTC = (PORTC&0xf0) | (instr&0xf0);
       delay_ms(1);
       PORTC.4 = 0;
       delay_ms(1);
       
    }

    void piszdlcd(char dana)
    {
       PORTC.5 = 1;
       PORTC.4 = 1;
       PORTC = (PORTC&0Xf0) | ((dana&0x0f)>>4);
       delay_ms(1);
       PORTC.4 = 0;
       delay_ms(1);
       PORTC.4 = 1;
       PORTC = (PORTC&0xf0) | (dana&0xf0);
       delay_us(100);
       PORTC.4 = 0;
       delay_us(50);
       
    }

    void czysclcd(void)
    {
      piszlcd(0x01);
      czekaj(1.64*tau);
      wiersz = 0;
      kolumna = 0;
       
    }

    void piszznak(char znak)
    {
       piszdlcd(znak);
       
       if(++kolumna == 16) {
          kolumna = 0;
          if(wiersz == 2)
             wiersz = 0;
       
       }   
    }

    void lcdxy(unsigned char w, unsigned char k)
    {
       piszlcd((w * 0x40+k)|0x80);
    }

    void pisztekst(char *tekst)
    {
       char zn;
       char dlugosc;
       char tab[32];
       int k;
       
       for(k=0; k<32; k++)
          tab[k] = '';
       
       zn = *tekst;
       dlugosc = strlen(tekst);
       
       for(k=0; k<dlugosc; k++) {
          tab[k] = *(tekst+k);
         
       }
       
       // wyświetlenie
       
       for(k=0; k<=dlugosc; k++) {
          piszdlcd(tab[k]);
         
       }
       
       
    }


    void main(void)

    int p=0;
    char *p1;
    long int licz;

    char *tekst = "txt pierwszy";
    char *tekst1 = "init";
    char *tekst2 = " ";
    char *tekst3 = "second button ON";
    char *tekst4 = "tekst 2";
    ////////////////konf portow   /////////////////////
    PORTC = 0xff;   
    PORTB = 0x03;
    DDRD = 0x00;
    DDRC = 0xff;
    ////////////////main//////////////////////
    czekaj(45*tau);




    //


    for(i=0; i<3; i++) {
       PORTC.4 = 1;
       PORTC = (PORTC&0Xf0) | 0x30;
       delay_ms(7);
       PORTC.4 = 0;
       czekaj(5*tau);
         
    }
     
       PORTC.4 = 1;
       PORTC = (PORTC&0XF0) | 0x20;
       delay_ms(7);
       PORTC.4 = 0;
       czekaj(10L);
       
    piszlcd(0x28);
    piszlcd(0x08);
    piszlcd(0x01);
    czekaj(1.64*tau);
         
       
    czysclcd();

    piszlcd(0x0f);   


    lcdxy(0,15);


    delay_ms(300);

    piszlcd(0x0c); 
     
     
      while(1)                   
      {
        lcdxy(0,15);
        pisztekst(tekst4);
        czekaj(100L*tau);
        for(i=0; i<14; i++) {
           
           piszlcd(0x18);
           czekaj(25*tau);
           
        }
        delay_ms(1000);
        lcdxy(0,1);
         for(i=0; i<14; i++) {
           pisztekst(tekst2);
           czekaj(40*tau);
           
        }
        delay_ms(20);
        czysclcd();
       
      }
                               
       
    }


    Na wyswietlaczu bez zmian - brak czegokolwiek :]

    pozdrawiam
  • Level 16  
    Nie zrobiles tak jak napisalem. Zwroc uwage na wartosci 0xf0 i 0x0f oraz operator >>.
  • Level 14  
    Zmienilem i dalej nic :((( Funkcje wygladaja nastepujaco :
    Code:

    void piszlcd(unsigned char instr)
    {
       PORTC.5 = 0;
       PORTC.4 = 1;
       PORTC = (PORTC&0Xf0) | ((instr&0xf0)>>4);
        delay_ms(2);
       PORTC.4 = 0;
        delay_ms(2);
       PORTC.4 = 1;
       PORTC = (PORTC&0xf0) | (instr&0x0f);
        delay_ms(2);
       PORTC.4 = 0;
        delay_ms(2);
       
    }

    void piszdlcd(char dana)
    {
       PORTC.5 = 1;
       PORTC.4 = 1;
       PORTC = (PORTC&0Xf0) | ((dana&0xf0)>>4);
       delay_ms(2);
       PORTC.4 = 0;
       delay_ms(2);
       PORTC.4 = 1;
       PORTC = (PORTC&0xf0) | (dana&0x0f);
        delay_ms(2);
       PORTC.4 = 0;
        delay_ms(2);
       
    }

  • Level 25  
    Jeżeli chodzi o tego typu wyrażenia:
    Code:
    PORTC = (PORTC&0xf0) | (instr&0x0f); 


    to radzilbym calość po znaku '=' ograniczyć nawiasami, bo tak to jak dla mnie najpierw na port wpisujesz 0xf0 a dopiero pózniej są wykonywane operacje logiczne. Zrób tak:
    Code:
    PORTC = ((PORTC&0xf0) | (instr&0x0f)); 

    i testuj czy działa... a i może sie mylę ale osobiście wróciłbym do pierwszego zapisu.
    Przykładowa moja funkcja zapisująca bajt do lcd, pisana dla dsPIC:
    Code:
    void write_to_lcd(char data, char rs){
    
       if(rs==1)
       {SET_RS;}
       else
       {CLR_RS;}
       DATA=((DATA&0xFF0F)|(data&0xF0));
       SET_E;
       delay_1us();
       CLR_E;
       delay_1us();
       DATA=((DATA&0xFF0F)|((data&0x0F)<<4));
       SET_E;
       delay_1us();
       CLR_E;
       delay_1us();
       CLR_RS;
    }

    do DATA jest przypisany port. Reszta chyba jasna:)
  • Level 14  
    Mat_91 wrote:
    Jeżeli chodzi o tego typu wyrażenia:
    Code:
    PORTC = (PORTC&0xf0) | (instr&0x0f); 


    to radzilbym calość po znaku '=' ograniczyć nawiasami, bo tak to jak dla mnie najpierw na port wpisujesz 0xf0 a dopiero pózniej są wykonywane operacje logiczne. Zrób tak:
    Code:
    PORTC = ((PORTC&0xf0) | (instr&0x0f)); 

    i testuj czy działa... a i może sie mylę ale osobiście wróciłbym do pierwszego zapisu.


    Zmieniłem tak jak napisałeś i dalej bez skutku..

    Mat_91 wrote:

    Przykładowa moja funkcja zapisująca bajt do lcd, pisana dla dsPIC:
    Code:
    void write_to_lcd(char data, char rs){
    
       if(rs==1)
       {SET_RS;}
       else
       {CLR_RS;}
       DATA=((DATA&0xFF0F)|(data&0xF0));
       SET_E;
       delay_1us();
       CLR_E;
       delay_1us();
       DATA=((DATA&0xFF0F)|((data&0x0F)<<4));
       SET_E;
       delay_1us();
       CLR_E;
       delay_1us();
       CLR_RS;
    }

    do DATA jest przypisany port. Reszta chyba jasna:)


    Kiedys tez zrobilem dzialający LCD na PORTB, gdzie DB4-7 polaczone bylo z PORTB.4-7. Sadzac po Twoim sterowaniu masz podlaczony tak samo jak ja mialem wtedy. Teraz niestety plytka jest wytrawiona i musze jakosc wysterowac na mlodszych bitach portu B;/ Programu wykonawczegno nie zmienilem ale sadze ze cos sknocone jest z operatorami przesuniecia bitów ;/// teraz DB4-7 jest podlaczone do PORTC.0-3. Nie wiem czemu ale do niedawna dalbym glowe sobie uciac ze to bedzie dzialac :]
  • Level 25  
    Bo to powinno działać, hmm... postaram sie jutro na szybko zlutować jakiś układ z LCD na pinach innych niz 4-7, napisze jutro wieczorem czy działa:|
  • MCUs specialist
    Piecia wrote:

    Kiedys tez zrobilem dzialający LCD na PORTB, gdzie DB4-7 polaczone bylo z PORTB.4-7. Sadzac po Twoim sterowaniu masz podlaczony tak samo jak ja mialem wtedy. Teraz niestety plytka jest wytrawiona i musze jakosc wysterowac na mlodszych bitach portu B;/ Programu wykonawczegno nie zmienilem ale sadze ze cos sknocone jest z operatorami przesuniecia bitów ;/// teraz DB4-7 jest podlaczone do PORTC.0-3. Nie wiem czemu ale do niedawna dalbym glowe sobie uciac ze to bedzie dzialac :]



    Popraw inicjalizację wyświetlacza

    Code:


    for(i=0; i<3; i++) {
       PORTC.4 = 1;
       PORTC = (PORTC & 0xf0) | 0x03;
       delay_ms(7);
       PORTC.4 = 0;
       czekaj(5*tau);
         
    }
     
       PORTC.4 = 1;
       PORTC = (PORTC & 0xf0) | 0x02;
       delay_ms(7);
       PORTC.4 = 0;
       czekaj(10L);


    W więcej kodu nie wnikałem, jest mało czytelny.
  • Level 16  
    Nie mam pod reka specyfikacji wyswietlacza, ale na podstawie wypowiedzi kolegi:
    Mat_91 wrote:

    Code:
       DATA=((DATA&0xFF0F)|(data&0xF0));
    
       SET_E;
       delay_1us();
       CLR_E;




    Proponuje przeniesc linie:
    Code:
    PORTC.4=1

    ponizej linijki wystawiajacej dane na port C. Zachowaj format jaki podalem w drugim poscie.
  • Level 25  
    Gdzie masz inicjalizację LCD ?
    Jesli to jest inicjalizacja:
    Code:

    piszlcd(0x28);
    piszlcd(0x08);
    piszlcd(0x01);
    piszlcd(0x0f);

    to jest to tylko konfiguracja, a gdzie jest trzykrotnie wykonywana pętla z komendą inicjalizacji ?

    PS.
    Gdzie zachowanie odpowiednich odstępów czasowych między komendami LCD ?
  • Level 14  
    Piecia wrote:




    void piszlcd(unsigned char instr)
    {
    PORTC.5 = 0;
    PORTC.4 = 1;
    PORTC = (PORTC&0Xf0) | ((instr&0xf0)>>4);
    delay_ms(1);
    PORTC.4 = 0;
    delay_ms(1);
    PORTC.4 = 1;
    PORTC = (PORTC&0xf0) | (instr&0x0f);
    delay_ms(1);
    PORTC.4 = 0;
    delay_ms(1);

    }


    void piszdlcd(char dana)
    {
    PORTC.5 = 1;
    PORTC.4 = 1;
    PORTC = (PORTC&0Xf0) | ((dana&0xf0)>>4);
    delay_ms(1);
    PORTC.4 = 0;
    delay_ms(1);
    PORTC.4 = 1;
    PORTC = (PORTC&0xf0) | (dana&0x0f);
    delay_us(100);
    PORTC.4 = 0;
    delay_us(50);

    }


    To sa odstepy czasowe uzyte wewnatrz funkcji wyslania komendy do LCD


    Piecia wrote:



    for(i=0; i<3; i++) {
    PORTC.4 = 1;
    PORTC = (PORTC&0Xf0) | 0x30;
    delay_ms(7);
    PORTC.4 = 0;
    czekaj(5*tau);

    }

    PORTC.4 = 1;
    PORTC = (PORTC&0XF0) | 0x20;
    delay_ms(7);
    PORTC.4 = 0;
    czekaj(10L);

    piszlcd(0x28);
    piszlcd(0x08);
    piszlcd(0x01);
    czekaj(1.64*tau);


    czysclcd();

    piszlcd(0x0f);


    lcdxy(0,15);


    delay_ms(300);

    piszlcd(0x0c);



    Inicjalizacja
    wszystko bylo we wczesniejszych postach...
  • Level 25  
    Przepraszam ze dopiero teraz pisze, wcześniej nie miałem okazji. U mnie działam na całym porcie. Musisz szukać błędu w kodzie:
    -inicjalizacje umieść w osobnej funkcji,
    -sprawdź opóźnienia czasowe, jesteś pewny że są dokładne?
    -i teraz pytam: Czy poprawiłeś wszystkie linijki tego typu:
    Code:
    PORTC = (PORTC&0XF0) | 0x20; 

    tak jak Ci wcześniej sugerowałem?

    ps.:
    sprawdź TEN temat, jest tam umieszczony cały kod z którego korzystam, na inny procesor ale z przepisaniem go na avr nie powinno być problemu.
  • Level 25  
    Jeśli nawet krzaków nie wyświetla, to nadal upierałbym się przy czasach i/lub inicjalizacji. Trochę jest to chaotyczne i totalnie nie w moim stylu dlatego ciężko mi to analizować.

    PS. Jakiego kompilatora używasz ? Jak będę miał chwilę to spróbuje to uruchomić.
  • Level 14  
    Podkreslam: Kod ten dzialal poprawnie gdy mialem podlaczone dane LCD db4-7 do pinow portb.4-7, a linie sterujace do portb.2-3. Z tym ze wtedy i instrukcje wysylaly sie w taki sposob:

    PORTB = (PORTB&0X0f) | (instr&0xf0);
    ...
    PORTB = (PORTB&0x0f) | ((instr&0x0f)<<4);

    po zmianie na mlodsze bity i na portc nic nie dziala. Polaczenia sprawdzalem wielokrotnie wiec to napewno nie to..

    czasy sa podobierane z duzym zapasem wiec nie powinno byc z tym problemu, aha i portc ma 7 wyjsc a nie jak pozostale porty - 8..

    Uzywam Codevision V2.03
  • Level 16  
    No dobrze, nareszcie piszę z komputera, a nie z telefonu.

    Do poprawy:

    Code:

    void piszlcd(unsigned char instr)
    {
       PORTC.5 = 0;
       PORTC.4 = 1;
       PORTC = ((PORTC&0xf0) | ((instr&0xf0)>>4));   // tutaj (4 starsze bity)
       delay_ms(1);
       PORTC.4 = 0;
       delay_ms(1);
       PORTC.4 = 1;
       PORTC = ((PORTC&0xf0) | (instr&0x0f));           // tutaj (4 młodsze bity)
       delay_ms(1);
       PORTC.4 = 0;
       delay_ms(5);                                                  // tutaj - czas wykonywania instrukcji max. 4,8ms
       
    }

    void piszdlcd(char dana)
    {
       PORTC.5 = 1;
       PORTC.4 = 1;
       PORTC = ((PORTC&0xf0) | ((dana&0xf0)>>4));   // tutaj j.w.
       delay_ms(1);
       PORTC.4 = 0;
       delay_ms(1);
       PORTC.4 = 1;
       PORTC = (PORTC&0xf0) | (dana&0x0f));            // tutaj j.w.
       delay_us(100);
       PORTC.4 = 0;
       delay_us(100);                                                // tutaj - max. czas obsługi wysłanego znaku 120us
       
    }

    //  dalszy ciąg programu

    void main(void)

    int p=0;
    char *p1;
    long int licz;

    char *tekst = "txt pierwszy";
    char *tekst1 = "init";
    char *tekst2 = " ";
    char *tekst3 = "second button ON";
    char *tekst4 = "tekst 2";
    ////////////////konf portow   /////////////////////
    PORTC = 0xff;   
    PORTB = 0x03;
    DDRD = 0x00;
    DDRC = 0xff;
    ////////////////main//////////////////////
    czekaj(45*tau);




    //

    PORTC.5 = 0;                           // tutaj - będziemy wysyłać instrukcje init LCD
    for(i=0; i<3; i++) {
       PORTC.4 = 1;
       PORTC = ((PORTC&0xf0) | 0x03);   // tutaj - dane LCD na 4 młodszych bitach PORTC
       delay_ms(7);
       PORTC.4 = 0;
       czekaj(5*tau);
         
    }
     
       PORTC.4 = 1;
       PORTC = ((PORTC&0xf0) | 0x02);   // tutaj - dane LCD na 4 młodszych bitach PORTC 
       delay_ms(7);
       PORTC.4 = 0;
       czekaj(10L);
       
       PORTC.4 = 1;                                // wymagane 2razy
       PORTC = ((PORTC&0xf0) | 0x02);   // tutaj - dane LCD na 4 młodszych bitach PORTC 
       delay_ms(7);
       PORTC.4 = 0;
       czekaj(10L);
       
    piszlcd(0x28);
    piszlcd(0x0c);                           // tutaj - 0x0c - Display ON
    piszlcd(0x01);
    czekaj(1.64*tau);
         
    // dalsza część programu



    Jeśli nie zadziała to nie wiem.
  • Level 14  
    tekst skopiowany - dalej nie dziala...:( wyswietlaja sie tyko pelne segmenty jednego wiersza wyswietlacza - nie dziala w ogole...
  • Level 16  
    Jeśli nie zadziałało, spróbuj na początek prostym programem wysterować pojedyncze bity portu C z diodą LED.

    Poprawka do mojego poprzedniego postu:
    Code:
    void piszdlcd(char dana)
    
    {
       PORTC.5 = 1;
       PORTC.4 = 1;
       PORTC = ((PORTC&0xf0) | ((dana&0xf0)>>4));   // tutaj j.w.
       delay_ms(1);
       PORTC.4 = 0;
       delay_ms(1);
       PORTC.4 = 1;
       PORTC = ((PORTC&0xf0) | (dana&0x0f));            // tutaj j.w. - BRAKOWAŁO NAWIASU
       delay_us(100);
       PORTC.4 = 0;
       delay_us(100);                                                // tutaj - max. czas obsługi wysłanego znaku 120us
       
    }
  • Level 14  
    no wiem program mi sie nie skompilowal ale poprawilem i poszlo... Mimo to na wyswietlaczu bez zmian..
  • Level 25  
    Może głupie pytanie ale tylko chciałem się upewnić, czy zasilasz Avcc(pin20) ?
  • Level 14  
    sprawdzalem juz obie opcje... podlaczalem AVCC i tez nic nie dalo..