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

Inicjalizacja LCD 2x16 z Atmega - czarne kwadraty, brak działania

gszyszka 06 Kwi 2005 01:33 7235 10
REKLAMA
  • #1 1379936
    gszyszka
    Poziom 12  
    Posty: 30
    Pomógł: 2
    Posiadam LCD 2x16 (niestety nie jestem pewien co do rodzaju sterownika - na pewno HD44780 lub odpowiednik :) ,
    zakupiony na allegro:
    http://www.allegro.pl/show_item.php?item=46738573
    Wydaje się być sprawnym ponieważ po podłączeniu do zasilania pojawia się linia czarnych kwadracikow (tylko jedna)
    Nie udało mi się jak dotąd go zainicjalizować :(
    Próbowałem juz prawie wszystkiego(różne pdfy i różne czasy opóźnień, lektura elektrody), poświęciłem chyba dwa tygodnie i nic :(
    Efekt taki sam jak po podłączeniu do zasilania tzn czarne kwadraty w górnej lini
    a tutaj kawalek kodu
    void LCD_Init(){
    	//ustawienie portow jako wyjsciowe
    	DDRB = 0xFF;
    	DDRC = 0xFF;
    
    	//czyscimy porty
    	PORTB = 0x00;
    	PORTC = 0x00;
    	
    	//czekamy az ustali sie napiecie
    	delayms(500);
    	
    	
    	D5_ON;
    	D4_ON;
    	EN_ON;
    	delayms(1);
    	EN_OFF;
    	asm("nop");
    	asm("nop");
    	asm("nop");	
    	PORTB = 0x00;
    	PORTC = 0x00;
    
    	delayms(50);	
    	
    	D5_ON;
    	D4_ON;
    	EN_ON;
    	delayms(1);
    	EN_OFF;
    	asm("nop");
    	asm("nop");
    	asm("nop");	
    	PORTB = 0x00;
    	PORTC = 0x00;
    
    	delayms(50);	
    
    	D5_ON;
    	D4_ON;
    	EN_ON;
    	delayms(1);
    	EN_OFF;
    	asm("nop");
    	asm("nop");
    	asm("nop");	
    	PORTB = 0x00;
    	PORTC = 0x00;
    	
    	delayms(50);	
    	
    	D5_ON;
    	EN_ON;
    	delayms(1);
    	EN_OFF;
    	asm("nop");
    	asm("nop");
    	asm("nop");	
    	PORTB = 0x00;
    	PORTC = 0x00;
    
    	delayms(1);	
    
    	D5_ON;
    	EN_ON;
    	delayms(1);
    	EN_OFF;
    	asm("nop");
    	asm("nop");
    	asm("nop");
    	PORTB = 0x00;
    	PORTC = 0x00;
    
    	delay(1);		
    	
    	D7_ON;	//dwie linie wyswietlacza
    	D6_OFF;	//5X7 
    	EN_ON;
    	delayms(1);
    	EN_OFF;
    	asm("nop");
    	asm("nop");
    	asm("nop");
    	PORTB = 0x00;
    	PORTC = 0x00;
    	delayms(1);		
    
    	EN_ON;
    	delayms(1);
    	EN_OFF;
    	asm("nop");
    	asm("nop");
    	asm("nop");
    	PORTB = 0x00;
    	PORTC = 0x00;
    
    	delayms(1);		
    	
    	D7_ON;
    	EN_ON;
    	delayms(1);
    	EN_OFF;
    	asm("nop");
    	asm("nop");
    	asm("nop");
    	PORTB = 0x00;
    	PORTC = 0x00;
    
    	delayms(1);		
    	
    	EN_ON;
    	delayms(1);
    	EN_OFF;
    	asm("nop");
    	asm("nop");
    	asm("nop");
    	PORTB = 0x00;
    	PORTC = 0x00;
    
    	delayms(1);		
    	
    	D4_ON;
    	EN_ON;
    	delayms(1);
    	EN_OFF;
    	asm("nop");
    	asm("nop");
    	asm("nop");
    	PORTB = 0x00;
    	PORTC = 0x00;
    
    	delayms(1);	
    
    	EN_ON;
    	delayms(1);
    	EN_OFF;
    	asm("nop");
    	asm("nop");
    	asm("nop");
    	PORTB = 0x00;
    	PORTC = 0x00;
    
    	delayms(1);	
    
    	D6_ON;
    	D5_ON;
    	D4_ON;
    	EN_ON;
    	delayms(1);
    	EN_OFF;
    	asm("nop");
    	asm("nop");
    	asm("nop");
    	PORTB = 0x00;
    	PORTC = 0x00;
    
    	delayms(1);		

    Wiem że to częste pytanie ale już się zniecheciłem od ciągłego próbowania bez efektów, wiec jażeli ktoś wskaże błąd to jestem wdzięczny[/url]
  • REKLAMA
  • #2 1380001
    LordBlick
    VIP Zasłużony dla elektroda
    Posty: 5438
    Pomógł: 549
    Ocena: 69
    A schemat myszki zjadły... ;)
    Tryb 8 czy 4bit ?
    Czemu wszystki opóźnienia są w milisekundach ? największe potrzebne to 2 ms, a najmniejsze to 0.04 ms. Nadgorliwość też nie zawsze popłaca, po co ciągle "czyścisz porty" ? Po co te 3 x nop, skoro i tak czekasz 1 ms, to ma byc jakies magiczne zaklęcie ? ;)
    Najlepsza jak dla mnie strona o sterowaniu LCD na HD44780 ( po jej przeczytaniu wydłubałem od ręki procedurkę w asm, która wyświetliła "AAAAAAAA" ;) ) :
    http://home.iae.nl/users/pouweha/lcd/lcd0.shtml
    Pozdrawiam, Light-I
  • #3 1380530
    Artii80
    Poziom 11  
    Posty: 11
    Ja mam podobny problem i takie same objawy. Tylko w moim przypadku używam kompilatora keil i przykładowych programów z książki K.Kardacha wiec pomyłka jest nie możliwa, wszystkie programy z tej ksiąki były zwykle pewne. Po podłączeniu nie ma nic, no chyba ze podkręcę kontrast wtedy mam rządek czarnych kwadratów. Szukam rozwiązania mojego problemu, najlepiej przykładowych programów. Załączam program, którym steruje wyświetlacz, cw20 z książki Programowanie mikrokontrolerów z serii 8x51 w języku c

    #include <sfr51.h> /* zbiór nagłówkowy adresów rejestrów i bitów */
    sbit Button = P3^2; /* definicja adresu bitu Button */

    #define DATA_LCD P0 /* wyświetlacz podłączony do portu P0 */
    #define DC_LCD P0_4 /* linia D/~C (Data/Control) */
    #define RW_LCD P0_5 /* linia R/~W (Read/Write) */
    #define E_LCD P0_6 /* linia E (Enable) */

    /* Polecenia sterujące wyświetlacza LCD ----------------------------------*/
    #define HOME 0x80 /* ustaw kursor na początek pierwszej linii LCD */
    #define INITDISP 0x28 /* ustaw interfejs wyświetlacza LCD na 4-bity */
    #define HOM2 0xc0 /* ustaw kursor na początek drugiej linii LCD */
    #define LCDON 0x0f /* włącz LCD, włącz kursor, włącz migotanie */
    #define CLEAR 0x01 /* zeruj LCD,
    ustaw kursor na początek pierwszej linii LCD */

    /* Prototypy funkcji obsługi wyświetlacza LCD ----------------------------*/
    void LCD_ctrlWR(char);
    void LCD_dataWR(char);
    void put_message (char *);

    #define LCD_init { LCD_ctrlWR(INITDISP); \
    LCD_ctrlWR(CLEAR); LCD_ctrlWR(LCDON);}

    void main(void) {
    char i=0x20; /* pierwszy wyświetlany znak to odstęp */
    LCD_init; /* inicjalizacja LCD */


    put_message ("LCD DEMO: <<<<press P3.2");

    while(1) {
    while( Button); /* czekanie na wartość 0 na linii P3.2 */
    while(!Button); /* czekanie na wartość 1 na linii P3.3 */

    LCD_ctrlWR( HOM2); /* kolejne znaki ASCII drukowane są na
    początku drugiej linii wyświetlacza */
    LCD_dataWR( i++);
    }
    }

    /* ------------------------ sprawdzenie flagi zajętości wyświetlacza LCD */
    BYTE check_busy (void) {
    BYTE bf;
    DATA_LCD |= 0x0f; /* dane znajdują się na młodszej czwórce portu */
    DC_LCD = 0; /* linia D/~C=0 : odczyt słowa Control (statusu) */
    RW_LCD = 1; /* linia R/~W=0 : odczyt */
    E_LCD = 1;
    bf = DATA_LCD & 0x08; /* najstarszy bit informuje o zajętości LCD */
    E_LCD = 0;
    E_LCD = 1; /* linia Enable E=1: odczyt z wyświetlacza */
    E_LCD = 0; /* linia Enable E=0:koniec odczytu */
    return (bf);
    }



    /*------------------------------------- zapis 4-bitów do wyświetlacza LCD */
    void write_nibble ( BYTE nibble) {
    E_LCD = 0; /* Enable=0 */

    DATA_LCD &= 0xf0; /* pozostaw starszą czwórkę portu danych bez zmian */
    RW_LCD = 0; /* linia zapisu R/~W=0 */
    nibble &= 0x0f; /* tylko 4-młodsze bity będą zapisane */
    DATA_LCD |= nibble; /* wystawienie danych do zapisu */

    E_LCD = 1; /* linia Enable E=1: zapis do wyświetlacza */
    E_LCD = 0; /* linia Enable E=0: koniec zapisu */
    }


    /*------------------- zapis słowa sterującego Control do wyświetlacza LCD */
    void LCD_ctrlWR ( BYTE cmde) {
    while (check_busy() ); /* sprawdzenie zajętości wyświetlacza */
    DC_LCD = 0; /* wybierz rejestr Control LCD */
    write_nibble(cmde >> 4); /* zapis starszej czwórki bajtu Control */
    write_nibble(cmde); /* zapis młodszej czwórki bajtu Control */
    }


    /*---------------------------------- zapis danych Data do wyświetlacza LCD */
    void LCD_dataWR ( BYTE byte) {
    while (check_busy() ); /* sprawdzenie zajętości wyświetlacza */
    DC_LCD = 1; /* wybierz rejestr danych Data LCD */
    write_nibble(byte >> 4); /* zapis starszej czwórki bajtu Control */
    write_nibble(byte); /* zapis młodszej czwórki bajtu Control */
    }

    /*------------ podprogram drukowania ciągu znaków aż do ogranicznika 0x00 */
    void put_message (char *s) {
    while (*s)
    LCD_dataWR( *s++);
    }
  • REKLAMA
  • #4 1380595
    gmp
    Poziom 19  
    Posty: 434
    Pomógł: 29
    Ocena: 28
    Do autora: twoj program jest bardzo nieczytelny, albo zrob funkcje ktora wysylaj bajta na szyne danych do wyswietlacza, albo napisz PORTX=costam, zwazywszy ze ustawiasz wszystko bitowo (np: D4_ON) a potem zerujesz port
    (PORTC=0;) .
    Co do dlugosci opoznien to sprawdzone mam to na wielu wyswietlaczach roznych producentow i nie ma problemu z za dlugim czassem, gorej gdy jest za krotki. Starcze LCD robiona na orginalnym HD chodzily najednym programie, teraz niestety co producent to jest inna procedura inicjalizacji, choc roznia sie bardzo niewiele. Na ogol roznia sie tylko "dalszymi" bajtami tego co trzba wyslac. No i jeszce nie mialbym pewnosci co do sprawnosci tego wyswietlacza. Poza tym programy na LCD znajdzeisz w necie , a na pewno na avrfreaks. A i jeszce daj definicje swoich makr, bo ja nie wiem czy np: E_ON jest poprawnie.
  • REKLAMA
  • #5 1380612
    PioTherm
    Poziom 16  
    Posty: 134
    Pomógł: 11
    Ocena: 19
    Częstymi przyczynami wyświetlania kwadracików jest złe podłączenie wyświetlacza do mikrokontrolera. Drugą przyczyną może być to że np w ATMEGA32 defaultowo masz zajęte piny na porcie C dla interfejsu JTAG wskutek czego jak masz podłączony wyświetlacz pod te zajęte piny wyświetla on dziwne znaczki lub właśnie kwadraty.
  • REKLAMA
  • #6 1380708
    gszyszka
    Poziom 12  
    Posty: 30
    Pomógł: 2
    Co do makr
    //definicja polaczen
    #define D7_ON sbi(DDRC, PC5);sbi(PORTC, PC5);
    #define D7_OFF sbi(DDRC, PC5);cbi(PORTC, PC5);
    
    #define D6_ON sbi(DDRC, PC4);sbi(PORTC, PC4);
    #define D6_OFF sbi(DDRC, PC4);cbi(PORTC, PC4);
    
    #define D5_ON sbi(DDRC, PC3);sbi(PORTC, PC3);
    #define D5_OFF sbi(DDRC, PC3);cbi(PORTC, PC3);
    
    #define D4_ON sbi(DDRC, PC2);sbi(PORTC, PC2);
    #define D4_OFF sbi(DDRC, PC2);cbi(PORTC, PC2);
    
    #define EN_ON sbi(DDRB, PB3);sbi(PORTB, PB3);
    #define EN_OFF sbi(DDRB, PB3);cbi(PORTB, PB3);
    
    #define RS_ON sbi(DDRB, PB1);sbi(PORTB, PB1);
    #define RS_OFF sbi(DDRB, PB1);cbi(PORTB, PB1);


    dodam ze probowalem te inaczej np
    //definicja polaczen
    #define D7_ON sbi(PORTC, PC5);
    #define D7_OFF cbi(PORTC, PC5);
    
    #define D6_ON sbi(PORTC, PC4);
    #define D6_OFF cbi(PORTC, PC4);
    
    #define D5_ON sbi(PORTC, PC3);
    #define D5_OFF cbi(PORTC, PC3);
    
    #define D4_ON sbi(PORTC, PC2);
    #define D4_OFF cbi(PORTC, PC2);
    
    #define EN_ON sbi(PORTB, PB3);
    #define EN_OFF cbi(PORTB, PB3);
    
    #define RS_ON sbi(PORTB, PB1);
    #define RS_OFF cbi(PORTB, PB1);

    co do czytelności to uważalem że tak będzie najlepiej ze względu na podłączenie wyświetlacza w nieklasyczny sposób tzn nie do jednego portu i wysyłanie bajtów na port troche zniekształaca całość

    czy to możliwe że to właśnie PORTC może być odpowiedzialny za taki stan rzeczy??
  • #7 1380728
    PioTherm
    Poziom 16  
    Posty: 134
    Pomógł: 11
    Ocena: 19
    Dokładnie. Napisałem powyżej że w ATMEDZE32 połowa pinów z portu C jest wykorzystywana domyślnie przez interfejs JTAG.

    Jakiego proca używasz ?
  • #8 1380770
    gszyszka
    Poziom 12  
    Posty: 30
    Pomógł: 2
    Dokladnie ATmega32 :)
    jestem podpiety z linią danych D4-D7 pod piny PC2-PC5
    z tego co widze to wlasnie te piny sa wykorzystywane przez interfejs JTAG czy czeka mnie przelutowywanie układu???
  • Pomocny post
    #9 1380814
    Pituś Bajtuś
    Poziom 28  
    Posty: 934
    Pomógł: 137
    Ocena: 10
       
    MCUCSR |= 0x80;
    MCUCSR |= 0x80;
    


    Wstaw te dwie instrukcje na początku programu. JTAG zostanie wyłączony będziesz mógł normalnie korzystać z pinów portu C. I to że są dwie identyczne instrukcje to nie przypadek ani pomyłka :) Tak ma być.
  • Pomocny post
    #10 1380896
    PioTherm
    Poziom 16  
    Posty: 134
    Pomógł: 11
    Ocena: 19
    No to Bingo. Także wyświetlacz masz pewnie sprawny i układ z programem również. Ja wiem tylko jak wyłączyć obsługę interfejsu JTAG
    za pomocą FUSE Bitów w BASCOMIE.
    Niestety na C się nie znam ani na ASMie

    pzdr.
    Piotrunio
  • #11 1381266
    gszyszka
    Poziom 12  
    Posty: 30
    Pomógł: 2
    Z pewnością to było to ponieważ wyświetlacz zareagował na inicjalizację "zbladnięciem" i pojawieniem sie kawałka drugiej linii. Jeszcze nic nie wyświetlam ale mam nadzieje że to już tylko kwestia czasu:)
    Dzięki wielki sam bym na to w życiu nie wpadł

Podsumowanie tematu

LABEL_AI_GENERATED
Problem dotyczył inicjalizacji wyświetlacza LCD 2x16 z kontrolerem HD44780 lub odpowiednikiem pod mikrokontrolerem ATmega32. Po podłączeniu pojawiała się tylko górna linia czarnych kwadratów, co wskazuje na brak poprawnej inicjalizacji. Dyskusja zwróciła uwagę na możliwe przyczyny: błędne podłączenie, nieodpowiednie czasy opóźnień, nieczytelny kod inicjalizacji oraz domyślne wykorzystanie pinów portu C w ATmega32 przez interfejs JTAG, który blokuje dostęp do linii danych D4-D7 podłączonych do PC2-PC5. Rozwiązaniem było wyłączenie interfejsu JTAG poprzez ustawienie bitu MCUCSR |= 0x80 na początku programu, co umożliwiło poprawną komunikację z wyświetlaczem i reakcję na inicjalizację. Wskazano również na konieczność przemyślenia struktury kodu, unikania nadmiernego czyszczenia portów oraz stosowania odpowiednich opóźnień zgodnych ze specyfikacją HD44780.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA