LCD w C

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
Awatar użytkownika
Aro
Użytkownik
Posty: 677
Rejestracja: 30 paź 2006, 18:49
Lokalizacja: Świerczyniec | Wrocław
Kontakt:

LCD w C

Post autor: Aro » 28 sty 2007, 20:10

Jest jakaś biblioteka w C do obsługi alfanumerycznego wyświetlacza LCD? Jak zrobic taką bibliotekę, czy plik, żeby wpis tekstu czy zmiennej na LCD sprowadzał się do jednego polecenia w głównym pliku źródłowym?


Awatar użytkownika
Aro
Użytkownik
Posty: 677
Rejestracja: 30 paź 2006, 18:49
Lokalizacja: Świerczyniec | Wrocław
Kontakt:

Post autor: Aro » 29 sty 2007, 14:26

Troche tego jest. Wszystko sie dobrze kompiluje i ładuje do procka, no ale jak to bywa z czymś nowym oczywiście nie działa :evil:. Pozmieniałem plik .h do moich potrzeb, no ale widocznie coś przegapiłem. Jak to poustawiac, bo te oznaczenia w pliku.h dotyczące lini
danych były troche dziwne. Ja mam wyświetlacz 1*16zn. podłączony do potru c tak: Rs-Pc.5, Ena-Pc.4, D4-Pc.3, D5-Pc.2, D6-Pc.1, D7-Pc.0

ZbeeGin

Post autor: ZbeeGin » 29 sty 2007, 19:22

Tak zrobiłeś? (frament z pliku nagłówkowego lcd.h):

Kod: Zaznacz cały

#define LCD_IO_MODE      1         /**< 0: memory mapped mode, 1: IO port mode */
#if LCD_IO_MODE
/**
 *  @name Definitions for 4-bit IO mode
 *  Change LCD_PORT if you want to use a different port for the LCD pins.
 *
 *  The four LCD data lines and the three control lines RS, RW, E can be on the 
 *  same port or on different ports. 
 *  Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on
 *  different ports. 
 *
 *  Normally the four data lines should be mapped to bit 0..3 on one port, but it
 *  is possible to connect these data lines in different order or even on different
 *  ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions.
 *  
 */
#define LCD_PORT         PORTC        /**< port for the LCD lines   */
#define LCD_DATA0_PORT   LCD_PORT     /**< port for 4bit data bit 0 */
#define LCD_DATA1_PORT   LCD_PORT     /**< port for 4bit data bit 1 */
#define LCD_DATA2_PORT   LCD_PORT     /**< port for 4bit data bit 2 */
#define LCD_DATA3_PORT   LCD_PORT     /**< port for 4bit data bit 3 */
#define LCD_DATA0_PIN    3            /**< pin for 4bit data bit 0  */
#define LCD_DATA1_PIN    2            /**< pin for 4bit data bit 1  */
#define LCD_DATA2_PIN    1            /**< pin for 4bit data bit 2  */
#define LCD_DATA3_PIN    0            /**< pin for 4bit data bit 3  */
#define LCD_RS_PORT      LCD_PORT     /**< port for RS line         */
#define LCD_RS_PIN       5            /**< pin  for RS line         */
#define LCD_RW_PORT      LCD_PORT     /**< port for RW line         */
#define LCD_RW_PIN       6            /**< pin  for RW line         */
#define LCD_E_PORT       LCD_PORT     /**< port for Enable line     */
#define LCD_E_PIN        4            /**< pin  for Enable line     */

#elif defined(__AVR_AT90S4414__) || defined(__AVR_AT90S8515__) || defined(__AVR_ATmega64__) || \
      defined(__AVR_ATmega8515__)|| defined(__AVR_ATmega103__) || defined(__AVR_ATmega128__) || \
      defined(__AVR_ATmega161__) || defined(__AVR_ATmega162__)
/*
 *  memory mapped mode is only supported when the device has an external data memory interface
 */
#define LCD_IO_DATA      0xC000    /* A15=E=1, A14=RS=1                 */
#define LCD_IO_FUNCTION  0x8000    /* A15=E=1, A14=RS=0                 */
#define LCD_IO_READ      0x0100    /* A8 =R/W=1 (R/W: 1=Read, 0=Write   */
#else
#error "external data memory interface not available for this device, use 4-bit IO port mode"

#endif
Nie używaną linię RW dałem na PC6.

Awatar użytkownika
Aro
Użytkownik
Posty: 677
Rejestracja: 30 paź 2006, 18:49
Lokalizacja: Świerczyniec | Wrocław
Kontakt:

Post autor: Aro » 29 sty 2007, 20:55

dokładnie tak miałem. Nie jestem do końca pewny czy to wszystkie zmiany jakie trzeba wprowadzic. Zmieniałem jeszcze typ wyświetlacza na 1 linia 16 znaków(to jest kilka linijek wyżej od ustawień wyprowadzeń).

Kod: Zaznacz cały

#define LCD_LINES           1     /**< number of visible lines of the display */
#define LCD_DISP_LENGTH    16     /**< visibles characters per line of the display */
#define LCD_LINE_LENGTH  0x40     /**< internal line length of the display    */
#define LCD_START_LINE1  0x00     /**< DDRAM address of first char of line 1 */
#define LCD_START_LINE2  0x40     /**< DDRAM address of first char of line 2 */
#define LCD_START_LINE3  0x14     /**< DDRAM address of first char of line 3 */
#define LCD_START_LINE4  0x54     /**< DDRAM address of first char of line 4 */
#define LCD_WRAP_LINES      0     /**< 0: no wrap, 1: wrap at end of visibile line */

xtal=4000000 ustawiany troche wyżej to chyba nie powód niedziałania bo mam kwarc 1MHz

ZbeeGin

Post autor: ZbeeGin » 29 sty 2007, 22:26

Myślę, że trzeba zmienić jeszcze dane w części:

Kod: Zaznacz cały

#define LCD_LINES           2     /**< number of visible lines of the display */ <-- tutaj
#define LCD_DISP_LENGTH     8     /**< visibles characters per line of the display */  <--tutaj
#define LCD_LINE_LENGTH  0x40     /**< internal line length of the display    */
#define LCD_START_LINE1  0x00     /**< DDRAM address of first char of line 1 */
#define LCD_START_LINE2  0x40     /**< DDRAM address of first char of line 2 */
#define LCD_START_LINE3  0x14     /**< DDRAM address of first char of line 3 */
#define LCD_START_LINE4  0x54     /**< DDRAM address of first char of line 4 */
#define LCD_WRAP_LINES      1     /**< 0: no wrap, 1: wrap at end of visibile line */  <-- i tutaj
Bo wyświetlacze 1x16 mają to do siebie, że w większości wewnętrznie są to dwie linie po 8 znaków, tylko połączone tak, by widać było jedną linię 16 znakową. Patrz: http://home.wanadoo.nl/electro1/avr/sof ... AYYBJP.pdf (str. 10)
Ostatnio zmieniony 01 sty 1970, 1:00 przez ZbeeGin, łącznie zmieniany 1 raz.

Awatar użytkownika
Aro
Użytkownik
Posty: 677
Rejestracja: 30 paź 2006, 18:49
Lokalizacja: Świerczyniec | Wrocław
Kontakt:

Post autor: Aro » 30 sty 2007, 17:22

Nic :sad: . Raz tylko po zresttowaniu zapaliła się pierwsza kratka co chyba powinno oznaczac inicjację wyświetlacza jak się nie mylę. Próbowałem wszystkich możliwości, podłanczałem też pod wyświetlacz 2*16(odpowiednio zmodyfikowany .h) i też nic.
Mam jeszcze takie pytanie - czy to może byc powód kompilacji na starej wersji AVR-GCC? Ja mam 20050214.

ZbeeGin

Post autor: ZbeeGin » 30 sty 2007, 18:20

Jeszcze jedno. Linię RW wyświetlacza łączysz z masą? Jeśli tak to podłącz do portu zgodnie z definicją. Choć nie przyglądałem się dokładnie, ale może biblioteka próbować coś odczytać z LCD.

[ Dodano: 2007-01-30, 19:01 ]
-------------

Moje boje z tym programem także zakończyły się niepowodzeniem. Zmieniłem definicję pod LCD 2*16, ATTiny2313 w płytce AVT3500. Kompilacja w środowisku WinAVR 20060421 przechodzi bez problemów, po wgraniu do procesora... także echo.

P.S. Jak widać nie jesteśmy sami: http://www.elektroda.pl/rtvforum/viewto ... 274ed70e55
Ostatnio zmieniony 30 sty 2007, 23:43 przez ZbeeGin, łącznie zmieniany 1 raz.

Awatar użytkownika
Aro
Użytkownik
Posty: 677
Rejestracja: 30 paź 2006, 18:49
Lokalizacja: Świerczyniec | Wrocław
Kontakt:

Post autor: Aro » 30 sty 2007, 21:03

Też tam zaglądałem, i nic z tego mi nie wyszło. Lini r/w nie podłączę bo musiałbym zmieniac potrt na b. PortC ma tylko 6 nóżek :cry: Koppel sobie z tym poradził, tylko nie wiem jak bo nie mam tych numerów EDW. Sprzęt jest na bank dobry po z bascoma działał.

Awatar użytkownika
gaweł
Użytkownik
Posty: 651
Rejestracja: 05 kwie 2004, 8:38
Lokalizacja: Białystok
Kontakt:

Post autor: gaweł » 30 sty 2007, 21:32

Aro pisze:(...)Koppel sobie z tym poradził, tylko nie wiem jak bo (...)
Sądzę, że też możesz poradzić sobie sam. Potrzebujesz tylko drobnej informacji. Jeżeli używasz linii R/W, to możesz wczytywać status z LCD i wiedzieć, kiedy kończy on wykonywanie poprzednich poleceń. Jeżeli nie masz możliwości odczytu, jak po podaniu na R/W na stałe "0", to musisz odczekać określony czas wynikający z realizacji zadanego polecenia. Być może wyjaśnią ci się te kwestie po lekturze:
https://elportal.pl/index.php?module=Co ... y&ceid=319
co prawda nie jest to w C, ale liczy się algorytm działania.

ZbeeGin

Post autor: ZbeeGin » 30 sty 2007, 21:39

Widzisz Gaweł, ta biblioteka którą obaj z Aro próbowaliśmy odpalć - z marnym skutkiem - posiada odpowiednie opóźnienia wplecone w procedury:

Kod: Zaznacz cały

    /*
     * Initialize LCD to 8 bit memory mapped mode
     */
    
    /* enable external SRAM (memory mapped lcd) and one wait state */        
    MCUCR = _BV(SRE) | _BV(SRW);

    /* reset LCD */
    delay(16000);                           /* wait 16ms after power-on     */
    lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit interface */                   
    delay(4992);                            /* wait 5ms                     */
    lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit interface */                 
    delay(64);                              /* wait 64us                    */
    lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit interface */                
    delay(64);                              /* wait 64us                    */
Nigdzie nie doszukałem się procedur odczytujących status LCD podczas wykonywania operacji zapisu - ale przy takim skompilikowaniu kodu (dużo robi preprocesor) mogłem je przeoczyć gdzieś w #define lub w warunkowej kompilacji...

Awatar użytkownika
gaweł
Użytkownik
Posty: 651
Rejestracja: 05 kwie 2004, 8:38
Lokalizacja: Białystok
Kontakt:

Post autor: gaweł » 30 sty 2007, 21:49

Wiesz ZbeeGin, co prawda, to przejrzałem jej implementację dość pobieżnie ale odniosłem wrażenie, że właśnie taki ma algorytm. Skoro poświęciłeś tematowi więcej czasu, to zapewne masz większą wiedzę na temat jej implementacji i nie wykluczone, że masz rację.

ZbeeGin

Post autor: ZbeeGin » 30 sty 2007, 23:29

Z ostatniej chwili. Udało mi się uruchomić tą bibliotekę i testowy program na płytce AVT3500. Ale działa nieco niestabilnie - przekłamuje znaki, definicje CGRAM są błędne. Myślę, że to sprawa opóźnień (Mój Tiny2313 pracuje z wewnętrznym RC@4MHz).

Zmiany jakie wprowadziłem:
1. Definicje

Kod: Zaznacz cały

#define LCD_PORT         PORTB        /**< port for the LCD lines   */
#define LCD_DATA0_PORT   LCD_PORT     /**< port for 4bit data bit 0 */
#define LCD_DATA1_PORT   LCD_PORT     /**< port for 4bit data bit 1 */
#define LCD_DATA2_PORT   LCD_PORT     /**< port for 4bit data bit 2 */
#define LCD_DATA3_PORT   LCD_PORT     /**< port for 4bit data bit 3 */
#define LCD_DATA0_PIN    4            /**< pin for 4bit data bit 0  */
#define LCD_DATA1_PIN    5            /**< pin for 4bit data bit 1  */
#define LCD_DATA2_PIN    6            /**< pin for 4bit data bit 2  */
#define LCD_DATA3_PIN    7            /**< pin for 4bit data bit 3  */
#define LCD_RS_PORT      LCD_PORT     /**< port for RS line         */
#define LCD_RS_PIN       2            /**< pin  for RS line         */
#define LCD_RW_PORT      LCD_PORT     /**< port for RW line         */
#define LCD_RW_PIN       0            /**< pin  for RW line         */
#define LCD_E_PORT       LCD_PORT     /**< port for Enable line     */
#define LCD_E_PIN        3            /**< pin  for Enable line     */
Jest to: D4 = PB.4, D5=PD.5, D6 = PD.6, D7 = PD.7, Rs = PB.2, E = PB.3, RW do masy (choć definicja jest na PB.0 nie używam RW).

W kwestii informacyjnej:

Kod: Zaznacz cały

#define LCD_LINES           2     /**< number of visible lines of the display */
#define LCD_DISP_LENGTH    16     /**< visibles characters per line of the display */
Czyli jak widać standardowy LCD 16x2.

2. Żródło "LCD.C"

Kod: Zaznacz cały

/*************************************************************************
loops while lcd is busy, returns address counter
*************************************************************************/
static uint8_t lcd_waitbusy(void)

{
//    register uint8_t c;
    
    /* wait until busy flag is cleared */
//    while ( (c=lcd_read(0)) & (1<<LCD_BUSY)) {}
    
    /* the address counter is updated 4us after the busy flag is cleared */
//	delay(2);
	delay(64);

    /* now read the address counter */
//    return (lcd_read(0));  // return address counter
	return (0);
}/* lcd_waitbusy */
Czyli stałe opóźnienie bez odczytywania BUSY_FLAG z rejestrów LCD. Ujemny skutek: nie można odczytać bieżącego adresu pozycji kursora. Ta jedyna procedura jak się okazuje odczytuje coś z LCD, i jest wykorzystywana w bibliotece. Zatem tu kol. Gaweł miał rację.

3. Program główny "TEST_LCD.C"
Zmiana treści procedury wait_until_key_pressed() by reagowała na stan PD0. Tutaj jest µ-switch S1 na płyce AVT. Ale ta zmiana nie ma odbicia w samej bibliotece.

Awatar użytkownika
Aro
Użytkownik
Posty: 677
Rejestracja: 30 paź 2006, 18:49
Lokalizacja: Świerczyniec | Wrocław
Kontakt:

Post autor: Aro » 31 sty 2007, 17:58

No i jak to w C ...działa :grin: :grin: :grin: Dziękuję wszystkim , a szczególnie Tobie ZbeeGin
Pozdro :wink:

Awatar użytkownika
Koppel
Użytkownik
Posty: 500
Rejestracja: 24 lip 2005, 18:05
Lokalizacja: Gliwice

Post autor: Koppel » 01 lut 2007, 9:07

Aro pisze:Koppel sobie z tym poradził, tylko nie wiem jak bo nie mam tych numerów EDW.
Wszystkie kody są na stronie www.elportal.pl/n0017. Jeśli czegoś tam brakuje, proszę o wiadomość na maila (zwykle odpowiadam szybciej niż na PW). Kody są opatrzone bogatymi komentarzami, więc nie powinno być problemu aby zrozumieć ich działania.

Widzę, że sprawę już zamknąłeś z innym programem. Chciałem jednak tylko przypomnieć jak z mojej strony wygląda sprawa :)

// Edit: usunąłem kropkę z linka do strony która utrudniała jej otwarcie.
Ostatnio zmieniony 02 lut 2007, 17:54 przez Koppel, łącznie zmieniany 1 raz.

ODPOWIEDZ