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

Atmega8 LCD 4-bitowa magistrala program C nie dziala

Piecia 31 Maj 2009 22:38 1641 20
  • #1 6600956
    Piecia
    Poziom 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.
    
    
    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);
       
    }
    
    


    
    
    piszlcd(0x28);
    piszlcd(0x08);
    piszlcd(0x01);
          
    piszlcd(0x0f);   
    
    piszdlcd('A');
    
    



    Z gory dziekuje za pomoc i pozdrawiam

    Dodano po 1 [minuty]:

    Piecia napisał:
    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.
    
    
    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);
       
    }
    
    


    
    
    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
  • #2 6601082
    hose2
    Poziom 17  
    Witam,

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


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


    Proponuje spróbować:
       PORTC = (PORTC&0Xf0) | ((instr&0xf0)>>4);
    ...
       PORTC = (PORTC&0xf0) | (instr&0x0f);
    
  • #3 6603177
    Piecia
    Poziom 14  
    Zrobilem tak jak napisales i bez skutku... Przesylam caly kod programu
    
    #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
  • #4 6605766
    hose2
    Poziom 17  
    Nie zrobiles tak jak napisalem. Zwroc uwage na wartosci 0xf0 i 0x0f oraz operator >>.
  • #5 6607629
    Piecia
    Poziom 14  
    Zmienilem i dalej nic :((( Funkcje wygladaja nastepujaco :
    
    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);
       
    }
    
    
  • #6 6608051
    Mat_91
    Poziom 25  
    Jeżeli chodzi o tego typu wyrażenia:
    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:
    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:
    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:)
  • #7 6608891
    Piecia
    Poziom 14  
    Mat_91 napisał:
    Jeżeli chodzi o tego typu wyrażenia:
    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:
    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 napisał:

    Przykładowa moja funkcja zapisująca bajt do lcd, pisana dla dsPIC:
    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 :]
  • #8 6609021
    Mat_91
    Poziom 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:|
  • #9 6609086
    michalko12
    Specjalista - Mikrokontrolery
    Piecia napisał:

    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

    
    
    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.
  • #10 6612805
    hose2
    Poziom 17  
    Nie mam pod reka specyfikacji wyswietlacza, ale na podstawie wypowiedzi kolegi:
    Mat_91 napisał:

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




    Proponuje przeniesc linie:

    ponizej linijki wystawiajacej dane na port C. Zachowaj format jaki podalem w drugim poscie.
  • #11 6618719
    Kolek
    Poziom 25  
    Gdzie masz inicjalizację LCD ?
    Jesli to jest inicjalizacja:
    
    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 ?
  • #12 6620519
    Piecia
    Poziom 14  
    Piecia napisał:




    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 napisał:



    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...
  • #13 6620671
    Mat_91
    Poziom 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:
    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.
  • #14 6621226
    Kolek
    Poziom 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ć.
  • #15 6621303
    Piecia
    Poziom 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
  • #16 6621355
    hose2
    Poziom 17  
    No dobrze, nareszcie piszę z komputera, a nie z telefonu.

    Do poprawy:

    
    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.
  • #17 6621406
    Piecia
    Poziom 14  
    tekst skopiowany - dalej nie dziala...:( wyswietlaja sie tyko pelne segmenty jednego wiersza wyswietlacza - nie dziala w ogole...
  • #18 6622079
    hose2
    Poziom 17  
    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:
    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
       
    }
    
  • #19 6622254
    Piecia
    Poziom 14  
    no wiem program mi sie nie skompilowal ale poprawilem i poszlo... Mimo to na wyswietlaczu bez zmian..
  • #20 6622499
    Kolek
    Poziom 25  
    Może głupie pytanie ale tylko chciałem się upewnić, czy zasilasz Avcc(pin20) ?
  • #21 6626765
    Piecia
    Poziom 14  
    sprawdzalem juz obie opcje... podlaczalem AVCC i tez nic nie dalo..
REKLAMA