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

[ATmega32] [C] dziwne zachowanie LCD 2x20 na HD44100FS

csdominik 21 Paź 2010 17:07 1806 2
REKLAMA
  • #1 8646668
    csdominik
    Poziom 11  
    Witam serdecznie.
    Jakiś czas temu kupiłem sobie nowy wyjątkowo duży wyświetlacz LCD, ponieważ potrzebowałem taki do mojego projektu. Przed kupnem zorientowałem się w wyświetlaczach, i okazało się ze mój stary wyświetlacz ma sterownik HD44780, natomiast nowy ma HD44100FS. Na elektrodzie wyczytałem że - to nic nie szkodzi, najwyżej będę miał do dyspozycji 16 znaków w linii a nie 20. Moim głównym założeniem było zwiększenie czytelności interfejsu - więc mogłem sobie pozwolić na to ograniczenie. Podsumowując, myślałem że wystarczy wyciągnąć mój stary LCD 2x16 , wetknąć odpowiednio nowy, i będzie wszystko OK... niestety nic z tego.
    Wyświetlacz przy wewnętrznym oscylatorze 1Mhz wyświetla poprawnie tekst - ale tylko w 1 linii. Do 2 linii nie ma dostępu.
    Po dołączeniu do Atmegi32 kwarcu 16Mhz skuteczność poprawnego wyświetlania w 1 linii spadła do powiedzmy 60% (czyli 40% znaków przekłamanych), dostępu do 2 linii nadal nie ma. Po małej modyfikacji opóźnień w funkcji inicjalizacji LCD osiągnąłem poprawne wyświetlanie w 1 linii. Niestety nadal nie jestem w stanie przejść do 2 linii. Ani za pomocą moich funkcji - ani w nieskończoność wysyłając znaki do LCD (co przy sterowniku z mojego starszego LCD było możliwe).

    Oczywiście stary LCD 2x16 z HD44780 działa poprawnie.

    Przejrzałem datasheet do HD44100 i nie ma tam żadnych komend, jest tylko metoda aplikacji.

    Czy spotkał się ktoś z takim problemem?

    Załączam funkcję których używam :
    Cytat:

    void Wyslij_do_LCD(int8_t bajt)
    {
    //ustawienie EN
    PORT_LCD |= _BV(EN_LCD);

    //wysłanie 4 najstarszych bitów danych
    PORT_LCD = (bajt & 0xF0)|(PORT_LCD & 0x0F);

    //potwierdzenie wysłania danych (opadającym zboczem EN)
    PORT_LCD &= ~(_BV(EN_LCD));

    //zaczekaj cykl
    asm volatile("nop");

    //ustawienie EN
    PORT_LCD |= _BV(EN_LCD);

    //wysłanie 4 najmłodszych bitów danych
    PORT_LCD = ((bajt & 0x0F)<<4)|(PORT_LCD & 0x0F);

    //potwierdzenie wysłania danych (opadającym zboczem EN)
    PORT_LCD &= ~(_BV(EN_LCD));

    //zaczekaj 100 us - dla poprawnego wyświetlania
    _delay_us(100);
    }


    void komendaLCD(int8_t x)
    { // wysyła komendę do LCD
    PORT_LCD &= ~(_BV(RS_LCD));
    Wyslij_do_LCD(x);
    PORT_LCD |= _BV(RS_LCD);
    }


    void ustaw_kursorLCD(int8_t x, int8_t y)
    {//przesowa kursor na (x,y)
    komendaLCD(0x80 | (x + (0x40 * y)));
    }



    Pozdrawiam
    Dominik
  • REKLAMA
  • #2 8647134
    gdL
    Poziom 27  
    Poprawnie inicjujesz wyświetlacz, żeby wyświetlał 2 linie ?

    U mnie to wygląda tak :

    
    void lcd_init() {
    _delay_ms(20);
    LCD_DataDR = 0xFF;
    LCD_DataPort |=1<<LCD_LIGHT;
    LCD_DataPort &= ~(1<<LCD_RS); // zeruje RS
    LCD_DataPort &= ~(1<<LCD_EN); // zeruje E
    _delay_ms(2);
    
    for (int i = 0; i < 3; i++ ) {
    LCD_DataPort |= ~(1<<LCD_EN);
    lcdCommand(0x33);
    LCD_DataPort &= ~(1<<LCD_EN); // zeruje E
    _delay_ms(5);
    }
    LCD_DataPort |= ~(1<<LCD_EN);
    lcdCommand(0x32);
    LCD_DataPort &= ~(1<<LCD_EN); // zeruje E
    _delay_ms(2);
    
    lcdCommand(HD44780_FUNCTION_SET | HD44780_TWO_LINE | HD44780_4_BIT); // interfejs 4-bity, 2-linie, znak 5x7
    lcdCommand(HD44780_FUNCTION_SET | HD44780_TWO_LINE | HD44780_4_BIT); // interfejs 4-bity, 2-linie, znak 5x7
    
    lcdCommand(HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_OFF); // wyłączenie wyswietlacza
    lcdCommand(HD44780_CLEAR); // czyszczenie zawartosći pamieci DDRAM
    _delay_ms(2);
    lcdCommand(HD44780_ENTRY_MODE | HD44780_EM_SHIFT_CURSOR | HD44780_EM_INCREMENT);// inkrementaja adresu i przesuwanie kursora
    lcdCommand(HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_ON | HD44780_CURSOR_OFF | HD44780_CURSOR_NOBLINK); // włącz LCD, bez kursora i mrugania
    }
    
    


    i LCD.h

    
    #define HD44780_CLEAR					0x01
    
    #define HD44780_HOME					0x02
    
    #define HD44780_ENTRY_MODE				0x04
    	#define HD44780_EM_SHIFT_CURSOR		0
    	#define HD44780_EM_SHIFT_DISPLAY	1
    	#define HD44780_EM_DECREMENT		0
    	#define HD44780_EM_INCREMENT		2
    
    #define HD44780_DISPLAY_ONOFF			0x08
    	#define HD44780_DISPLAY_OFF			0
    	#define HD44780_DISPLAY_ON			4
    	#define HD44780_CURSOR_OFF			0
    	#define HD44780_CURSOR_ON			2
    	#define HD44780_CURSOR_NOBLINK		0
    	#define HD44780_CURSOR_BLINK		1
    
    #define HD44780_DISPLAY_CURSOR_SHIFT	16
    	#define HD44780_SHIFT_CURSOR		0
    	#define HD44780_SHIFT_DISPLAY		8
    	#define HD44780_SHIFT_LEFT			0
    	#define HD44780_SHIFT_RIGHT			4
    
    #define HD44780_FUNCTION_SET			32
    	#define HD44780_FONT5x7				0
    	#define HD44780_FONT5x10			4
    	#define HD44780_ONE_LINE			0
    	#define HD44780_TWO_LINE			8
    	#define HD44780_4_BIT				0
    	#define HD44780_8_BIT				16
    
    #define HD44780_CGRAM_SET				64
    
    #define HD44780_DDRAM_SET				128
    ///////////
    
    #define LCD_DataPort PORTD
    #define LCD_DataDR DDRD
    #define LCD_DataPin PIND
    
    #define LCD_RS 2
    #define LCD_EN 3
    #define LCD_LIGHT 1;
    


    To powinno działać.
  • #3 8647378
    csdominik
    Poziom 11  
    Dziękuję za odpowiedz.
    Rzeczywiście nie zamieściłem inicjalizacji LCD.
    A wygląda ona tak : ( zalecam przejście od razu do momentu z wykrzyknikami)
    Cytat:
    void WlaczLCD()
    {
    //ustawienie kierunku wyjściowego linii podłączonych do LCD
    DDR_LCD = (0xF0)|(1<<RS_LCD)|(1<<EN_LCD);
    //stan niski na liniach
    PORT_LCD = 0;

    //zaczekaj co najmniej 45 ms na ustabilizowanie się napięcia
    _delay_ms(45);

    //1
    //ustaw linię EN
    PORT_LCD |= (1<<EN_LCD);
    //załaduj sekwencję 0011
    PORT_LCD |= (1<<DB4_LCD)|(1<<DB5_LCD);

    //potwierdź opadającym zboczem EN
    PORT_LCD &= ~(_BV(EN_LCD));

    //zaczekaj co najmniej 4.1 ms
    _delay_ms(4.1);

    //2
    //ustaw linię EN
    PORT_LCD |= (1<<EN_LCD);
    //potwierdź opadającym zboczem EN sekwencję 0011
    PORT_LCD &= ~(_BV(EN_LCD));

    //zaczekaj co najmniej 100 us
    _delay_us(100);

    //3
    //ustaw linię EN
    PORT_LCD |= (1<<EN_LCD);
    //potwierdź opadającym zboczem EN sekwencję 0011
    PORT_LCD &= ~(_BV(EN_LCD));

    //zaczekaj co najmniej 100 us
    _delay_us(100);

    //4
    //ustaw linię EN
    PORT_LCD |= (1<<EN_LCD);
    //ustawienie interfejsu 4-bitowego
    PORT_LCD &= ~(_BV(DB4_LCD));

    //potwierdź opadającym zboczem EN
    PORT_LCD &= ~(_BV(EN_LCD));

    //ustaw parametry wyświetlacza
    //bit 4 = 0 (słowo danych ma 4 bity)
    //bit 3 = 1 (2 wiersze znaków) // <<---------------------------------------------------------------------- !!
    //bit 2 = 0 (matryca 5x8 pikseli)
    PORT_LCD &= ~(_BV(RS_LCD));
    Wyslij_do_LCD(0b00101000);
    PORT_LCD |= _BV(RS_LCD);

    //ustaw tryb pracy wyświetlacza
    //bit 2 = 1 (inkrementowanie adresu zapisu danych)
    //bit 1 = 1 (wyłączenie przesuwania w prawo)
    PORT_LCD &= ~(_BV(RS_LCD));
    Wyslij_do_LCD(0b00000110);
    PORT_LCD |= _BV(RS_LCD);

    //włącz wyświetlacz
    //bit 2 = 1 (włączenie wyświetlania)
    //bit 1 = 1 (kursor aktywny)
    //bit 0 = 0 (kursor nie miga)
    PORT_LCD &= ~(_BV(RS_LCD));
    Wyslij_do_LCD(0b00001110);
    PORT_LCD |= _BV(RS_LCD);

    CzyscLCD();
    }

    Jak widać ustawiam w słowie konfiguracyjnym bit 3 = 1 (2 wiersze znaków).
    Oczywiście wypróbuje też kod kolegi.
REKLAMA