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

Problem z porgramem obsługującym LCD

przemo_re 03 Sie 2009 15:02 4091 35
  • #1 6852162
    przemo_re
    Poziom 12  
    Witam!!
    Problem jest taki,że gdy w gram program to nic się nie dzieję. Na wyświetlaczu palą się budki na górnej linii. Program jest następujący

    //////////////////////////////////////////////////////////////////////////////////////////////////
    // alfanumerycznego LCD
    // 
    //          Kompilator: WinAVR
    
    //////////////////////////////////////////////////////////////////////////////////////////////////
    #include <avr\io.h>
    #include <inttypes.h>
    
    // Makra upraszczające dostęp do portów
    // *** Port
    #define PORT(x) XPORT(x)
    #define XPORT(x) (PORT##x)
    // *** Pin
    #define PIN(x) XPIN(x)
    #define XPIN(x) (PIN##x)
    // *** DDR
    #define DDR(x) XDDR(x)
    #define XDDR(x) (DDR##x)
    
    // Definicje wyprowadzeń
    #define LCD_RS 29
    #define LCD_RSPORT C
    #define LCD_E 28
    #define LCD_EPORT C
    // Port danych: zakładam, że wyprowadzenia są połączone kolejno. 
    // Definiowane jest jedynie przesunięcie oznaczające na którym wyprowadzeniu jest D4
    #define LCD_DPORT A
    #define LCD_D4 36 
    #define LCD_D5 35
    #define LCD_D6 34
    #define LCD_D7 33
    // Komendy sterujące wyświetlaczem
    #define LCDC_CLS		0x01
    #define LCDC_HOME		0x02
    #define LCDC_MODE		0x04
    	#define LCDC_MODER		0x02
    	#define LCDC_MODEL		0
    	#define LCDC_MODEMOVE	0x01
    #define LCDC_ON 		0x08
    	#define LCDC_ONDISPLAY	0x04
    	#define LCDC_ONCURSOR	0x02
    	#define LCDC_ONBLINK	0x01
    #define LCDC_SHIFT		0x10
    	#define LCDC_SHIFTDISP	0x08
    	#define LCDC_SHIFTR		0x04
    	#define LCDC_SHIFTL		0
    #define LCDC_FUNC		0x20
    	#define LCDC_FUNC8b		0x10
    	#define LCDC_FUNC4b		0
    	#define LCDC_FUNC2L		0x08
    	#define LCDC_FUNC1L		0
    	#define LCDC_FUNC5x10	0x4
    	#define LCDC_FUNC5x7	0
    #define LCDC_CGA		0x40
    #define LCDC_DDA		0x80
    
    //--------------------------------------------------
    // Generowanie opóźnień
    #define delay250ns() {asm volatile("nop"::);}
    
    #define delayus8(t)\
    	{asm volatile( \
    		"delayus8_loop%=: \n\t"\
    			"nop \n\t"\
    			"dec %[ticks] \n\t"\
    			"brne delayus8_loop%= \n\t"\
    	: :[ticks]"r"(t) );}
    	// DEC - 1 cykl, BRNE 2 cykle, + 1xnop. Zegar 4MHz
    
    void delay100us8(uint8_t t)
    {
    	while(t>0)
    	{
    		delayus8(100); 
    		--t; 
    	}
    }
    // Koniec opóźnień
    //--------------------------------------------------
    
    //--------------------------------------------------
    // Obsługa wyświetlacza
    // Funkcje niskiego poziomu
    #define LCD_EPULSE() \
    	{PORT(LCD_EPORT) |= 1<<LCD_E; \
    	delay250ns(); \
    	PORT(LCD_EPORT) &= ~(1<<LCD_E);}
    
    void LCDsendHalf(uint8_t data)
    {
    	data = (data & 0x0F) << LCD_D4; 
    	//data |= 0xF0;
    	//data &= 0x0F;
    	//data <<= LCD_D4; 
    	PORT(LCD_DPORT) = 
    		(PORT(LCD_DPORT) & ~(0x0F<<LCD_D4)) | data;
    	//PORT(LCD_DPORT) &= ~(0x0F<<LCD_D4); 
    	//PORT(LCD_DPORT) |= data; 
    	LCD_EPULSE();
    }
    
    void LCDsend(uint8_t data)
    {
    	// Starsza część
    	LCDsendHalf(data>>4);
    	// Młodsza część
    	LCDsendHalf(data);
    	delayus8(120);
    }
    
    // Funkcje interfejsu
    void LCDcommand(uint8_t command)
    {
    	PORT(LCD_RSPORT) &= ~(1<<LCD_RS);
    	LCDsend(command);
    }
    
    void LCDdata(uint8_t data)
    {
    	PORT(LCD_RSPORT) |= 1<<LCD_RS;
    	LCDsend(data);
    }
    
    void LCDcls(void)
    {
    	LCDcommand(LCDC_CLS);
    	delay100us8(48);
    }
    
    void LCDhome(void)
    {
    	LCDcommand(LCDC_HOME);
    	delay100us8(48);
    }
    
    void LCDinit(void)
    {
    	delay100us8(150);
    	PORT(LCD_RSPORT) &= ~(1<<LCD_RS);
    	LCDsendHalf(LCDC_FUNC|LCDC_FUNC8b); 
    	delay100us8(41);
    	LCDsendHalf(LCDC_FUNC|LCDC_FUNC8b);
    	delay100us8(2);
    	LCDsendHalf(LCDC_FUNC|LCDC_FUNC4b);
    	delay100us8(2);
    	// Teraz jest już 4b. Koniec korzystania z sendHalf
    	LCDcommand(LCDC_FUNC|LCDC_FUNC4b|LCDC_FUNC2L|LCDC_FUNC5x7);
    	LCDcommand(LCDC_ON);
    	LCDcls();
    	LCDcommand(LCDC_MODE|LCDC_MODER);
    	LCDcommand(LCDC_ON|LCDC_ONDISPLAY|LCDC_ONCURSOR);
    }
    
    // Koniec obsługi wyświetlacza
    //--------------------------------------------------
    
    // START
    int main(void)
    {
    	//----------------------------------------------
    	// Inicjacja - uwaga: uproszczona, może wymagać 
    	// zmian przy zmianie przyporządkowania portów
    	DDR(LCD_DPORT) = 1<<LCD_E | 1<<LCD_RS | 
    		0x0F<<LCD_D4;
    	
    	LCDinit();
    	// Koniec inicjacji
    	//----------------------------------------------
    	
    	// \/ Bez tego, czasami zerowanie z poziomu programatora
    	// \/ powoduje śmieci na wyświetlaczu. 
    	LCDcls(); 
    	
    	LCDdata('H');
    	LCDdata('E');
    	LCDdata('L');
    	LCDdata('L');
    	LCDdata('O');
    	LCDdata(' ');
    	LCDdata(':');
    	LCDdata('-');
    	LCDdata(')');
    
    

    Program skonfigurowałem względem mojego schematu,ktróry jest w załączniku. Proszę o pomoc czy to jest wszystko dobrze czy jednak jest zły soft.


    Proszę umieszczać listingi programów w znacznikach "Code". [c_p]
  • #2 6852173
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Po kolei:

    1. w_gram - bez spacji
    2. kod umieszcza się w znacznikach [ code ]
    3. sprawdź w słowniku jaka jest różnica między inicjalizacją a inicjacją
    4. Ze schematu wynika, że twój układ nie ma prawa działać, bo nie podłączyłeś wszystkich pinów zasilania i nie dałeś na każdy pin zasilania filtrującego kondensatora
    5. Schemat jest skrajnie nieczytelny

    4\/3!!
  • #3 6852182
    przemo_re
    Poziom 12  
    Gdzie mam podłączyć to zasilanie?
    Program który mrugał jedną diodą działał dlatego myślałem,że schemat jest ok.
  • #5 6852201
    przemo_re
    Poziom 12  
    Czy te piny muszą być podłączone pytam ,ponieważ mój promotor nic o tych pinach nie mówił? A co z tym softem czy to się do czego nadaje?
  • #7 6852224
    Freddie Chopin
    Specjalista - Mikrokontrolery
    przemo_re napisał:
    Czy te piny muszą być podłączone pytam ,ponieważ mój promotor nic o tych pinach nie mówił? A co z tym softem czy to się do czego nadaje?

    Więc może przeczytasz w końcu tego datasheeta i opis pinów? Będziesz mógł wtedy zdecydować kto ma racje - promotor czy firma Atmel.

    4\/3!!
  • #8 6852225
    przemo_re
    Poziom 12  
    Definiowanie portów i pinów zaczerpnąłem z kursu programowanie avr w języku C z EdW
  • #10 6852236
    m.bartczak
    Poziom 16  
    Z tego co widzę jest to kontroler HD44780, a do tego kontrolera jest sobie dawno napisany komplet przykładów użycia:

    http://radzio.dxp.pl/hd44780/

    Zajrzyj tam - znajdziesz zarówno przykłady na 4 bitowy jak i 8 bitowy interfejs, zarówno z użyciem flag zajętości jak i bez.
  • #11 6852247
    przemo_re
    Poziom 12  
    Ma to być interface klawiatury PCAT w systemie mikroprocesorowym, a uczelni to nie podam, ponieważ to nie jest takie ważne.

    Dodano po 4 [minuty]:

    Panie m.bartczak znam tą stronę. Jednak mam problem jak skonfigurować soft aby działał na moim projekcie. Narazie chcę zająć się LCD a później obsługą klawiatury.

    Dodano po 34 [minuty]:

    Panowie jesteście tam proszę o pomoc i szybką odpowiedź
  • #12 6852427
    m.bartczak
    Poziom 16  
    Z tego co widzę w Pańskim kodzie to nie ma żadnej komunikacji z wyświetlaczem.

    Ta definicja portów z Pańskiego kodu nie ma prawa zadziałać. Ze schematu wynika, że LCD jest podłączony do portu A i C.

    Definicja ustawień dla kodu ze strony Radosława (należy zmodyfikować tę sekcję w pliku HD44780.h) powinna wyglądać następująco:

    
    #define LCD_RS_DIR		DDRC
    #define LCD_RS_PORT 	PORTC
    #define LCD_RS_PIN		PINC
    #define LCD_RS			(1 << PC7)
    
    #define LCD_RW_DIR		DDRC
    #define LCD_RW_PORT	PORTC
    #define LCD_RW_PIN		PINC
    #define LCD_RW		(1 << PC5)
    
    #define LCD_E_DIR		DDRC
    #define LCD_E_PORT		PORTC
    #define LCD_E_PIN		PINC
    #define LCD_E			(1 << PC6)
    
    #define LCD_DB4_DIR	DDRA
    #define LCD_DB4_PORT	PORTA
    #define LCD_DB4_PIN	PINA
    #define LCD_DB4		(1 << PA4)
    
    #define LCD_DB5_DIR	DDRA
    #define LCD_DB5_PORT	PORTA
    #define LCD_DB5_PIN	PINA
    #define LCD_DB5		(1 << PA5)
    
    #define LCD_DB6_DIR	DDRA
    #define LCD_DB6_PORT	PORTA
    #define LCD_DB6_PIN	PINA
    #define LCD_DB6		(1 << PA6)
    
    #define LCD_DB7_DIR	DDRA
    #define LCD_DB7_PORT	PORTA
    #define LCD_DB7_PIN	PINA
    #define LCD_DB7		(1 << PA7)
    


    Proszę zauważyć że w komunikacji z AtMegą używamy nazw pinów a nie numerów nóżek scalaka.
  • #13 6852765
    przemo_re
    Poziom 12  
    Co mam zrobić z tymi plikami HD44780.c i HD44780.h czemu jest to podzielone na dwa pliki. Jak załaduje je do AVR studio to nie działa kompilacja co ja źle robię?
  • #16 6853348
    m.bartczak
    Poziom 16  
    Zapomniałeś ".h" - kompilator wyraźnie mówi że nie ma pliku o nazwie HD44780. Jest za to HD44780.h.

    PS: Zajrzyj w mój kompletny przykład w topicu:

    [Atmega16][C] Menu - obsługa przycisków

    PS2: Ten wątek zmierza w stronę nauki podstaw programowania, co nie jest raczej tematem na forum elektrody.
  • #17 6865647
    tz_tomek
    Poziom 12  
    Witam.

    Powyższe operacje wykonałem dla wyświetlacza 16x1. Jest OK, ale dlaczego chcąc wyświetlić 16 znaków muszę użyć do tego trzech linii?

    
    LCD_WriteText("abcdefgh");
    LCD_GoTo(0,1);
    LCD_WriteText("ijklmnop");
    


    Z opisów na forum i na wskazanej stronie wnioskuję, że na wyświetlaczu 16x2 nie ma takiego problemu.

    Pozdrawiam.
  • #19 6867131
    morph13
    Poziom 25  
    tz_tomek napisał:
    ...Powyższe operacje wykonałem dla wyświetlacza 16x1. Jest OK, ale dlaczego chcąc wyświetlić 16 znaków muszę użyć do tego trzech linii?
    
    LCD_WriteText("abcdefgh");
    LCD_GoTo(0,1);
    LCD_WriteText("ijklmnop");
    

    Z opisów na forum i na wskazanej stronie wnioskuję, że na wyświetlaczu 16x2 nie ma takiego problemu....

    Dlatego, że są wyświetlacze 1x16 w których jedna linia to 2x8.
    I wracając do wypowiedzi (namowy do zgłębiania wiedzy) Freddie Chopin, wypadało by kolego tz_tomek jednak przejrzeć notę katalogową kontrolera.
  • #20 6867232
    tz_tomek
    Poziom 12  
    Ok. Spokojnie Panowie. Już sobie poradziłem. Być może nie w elegancki sposób, ale działa.

    
    void LCD_WriteData(unsigned char dataToWrite)
    {
    	if(kolumna<8)
    		{
    		kolumna++;
    		}
    	else
    		{
    		LCD_GoTo(kolumna-8,1);
    		kolumna++;
    		}
    LCD_RS_PORT |= LCD_RS;
    _LCD_Write(dataToWrite);
    }
    


    Dzięki i pozdrawiam.
  • #21 6903203
    przemo_re
    Poziom 12  
    Mam kod w którym ustawiłem wszystkie porty tak jak na schemacie podłączyłem również piny 30 do VCC i 31 do masy i dalej nie ma komunikacjiz LCD co jest jeszcze nie tak proszę o pomoc.
     //Program w tym przykładzie realizuje obsługę alfanumerycznego
    //wyświetlacza LCD w trybie 4-bitowym:
    
    #include <avr/io.h>
    //
    //linie danych PA4-7
    #define LCD1    PORTA
    //linie sterujące PC 5, 6, 7
    #define LCD2	PORTC
    #define E  6
    #define RS  7
    #define RW  5
    
    //
    #define SET_DDRA0   DDRA |= _BV(0)
    #define SET_DDRA1   DDRA |= _BV(1)
    #define SET_DDRA2   DDRA |= _BV(2)
    #define SET_DDRA3   DDRA |= _BV(3)
    #define SET_DDRA4   DDRA |= _BV(4)
    #define SET_DDRA5   DDRA |= _BV(5)
    #define SET_DDRA6   DDRA |= _BV(6)
    #define SET_DDRA7   DDRA |= _BV(7)
    
    #define SET_DDRC0   DDRC |= _BV(0)
    #define SET_DDRC1   DDRC |= _BV(1)
    #define SET_DDRC2   DDRC |= _BV(2)
    #define SET_DDRC3   DDRC |= _BV(3)
    #define SET_DDRC4   DDRC |= _BV(4)
    #define SET_DDRC5   DDRC |= _BV(5)
    #define SET_DDRC6   DDRC |= _BV(6)
    #define SET_DDRC7   DDRC |= _BV(7)
    
    #define SET_E   LCD2 |= _BV(E)
    #define CLR_E   LCD2 &= ~_BV(E)
    //
    #define SET_RS  LCD2 |= _BV(RS)
    #define CLR_RS  LCD2 &= ~_BV(RS)
    
    #define SET_RW  LCD2 |= _BV(RW)
    #define CLR_RW  LCD2 &= ~_BV(RW)
    
    // funkcja opóźniająca o x*1ms
    void waitms(char x)
    {
    unsigned char a, b; // zmnienne licznikowe
    for( ; x > 0; --x) // ta pętla zostanie wykonana x-razy
      for(b = 10; b > 0; --b) // a ta 10 razy
           for(a = 100; a > 0; --a) // natomiast ta 100 razy
            __asm("nop"); // dodatkowa instrukcja opóźniająca o 1 cykl
      // razem to da opóźnienie ok. x * 1ms
           // x od 0 do 255
    }
    
    // pcodedura zapisu bajtu do wyświetlacza LCD
    // bez rozróżnienia instrukcja/dana
    void write_to_lcd(char x)
    {
    __asm("nop"); 
    SET_E; // ustaw na E stan wysoki
    __asm("nop"); 
    LCD1 = ((LCD1 & 0x0F) | (x & 0xF0)); // zapis pierwszej połówki bajtu
    __asm("nop"); 
    CLR_E; // opadające zbocze na E -> zapis do wyświetlacza
    __asm("nop"); 
    SET_E; // ustaw na E stan wysoki
    __asm("nop"); 
    LCD1 = ((LCD1 & 0x0F) | ((x & 0x0F) << 4)); // zapis drugiej połowki bajtu
    __asm("nop"); 
    CLR_E; // opadające zbocze na E -> zapis do wyświetlacza
    waitms(1); // czekaj 1ms
    }
    
    // procedura zapisu instrukcji do wyświetlacza LCD
    void write_command(char x)
    {
    CLR_RS; // niski stan na RS -> zapis instrukcji
    write_to_lcd(x); // zapis do LCD
    }
    
    // procedura zapisu danej do wyświetlacza LCD
    void write_char(char x)
    {
    SET_RS; // wysoki stan na RS -> zapis danej
    write_to_lcd(x); // zapis do LCD
    }
    
    // procedura zapisu tekstu do wyświetlacza LCD
    void write_text(char * s)
    {
    while(*s) // do napotkania 0
      {
      write_char(*s); // zapisz znak wskazywany przez s na LCD
      s++; // zwiększ s (przygotuj nastepny znak)
      }
    }
    
    // procedura inicjalizacji wyświetlacza LCD
    void lcd_init(void)
    {
    waitms(15); // czekaj 15ms na ustabilizowanie się napięcia zasilającego
    
    CLR_E; // E = 0
    CLR_RS; // RS = 0
    CLR_RW; // RW = 0
    
    char i; // zmianna licznikowa
    //jestesmy jeszcze w trybie 8-bitowym
    for(i = 0; i < 3; i++) // trzykrotne powtórzenie bloku instrukcji
      {
      SET_E; // E = 1
    __asm("nop"); 
    //rozkaz 0x38 8-bitowy interfejs , 2 linie na lcd
      LCD1 = 0x38; //lub
    //LCD1 |= _BV(4)
    //LCD1 |= _BV(5)
    //LCD1 &= ~_BV(6)
    //LCD1 &= ~_BV(7)
    
    __asm("nop"); 
      CLR_E; // E = 0
      waitms(5); // czekaj 5ms
      }
    
    //teraz przechodzimy w tryb 4-bitowy
    SET_E; // E = 1
    __asm("nop"); 
    LCD1 = 0x28; //lub
    //LCD1 &= ~_BV(4)
    //LCD1 |= _BV(5)
    //LCD1 &= ~_BV(6)
    //LCD1 &= ~_BV(7)
    
    __asm("nop"); 
    CLR_E; // E = 0
    waitms(5); // czekaj 5ms
    
    
    write_command(0x28); // interfejs 4-bity, 2 linie
    waitms(5); // czekaj 5ms
    
    write_command(0x0C); // włącz LCD
    write_command(0x14); // przesuw w prawo
    write_command(0x06); // przesuw kursora
    
    write_command(0x01); // czyść LCD
    waitms(5); 
    write_command(0x80); // górna linia lewy skraj
    
    }
    
    // program główny
    int main(void)
    {
    // konfiguracja portów we/wy
    DDRA = 0xFF;
    DDRC = 0xFF;
    PORTA = 0xFF;
    PORTC = 0xFF;
    
    // inicjalizacja LCD
    lcd_init();
    // zapisz na LCD przykładowy tekst
    do
    {
    //write_text("Ala ma kota :D");
    // górna linia 
    write_command(0x80); 
    write_to_lcd("A");
    // dolna linia 
    write_command(0xC0); 
    write_to_lcd("B");
    
    // petla nieskończona
    }
    while(1);
    return 0;
    }
    
    
  • #22 6923352
    przemo_re
    Poziom 12  
    Z wyświetlaczem juz sobie poradziłem teraz muszę dołączyć program, który będzie obsługiwał klawiaturę PC i wyświetlał znaki na LCD. Czy macie jakieś pomysły lub gotowe projekty? Proszę o pomoc!!!
  • #24 6927264
    przemo_re
    Poziom 12  
    Tak ale kod żródłowy jest w asemblerze a ja mam w języku C, ten drugi kod to już mam ale tam są wysyłane znaki przez UART do komputera. Problem polega na tym, że nie mam pojęcia jak zrealizować ten kod aby działał z LCD. Panowie proszę dalej o pomoc.
  • #25 6943768
    korrus666
    Poziom 40  
    Masz w pierwszym linku od m.bartczak opisaną komunikację z klawiaturą PC. Wystarczy to zaimplementować w programie. Sprawa jest banalnie prosta bo dane przesyłane są w prosty sposób szeregowo. Możesz do tego wykorzystać przerwania zewnętrzne lub jak sądzę bez problemów interface SPI.
  • #26 6950181
    przemo_re
    Poziom 12  
    Znalazłem link z kodem do obsługi klawiatury [url=http://radzio.dxp.pl/pckeyboard/].
    Teraz mam pytanie jak wyświetlić znak z klawiatury na LCD ,za pomocą jakiej funkcji?
  • #28 6952039
    przemo_re
    Poziom 12  
    Freddie ale mi pomogłeś dzięki jesteś super. A tak na poważnie gdybym umiał programować to bym tego tematu nie zakładał. Dlatego też szukam pomocy na forum, a ty mogłeś się lepiej postarać.
  • #30 6962569
    przemo_re
    Poziom 12  
    Ja się nie czepiam tylko mimo że mam te dwa programy to i tak nie wiem jak wyświetlić znak z klawiatury, przeczytałem kurs z EdW i z diody.pl a i tak jestem zielony. Czy znajdzie się osoba , która wreście mi pomoże? Mogę nawet zapłacić!!
REKLAMA