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

Jak zdefiniować i sterować LCD przez 4-bitową szynę w C?

majster256 21 Lip 2005 23:05 9810 53
Najlepsze odpowiedzi

Jak w C podłączyć i obsługiwać wyświetlacz LCD przez 4-bitową szynę, definiując piny sterujące oraz ustawiając kursor w wybranym wierszu i kolumnie?

Najprościej napisać własne procedury inicjalizacji i zapisu, bo w C nie ma gotowego odpowiednika Bascoma; w 4-bitowym trybie trzeba podłączyć DB4–DB7 do starszej połówki portu, a linie RS i E zdefiniować osobno przez `#define` i ustawić jako wyjścia [#1675441][#1674249] Przykładowy układ makr wygląda tak: `#define LCD PORTB`, `#define E 3`, `#define RS 2`, a dla bardziej dowolnego podłączenia można zdefiniować osobne `DDR_DBx`, `PORT_DBx`, `DBx` i sterować każdą linią niezależnie [#1674269][#1675441] Inicjalizacja polega na wysłaniu sekwencji startowej dla 4 bitów, potem komend typu `0x28` (4 bity, 2 linie), `0x08`, `0x01`, `0x06`, `0x0C` [#1675441] Kursor ustawia się komendą `0x80 | adres`, a w prostym helperze `LCDxy(x, y)` adres liczy się jako `0x80 | (x | (y << 6))` dla 2-liniowego LCD [#1674249][#3521494] Jeśli tekst ma się nie nadpisywać, nie wywołuj `LCDinit()` w pętli; inicjalizację wykonaj raz, a zmienne przed `LCDtext()` konwertuj na napis, np. przez `itoa()` [#1735923][#1736598]
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
  • #1 1671882
    majster256
    Poziom 21  
    Posty: 582
    Ocena: 8
    witam
    jak sie definiuje LCD pod C?? chce nim sterowac przez 4 bitowa szyne (tak jak to mozna bylo w bascomie):D jak to zrobic zeby sobie ustawic kursor w odpowiednim wierszu i kolumnie i pisac :D
    pomozcie mi prosze!!
    Pozdrawia serdecznie
  • #2 1672055
    Dexter77
    Poziom 28  
    Posty: 889
    Pomógł: 134
    Ocena: 19
    Trzeba napisac sobie procedury ktore to zrobia. C to nie Bascom, trzeba sie wykazac odrobina wiedzy i wyobrazni. Na forum bylo kilkakrotnie odnosnie procedur obslugi wyswietlacza w C. Poszukaj.
    Pozdro
    Dexter
  • #6 1674203
    majster256
    Poziom 21  
    Posty: 582
    Ocena: 8
    Pituś Bajtuś napisał:


    i teraz pod to

    // konfiguracja portów we/wy
    DDRB = 0xFF;
    DDRD = 0xFC;
    PORTB = 0xFF;
    PORTD = 0xF7;

    ustawiam pokolei

    piny D4 D5 D6 D7??
    a RS i EN to gdzie sie definiuje???
    i jeszcze jedno pytanko :D
    jak ustawic kursor w okreslonej pozycji XY???

    pozdrawiam serdecznie

    Dodano po 7 [minuty]:

    Tdv napisał:
    1. to może nieco szczegółów, jaki masz kompilator?


    tak mam AVR GCC i wlasnei studiuje caly ten program i on jest tez na 4 bity??? gdzie sie ustawia piny???

    pozdrawiam
  • #7 1674249
    Tdv
    Poziom 34  
    Posty: 2237
    Pomógł: 150
    Ocena: 53
    
    
    
    /*
    * Funkcje obslugi wyswietlaczy LCD. Funkcje proste dostepne wszystkie,
    * dostep do funkcji zlozonych po zadeklarowniau odpowiednich stalych
    * (patrz plik def.h). LCD podlaczony do uC interfejsem 4 bitowym, do
    * starszej polowki zadeklarowanego portu:
    *     LCD_D7  -  PORTx.7
    *     LCD_D6  -  PORTx.6
    *     LCD_D5  -  PORTx.5
    *     LCD_D4  -  PORTx.4
    * Sygnaly sterujace EN (enable), RS i R/W podlaczenie dowolne (nalezy
    * wlasciwie zadeklarowac porty uC).
    * W przypadku koniecznosci podlaczenie wyswietlacza do mlodszej czesci
    * portu nalezy odpowiednio zmodyfikowac funkcje.
    * Makra rozpoczynajace sie od VFD sluza do ustawiania jasnosci
    * wyswietlaczy tego typu (UWAGA:nie wszystkie wyswietlacze VFD maja
    * sterowanie zgodne z wyswietlaczami LCD).
    * Przy korzystaniu z funkcji wyswietlania liczb 8, 16 i 32 bitowych
    * na wyswietlaczu jest zawsze rezerwowana maksymalna ilosc cyfr, a
    * podawane wpolzedne dotycza pierwszego znaku np. dla in16xy uklad
    * na wyswietlczu (wyswietlane -32000, -120, 16501, -1, 0) będzie:
    * -32000
    *   -120
    *  16501
    *     -1
    *      0
    * Jak widac nieznaczace zera nie sa wyswietlane. Liczby zajmuja:
    *  8 bit  uint8_t  3 znaki LCD;
    * 16 bit  uint16_t 5 znakow LCD;
    * 32 bit  uint32_t 10 znakow LCD;
    * Liczby ze znakiem (signed) zajmuja o jedno pole wiecej niz ich
    * odpowiendiki bez znaku.
    */
    


    ;-D
  • #8 1674257
    frohme
    Poziom 21  
    Posty: 421
    Pomógł: 25
    Ocena: 15
    To co zrobiłeś to ustawienie kierunku, czyli zdefiniowanie co wejście a co wyjście na portach (dwie pierwsze linie) i wystawienie na nich stanów binarnych (dwie kolejne). Jak podepniesz linie danych, RS, R/W to twój wybór i ty będziesz tym sterował. Procedura ustawiania kursora w wierszu/kolumnie też gdzieś tu była omawiana.
  • #9 1674269
    Pituś Bajtuś
    Poziom 28  
    Posty: 934
    Pomógł: 137
    Ocena: 10
    W kodzie do którego podałem link linie sterujęce wyświeltaczem są definiowane tutaj :
    #define LCD  PORTB
    #define E  3
    #define RS  2

    D4-D7 są starszą połówką portu PORTB (wynika to z połączeń na płytce AVT3500)
    E to PORTB.3
    RS to PORTB.2
  • #10 1675235
    majster256
    Poziom 21  
    Posty: 582
    Ocena: 8
    witam no to jestem zmuszony do przerobienia PCB
    ja sie przesiadlem z Bascom AVR na AVRGCC
    w bascom to kazdy pin sie ustalalo z osobna i mozna bylo podlanczac jak sie chcialo;]

    pozdrawiam

    Dodano po 10 [minuty]:

    upsss mam atmega8
    i tak:
    PORTB na 1 PWM 6 i 7 jest kwarc
    PORTC na 6 jest reset 7 niema
    PORTD 0,1,2,3 UART i przerwania

    teraz mam podlaczone doPD6 PD7 PC5 PB5 PB4 PB3

    mozecie mi pomoc??
  • #11 1675441
    Pituś Bajtuś
    Poziom 28  
    Posty: 934
    Pomógł: 137
    Ocena: 10
    Cytat:
    w bascom to kazdy pin się ustalalo z osobna i mozna bylo podlanczac jak się chcialo;]

    Takie rozwiązanie jest trochę bardziej pamięciożerne, niemniej jednak dosyć wygodne. Postaram się coś napisać, może do jutra to zrobie.

    edit:
    Trochę kobylaste definicje wyszły, ale nie miałem czasu tego jakoś ładniej napsiać, ważne ze działa. Sprawdzane na AVT3500 z AT90S2313 oraz na PECELu z ATMEGA16 (sorki za brak komentarzy w niektórych miejscach, ale nie bardzo mam czas):
    
    #include <avr/io.h>
    
    #define DDR_DB4  DDRC
    #define PORT_DB4 PORTC
    #define DB4      PC4
    
    #define DDR_DB5  DDRC
    #define PORT_DB5 PORTC
    #define DB5      PC5
    
    #define DDR_DB6  DDRD
    #define PORT_DB6 PORTD
    #define DB6      PD7
    
    #define DDR_DB7  DDRA
    #define PORT_DB7 PORTA
    #define DB7      PA7
    
    
    #define DDR_RS   DDRC
    #define PORT_RS  PORTC
    #define RS       PC2
    
    #define DDR_E    DDRC
    #define PORT_E   PORTC
    #define E        PC3
    
    #define SET_DB4 PORT_DB4 |= _BV(DB4)
    #define CLR_DB4 PORT_DB4 &= ~_BV(DB4)
    
    #define SET_DB5 PORT_DB5 |= _BV(DB5)
    #define CLR_DB5 PORT_DB5 &= ~_BV(DB5)
    
    #define SET_DB6 PORT_DB6 |= _BV(DB6)
    #define CLR_DB6 PORT_DB6 &= ~_BV(DB6)
    
    #define SET_DB7 PORT_DB7 |= _BV(DB7)
    #define CLR_DB7 PORT_DB7 &= ~_BV(DB7)
    
    #define SET_E PORT_E |= _BV(E)
    #define CLR_E PORT_E &= ~_BV(E)
    
    #define SET_RS PORT_RS |= _BV(RS)
    #define CLR_RS PORT_RS &= ~_BV(RS)
    
    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 = 200; 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
    }
    
    
    void write_to_lcd(char x)
    {
    SET_E;
    if(x & _BV(4)) SET_DB4; else  CLR_DB4;
    if(x & _BV(5)) SET_DB5; else  CLR_DB5;
    if(x & _BV(6)) SET_DB6; else  CLR_DB6;
    if(x & _BV(7)) SET_DB7; else  CLR_DB7;
    CLR_E;
    SET_E;
    if(x & _BV(0)) SET_DB4; else  CLR_DB4;
    if(x & _BV(1)) SET_DB5; else  CLR_DB5;
    if(x & _BV(2)) SET_DB6; else  CLR_DB6;
    if(x & _BV(3)) SET_DB7; else  CLR_DB7;
    CLR_E;
    waitms(1);
    }
    
    void write_command(char x)
    {
    CLR_RS; // niski stan na RS -> zapis instrukcji
    write_to_lcd(x); // zapis do 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)
      }
    }
    
    void lcd_init(void)
    {
    DDR_DB4 |= _BV(DB4);
    DDR_DB5 |= _BV(DB5);
    DDR_DB6 |= _BV(DB6);
    DDR_DB7 |= _BV(DB7);
    
    DDR_E |= _BV(E);
    DDR_RS |= _BV(RS);
    
    waitms(15); // czekaj 15ms na ustabilizowanie się napięcia zasilającego
    CLR_E; // E = 0
    CLR_RS; // RS = 0
    char i; // zmianna licznikowa
    for(i = 0; i < 3; i++) // trzykrotne powtórzenie bloku instrukcji
      {
      SET_E; // E = 1
      SET_DB4;
      SET_DB5;
      CLR_DB6;
      CLR_DB7;
      CLR_E; // E = 0
      waitms(5); // czekaj 5ms
      }
    SET_E; // E = 1
    CLR_DB4;
    SET_DB5;
    CLR_DB6;
    CLR_DB7; //
    CLR_E; // E = 0
    waitms(1); // czekaj 1ms
    write_command(0x28); // interfejs 4-bity, 2-linie, znak 5x7
    write_command(0x08); // wyłącz LCD, kursor i miganie
    write_command(0x01); // czyść LCD
    write_command(0x06); // bez przesuwania w prawo
    write_command(0x0C); // włącz LCD, bez kursora i mrugania
    } 
    
    
    int main(void)
    {
    DDRB= 0xFF;
    // inicjalizacja LCD
    lcd_init();
    // zapisz na LCD przykładowy tekst
    write_text("Pitus Bajtus");
    // petla nieskończona
    while(1);
    return 0;
    }
  • #12 1676668
    Elektrooonik
    Poziom 29  
    Posty: 1212
    Pomógł: 127
    Ocena: 83
    Wgrałem ten kod do swojego AVRka po skompilowaniu i pięknie śmiga:) wielkie dzieki Pituś Bajtuś, własnie szukałem podobnego rozwiazania :)
  • #13 1676909
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    No w mordę , a mnie wyszło tak:
    
    #define PGMTXT
    #include <avr/io.h>
    #include <avr/delay.h>
    
    
    //Tu należy zdefiniować piny , używane do sterowania wyśw. LCD 
    //Sygnał R/W podpięty na stałe do GND
    #define RSPIN PC2  //numer bitu dla linii RS
    #define EPIN  PC3
    #define D4PIN PC4
    #define D5PIN PC5
    #define D6PIN PD7
    #define D7PIN PA7
    
    #define RSPORT PORTC  //port do którego podłączono linię RS 
    #define EPORT  PORTC
    #define D4PORT PORTC
    #define D5PORT PORTC
    #define D6PORT PORTD
    #define D7PORT PORTA
    
    #define RSDDR DDRC  //port konfiguracyjny linii RS
    #define EDDR DDRC
    #define D4DDR DDRC
    #define D5DDR DDRC
    #define D6DDR DDRD
    #define D7DDR DDRA
    //koniec definicji pinów LCD
    
    
    //jeśli używamy danych umieszczonych w pamięci programu
    //#define PGMTXT
    //Takie sobie uproszczenia ;)
    #define SET_D4 D4PORT|=(1<<D4PIN)
    #define SET_D5 D5PORT|=(1<<D5PIN)
    #define SET_D6 D6PORT|=(1<<D6PIN)
    #define SET_D7 D7PORT|=(1<<D7PIN)
    
    #define CLR_D4 D4PORT&=~(1<<D4PIN)
    #define CLR_D5 D5PORT&=~(1<<D5PIN)
    #define CLR_D6 D6PORT&=~(1<<D6PIN)
    #define CLR_D7 D7PORT&=~(1<<D7PIN)
    
    #define SET_E EPORT|=(1<<EPIN)
    #define CLR_E EPORT&=~(1<<EPIN)
    #define SET_RS RSPORT|=(1<<RSPIN)
    #define CLR_RS RSPORT&=~(1<<RSPIN)
    #define CLRDISP 0x01
    #define HOMEDISP 0x02
    //koniec uproszczeń
    
    void LCDresetdata(void) //wyzeruj szynę danych LCD
    {
    	CLR_D4;
    	CLR_D5;
    	CLR_D6;
    	CLR_D7;
    }
    void LCDwrite(char d) //zapis bajtu do LCD
    {
    	LCDresetdata();
    	if(d & 0x10){SET_D4;} 
    	if(d & 0x20){SET_D5;} 
    	if(d & 0x40){SET_D6;} 
    	if(d & 0x80){SET_D7;} 
    	SET_E;CLR_E;
    	LCDresetdata();
    	if(d & 0x01){SET_D4;} 
    	if(d & 0x02){SET_D5;} 
    	if(d & 0x04){SET_D6;} 
    	if(d & 0x08){SET_D7;} 
    	SET_E;CLR_E;
    	_delay_ms(2);
    }
    void LCDconfigIO(void) //wszystkie piny do których podłączony jest LCD jako wyjście
    {
    	RSDDR|=(1<<RSPIN);EDDR|=(1<<EPIN);D4DDR|=(1<<D4PIN);
    	D5DDR|=(1<<D5PIN);D6DDR|=(1<<D6PIN);D7DDR|=(1<<D7PIN);
    }
    void LCDcmd(char d) //Wyślij komendę do LCD
    {
    	CLR_RS;
    	LCDwrite(d);
    }
    void LCDchr(char d) //Wyślij 1 znak do LCD
    {
    	SET_RS;
    	LCDwrite(d);
    }
    void LCDinit(void) //inicjalizacja LCD
    {
    	LCDconfigIO();
    	CLR_RS;
    	CLR_E;
    	_delay_ms(20);
    	CLR_D7;
    	CLR_D6;
    	SET_D4;
    	SET_D5;
    	unsigned char i;
    	for(i=0;i<3;i++) {SET_E;CLR_E;_delay_ms(5);}
    	CLR_D4;
    	SET_E;
    	CLR_E;
    	_delay_ms(5);
    	LCDcmd(0x28); //function set - interface=4 bit,line=2,font=5x7 
    	LCDcmd(0x0c); //display ctrl - display on
    	LCDcmd(0x06); //entry mode set - increment
    	LCDcmd(0x01); //clear display
    
    }
    //wyczyść wyśw.
    void LCDcls(void) {LCDcmd(CLRDISP);}
    //ustaw kursor na pozycji 0,0
    void LCDhome(void) {LCDcmd(HOMEDISP);}
    //wyślij tekst z RAM na wyśw.
    void LCDtext(char *txt) {while(*txt) {LCDchr(*txt++);}}
    //umieść kursor na pozycji x,y - brak kontroli dla x i y
    void LCDxy(char x,char y)
    {
    	unsigned char com=0x80;
    	com|=(x|(y<<6));
    	LCDcmd(com);
    }
    #ifdef PGMTXT
    //wyświetlamy tekst zdefiniowany w pamięci programu
    #include <avr/pgmspace.h>
    void LCDtextP(const char *txtp)
    {
    char chr;
    while ((chr = pgm_read_byte(txtp++))) {LCDchr(chr);}
    }
    #endif
    
    
    
    // program główny
    char fromflash[] PROGMEM ="Text from flash";
    int main(void)
    {
    LCDinit();
    LCDxy(3,0);
    LCDtext("Piotrek");  //tradycyjnie
    LCDxy(0,1);
    LCDtextP(fromflash); //z pamięci programu
    while(1){}
    return 0;
    }
    
    


    Ktoś tu komuś chyba w karty zaglądał ;)

    Piotrek

    PS
    Też nas PECELU sprawdzone ;)
  • #14 1677874
    Pituś Bajtuś
    Poziom 28  
    Posty: 934
    Pomógł: 137
    Ocena: 10
    Troszkę oszczędniejsza wersja mojego programu (ok 30 bajtów mniej):
    #define F_CPU 4000000
    
    #include <avr/io.h>
    #include <avr/delay.h>
    
    #define DDR_DB4  DDRB
    #define PORT_DB4 PORTB
    #define DB4      PB4
    
    #define DDR_DB5  DDRB
    #define PORT_DB5 PORTB
    #define DB5      PB5
    
    #define DDR_DB6  DDRB
    #define PORT_DB6 PORTB
    #define DB6      PB6
    
    #define DDR_DB7  DDRB
    #define PORT_DB7 PORTB
    #define DB7      PB7
    
    
    #define DDR_RS   DDRB
    #define PORT_RS  PORTB
    #define RS       PB2
    
    #define DDR_E    DDRB
    #define PORT_E   PORTB
    #define E        PB3
    
    #define SET_DB4 PORT_DB4 |= _BV(DB4)
    #define CLR_DB4 PORT_DB4 &= ~_BV(DB4)
    
    #define SET_DB5 PORT_DB5 |= _BV(DB5)
    #define CLR_DB5 PORT_DB5 &= ~_BV(DB5)
    
    #define SET_DB6 PORT_DB6 |= _BV(DB6)
    #define CLR_DB6 PORT_DB6 &= ~_BV(DB6)
    
    #define SET_DB7 PORT_DB7 |= _BV(DB7)
    #define CLR_DB7 PORT_DB7 &= ~_BV(DB7)
    
    #define SET_E PORT_E |= _BV(E)
    #define CLR_E PORT_E &= ~_BV(E)
    
    #define SET_RS PORT_RS |= _BV(RS)
    #define CLR_RS PORT_RS &= ~_BV(RS)
    
    // funkcja wystawiająca na szynę danych połówkę bajtu
    // pod uwagę brana jest młodsza połówka parametru
    void out_nibble(char x)
    {
    if(x & _BV(0)) SET_DB4; else  CLR_DB4;
    if(x & _BV(1)) SET_DB5; else  CLR_DB5;
    if(x & _BV(2)) SET_DB6; else  CLR_DB6;
    if(x & _BV(3)) SET_DB7; else  CLR_DB7;
    }
    
    // funkcja zapisująca do LCD bajt danych
    void write_to_lcd(char x)
    {
    SET_E;
    out_nibble(x >> 4); // wystawienie na szynę danych starszej połówki bajtu
    CLR_E; // opadające zbocze na E powoduje zapis do wyświetlacza
    SET_E;
    out_nibble(x); // wystawienie na szynę danych młodszej połówki bajtu
    CLR_E; // opadające zbocze na E powoduje zapis do wyświetlacza
    _delay_ms(1); // opóźnienie ok 1 ms
    }
    
    // funkcja zapisująca do LCD rozkaz
    void write_command(char x)
    {
    CLR_RS; // niski stan na RS -> zapis instrukcji
    write_to_lcd(x); // zapis do LCD
    }
    
    // funkcja zapisujaca do LCD znak
    void write_char(char x)
    {
    SET_RS; // wysoki stan na RS -> zapis danej
    write_to_lcd(x); // zapis do LCD
    }
    
    // funkcja 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)
      }
    }
    
    // funkcja inicjująca LCD
    void lcd_init(void)
    {
    // ustawienie wszystkich linii sterujących LCD jako wyjścia
    DDR_DB4 |= _BV(DB4);
    DDR_DB5 |= _BV(DB5);
    DDR_DB6 |= _BV(DB6);
    DDR_DB7 |= _BV(DB7);
    DDR_E |= _BV(E);
    DDR_RS |= _BV(RS);
    //
    _delay_ms(15); // czekaj 15ms na ustabilizowanie się napięcia zasilającego
    CLR_E; // E = 0
    CLR_RS; // RS = 0
    char i; // zmianna licznikowa
    for(i = 0; i < 3; i++) // trzykrotne powtórzenie bloku instrukcji
      {
      SET_E; // E = 1
      out_nibble(0x03);
      CLR_E; // E = 0
      _delay_ms(5); // czekaj 5ms
      }
    SET_E; // E = 1
    out_nibble(0x02);
    CLR_E; // E = 0
    _delay_ms(1); // czekaj 1ms
    write_command(0x28); // interfejs 4-bity, 2-linie, znak 5x7
    write_command(0x08); // wyłącz LCD, kursor i miganie
    write_command(0x01); // czyść LCD
    write_command(0x06); // bez przesuwania w prawo
    write_command(0x0C); // włącz LCD, bez kursora i mrugania
    } 
    
    
    int main(void)
    {
    // inicjalizacja LCD
    lcd_init();
    // zapisz na LCD przykładowy tekst
    write_text("Pitus Bajtus");
    // petla nieskończona
    while(1);
    return 0;
    }
  • #15 1677986
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    To zaoszczędźmy w Twoim programie ,jeszcze kilkanaście:
    
    void out_nibble(char x)
    {
    CLR_DB4;
    CLR_DB5;
    CLR_DB6;
    CLR_DB7;
    if(x & _BV(0)) SET_DB4;
    if(x & _BV(1)) SET_DB5;
    if(x & _BV(2)) SET_DB6;
    if(x & _BV(3)) SET_DB7;
    }
    


    Piotrek
  • #16 1692737
    elektryk
    Poziom 42  
    Posty: 11029
    Pomógł: 439
    Ocena: 241
    zumek napisał:
    To zaoszczędźmy w Twoim programie ,jeszcze kilkanaście:
    void out_nibble(char x)
    {
    CLR_DB4;
    CLR_DB5;
    CLR_DB6;
    CLR_DB7;
    if(x & _BV(0)) SET_DB4;
    if(x & _BV(1)) SET_DB5;
    if(x & _BV(2)) SET_DB6;
    if(x & _BV(3)) SET_DB7;
    }
    Nawet nie chce wiedzieć kto was uczył pisać programy ;)
    PORTD=(PORTD && 0x0F)||((x && 0x0F)<<4) jeśli się nie zgadza składnia to prosze poprawić. Oczywiście wyrażenie można odpowiednio zoptymalizować ale to jest wersja ogólna.
  • #17 1693064
    Pituś Bajtuś
    Poziom 28  
    Posty: 934
    Pomógł: 137
    Ocena: 10
    Kolego Elektryk, z całym szacunkiem ale wydaje mi się że nie wiesz o co biega w naszych programach. Sęk w tym że LCD nie jest podłączony do kolejnych linii jakiegoś portu, tylko do dowolnych linii róznych portów Pełna swoboda wyboru, a kod który podałeś jest dla LCD podłączonego do jednej połówki konkretnego portu! Tak jak w Bascomie jest możliwość dowolnego przypisania linii streujacych LCD do dowolnych portów mikrokontrolera!
    Program ten napsiałem w odpowiedzi na takie stwierdzenie :
    Cytat:
    w bascom to kazdy pin się ustalalo z osobna i mozna bylo podlanczac jak się chcialo;]
  • #18 1693091
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    elektryk napisał:

    Nawet nie chce wiedzieć kto was uczył pisać programy ;)
    PORTD=(PORTD && 0x0F)||((x && 0x0F)<<4) jeśli się nie zgadza składnia to prosze poprawić. Oczywiście wyrażenie można odpowiednio zoptymalizować ale to jest wersja ogólna.


    Hmmm.... ja dopiero uczę się programować w C ale ... chyba nie zrozumiałeś co robi zacytowana przez Ciebie procedurka.A co do podanego przez Ciebie przykladu , to masz rację składnia się nie zgadza ,bo do PORTD chcesz wpisać wartość logiczna TRUE (1) lub FALSE (0) zależnie od wartości PORTD i zmiennej x . Jednak zawsze warto posłuchac co mówia inni , a w szczególności jak człowiek sie uczy :D

    Pozdrawiam
    Piotrek

    PS
    Ja bym napisał:PORTC=((PORTC & 0x0F) | ((x & 0x0F)<<4)) ;)
  • #19 1693110
    Pituś Bajtuś
    Poziom 28  
    Posty: 934
    Pomógł: 137
    Ocena: 10
    Zumek ma rację && jest operatorem logicznym natomiast & bitowym. Chcąd dokonać operacji logicznej na zbiorze bitów stosujemy operatory & i | Natomiast && i || stosujemy do operacji na wartościach wyrażeń logicznych typu if((a==10)&&(b==12))

    PS człowiek uczy się do śmierci i głupi umiera.
  • #20 1710410
    daniel93
    Poziom 29  
    Posty: 1673
    Pomógł: 30
    Ocena: 94
    Może ktośpodać przykładowy kod do lcd na avt3500 ?
    Tak żeby sprawdzić lcd .
  • #21 1710616
    Elektrooonik
    Poziom 29  
    Posty: 1212
    Pomógł: 127
    Ocena: 83
    daniel93 napisał:
    Może ktośpodać przykładowy kod do lcd na avt3500 ?
    Tak żeby sprawdzić lcd .

    Kilka postów wcześniej Pituś Bajtuś podał przecież działający kod w C.

    A w bascomie mozna tak sprawdzic LCD ;) :

    
    Cls
    Lcd "Wyswietlacz zepsuty" 
    


    ;)
  • #22 1710669
    Pituś Bajtuś
    Poziom 28  
    Posty: 934
    Pomógł: 137
    Ocena: 10
    Kilka postów wyżej, post o dacie wysłania : 24 Lip 2005 14:03 zawiera kod dla AVT3500. Wystarczy go tylko skompilować w WinAVR i wgrać do procka.
  • #23 1712884
    daniel93
    Poziom 29  
    Posty: 1673
    Pomógł: 30
    Ocena: 94
    Miałem zwarte dwie nużki i chyba uwaliłem wyświetlacz !!! :cry::cry::cry:
    I to 2*16 !!! :cry::cry::cry:
  • #24 1732251
    MA24M
    Poziom 12  
    Posty: 22
    Ocena: 3
    myslalem ze tylko w bascomie mozna prosto, jestem zdziwjony,a tu pelna kontrola ,myslalem ze obsluga lcd od podstaw to jakas skomplikowana sprawa ,zegnaj bascom.jeszcze pytanko nie na temat; czemu nigdy nie spotkalem w sieci mp3 playerow w bascom czy taki kiepski kod ma ???? sorry za tak glupie pytanie ale nieznam odpowiedzi.
  • #25 1732826
    majster256
    Poziom 21  
    Posty: 582
    Ocena: 8
    MA24M napisał:
    czemu nigdy nie spotkalem w sieci mp3 playerow w bascom czy taki kiepski kod ma ????


    moge sie tylko domyslac :D ale mp3 player to skomplikowana zabawka a bascom sie do tego nie nadaje ja robilem sterownik bramy w bascom i przy programie ok 2000 linii to program byl bardziej niestabilny niz win 98 :cry: tzn chodzil ladnie a nagle jakeis krzaki na wyswietlaczu (nawet jak ja nic nie robilem) krzaki znikaly i znowu chodzil ladnie az sie zrestartowal i wszystko zaczynalo sie od nowa. nei bylo zadnych regol na te bledy, probowalem tez zmienic procke ale i to nic nie pomoglo :cry: dowiadywalem sie dlaczego sie tak dzieje i dostalem proste odpowiedzi: "bascom jest do prostych probramikow"

    dlatego zminiam na C
  • #26 1733653
    morph13
    Poziom 25  
    Posty: 987
    Pomógł: 25
    Ocena: 32
    majster256 napisał:
    robilem sterownik bramy w bascom i przy programie ok 2000 linii to program byl bardziej niestabilny ......... tzn chodzil ladnie a nagle jakeis krzaki na wyswietlaczu (nawet jak ja nic nie robilem) krzaki znikaly i znowu chodzil ladnie az się zrestartowal i wszystko zaczynalo się od nowa

    Przyczyna - na 99,9% niekontrolowane przepełnienie stosu.
  • #27 1733840
    majster256
    Poziom 21  
    Posty: 582
    Ocena: 8
    morph13 napisał:

    Przyczyna - na 99,9% niekontrolowane przepełnienie stosu.


    to znaczy???

    Dodano po 1 [godziny] 59 [minuty]:

    zumek napisał:

    
    #define PGMTXT
    #include <avr/io.h>
    #include <avr/delay.h>
    
    
    //Tu należy zdefiniować piny , używane do sterowania wyśw. LCD 
    //Sygnał R/W podpięty na stałe do GND
    #define RSPIN PC2  //numer bitu dla linii RS
    #define EPIN  PC3
    #define D4PIN PC4
    #define D5PIN PC5
    #define D6PIN PD7
    #define D7PIN PA7
    
    #define RSPORT PORTC  //port do którego podłączono linię RS 
    #define EPORT  PORTC
    #define D4PORT PORTC
    #define D5PORT PORTC
    #define D6PORT PORTD
    #define D7PORT PORTA
    
    #define RSDDR DDRC  //port konfiguracyjny linii RS
    #define EDDR DDRC
    #define D4DDR DDRC
    #define D5DDR DDRC
    #define D6DDR DDRD
    #define D7DDR DDRA
    //koniec definicji pinów LCD
    
    
    //jeśli używamy danych umieszczonych w pamięci programu
    //#define PGMTXT
    //Takie sobie uproszczenia ;)
    #define SET_D4 D4PORT|=(1<<D4PIN)
    #define SET_D5 D5PORT|=(1<<D5PIN)
    #define SET_D6 D6PORT|=(1<<D6PIN)
    #define SET_D7 D7PORT|=(1<<D7PIN)
    
    #define CLR_D4 D4PORT&=~(1<<D4PIN)
    #define CLR_D5 D5PORT&=~(1<<D5PIN)
    #define CLR_D6 D6PORT&=~(1<<D6PIN)
    #define CLR_D7 D7PORT&=~(1<<D7PIN)
    
    #define SET_E EPORT|=(1<<EPIN)
    #define CLR_E EPORT&=~(1<<EPIN)
    #define SET_RS RSPORT|=(1<<RSPIN)
    #define CLR_RS RSPORT&=~(1<<RSPIN)
    #define CLRDISP 0x01
    #define HOMEDISP 0x02
    //koniec uproszczeń
    
    void LCDresetdata(void) //wyzeruj szynę danych LCD
    {
    	CLR_D4;
    	CLR_D5;
    	CLR_D6;
    	CLR_D7;
    }
    void LCDwrite(char d) //zapis bajtu do LCD
    {
    	LCDresetdata();
    	if(d & 0x10){SET_D4;} 
    	if(d & 0x20){SET_D5;} 
    	if(d & 0x40){SET_D6;} 
    	if(d & 0x80){SET_D7;} 
    	SET_E;CLR_E;
    	LCDresetdata();
    	if(d & 0x01){SET_D4;} 
    	if(d & 0x02){SET_D5;} 
    	if(d & 0x04){SET_D6;} 
    	if(d & 0x08){SET_D7;} 
    	SET_E;CLR_E;
    	_delay_ms(2);
    }
    void LCDconfigIO(void) //wszystkie piny do których podłączony jest LCD jako wyjście
    {
    	RSDDR|=(1<<RSPIN);EDDR|=(1<<EPIN);D4DDR|=(1<<D4PIN);
    	D5DDR|=(1<<D5PIN);D6DDR|=(1<<D6PIN);D7DDR|=(1<<D7PIN);
    }
    void LCDcmd(char d) //Wyślij komendę do LCD
    {
    	CLR_RS;
    	LCDwrite(d);
    }
    void LCDchr(char d) //Wyślij 1 znak do LCD
    {
    	SET_RS;
    	LCDwrite(d);
    }
    void LCDinit(void) //inicjalizacja LCD
    {
    	LCDconfigIO();
    	CLR_RS;
    	CLR_E;
    	_delay_ms(20);
    	CLR_D7;
    	CLR_D6;
    	SET_D4;
    	SET_D5;
    	unsigned char i;
    	for(i=0;i<3;i++) {SET_E;CLR_E;_delay_ms(5);}
    	CLR_D4;
    	SET_E;
    	CLR_E;
    	_delay_ms(5);
    	LCDcmd(0x28); //function set - interface=4 bit,line=2,font=5x7 
    	LCDcmd(0x0c); //display ctrl - display on
    	LCDcmd(0x06); //entry mode set - increment
    	LCDcmd(0x01); //clear display
    
    }
    //wyczyść wyśw.
    void LCDcls(void) {LCDcmd(CLRDISP);}
    //ustaw kursor na pozycji 0,0
    void LCDhome(void) {LCDcmd(HOMEDISP);}
    //wyślij tekst z RAM na wyśw.
    void LCDtext(char *txt) {while(*txt) {LCDchr(*txt++);}}
    //umieść kursor na pozycji x,y - brak kontroli dla x i y
    void LCDxy(char x,char y)
    {
    	unsigned char com=0x80;
    	com|=(x|(y<<6));
    	LCDcmd(com);
    }
    #ifdef PGMTXT
    //wyświetlamy tekst zdefiniowany w pamięci programu
    #include <avr/pgmspace.h>
    void LCDtextP(const char *txtp)
    {
    char chr;
    while ((chr = pgm_read_byte(txtp++))) {LCDchr(chr);}
    }
    #endif
    
    
    
    // program główny
    char fromflash[] PROGMEM ="Text from flash";
    int main(void)
    {
    LCDinit();
    LCDxy(3,0);
    LCDtext("Piotrek");  //tradycyjnie
    LCDxy(0,1);
    LCDtextP(fromflash); //z pamięci programu
    while(1){}
    return 0;
    }
    
    





    a jak zrobie
    
    LCDinit();
    LCDxy(0,5);
    LCDtext(majster256);
    

    w petli to mi zawsze kasuje zawartosc LCD i pisze od nowa
    a jak zrobic zeby tekstu ktory jest tkai sma nei zmienial??? w bascom tak wlasnie bylo :D
  • #28 1734344
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    majster256 napisał:

    to znaczy???

    Dołączyłem Ci 2 przykłady , byś sie przekonał , że identyczny program napisany w Bascomowym Basicu , raz działa a innym razem nie.
    Są 2 katalogi "Test1" i "Test2" , które należy rozpakować , załadować kod do Bascoma i skompilować. Następnie uruchomić symulator i ... obserwować jak "procek" głupieje czyli robi to czego nie powinien był zrobić.Jeśli to samo postąpisz z programem z katalogu "Test2" to symulacje będzie przebiegała tak jak powinna i procek bezbłędnie wykona to co mu kazaliśmy :D
    Ciekawe dla czego :?:

    majster256 napisał:


    
    LCDinit();
    LCDxy(0,5);
    LCDtext(majster256);
    

    w petli to mi zawsze kasuje zawartosc LCD i pisze od nowa
    a jak zrobic zeby tekstu ktory jest tkai sma nei zmienial??? w bascom tak wlasnie bylo :D


    Bo "C" jest do bani , a "Bascom" jest cacy ... żartowałem :wink:

    W kółko inicjujesz LCD.
    
    LCDinit();  //raz wystarczy ;)
    
    while(1) {
    LCDxy(0,5);
    LCDtext(majster256);
    }
    


    Pozdrawiam
    Piotrek
    Załączniki:
    • Przyklady.zip (1.77 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #29 1734508
    majster256
    Poziom 21  
    Posty: 582
    Ocena: 8
    juz probowalem przed pentelka;] i na poczatku wyswietlacza wysweitla mi koncowke tekstu ktory chce tam gdzies dalej;/ np teraz mam
    ter25majster256

    no nie ciekawie;/
  • #30 1734569
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    majster256 napisał:
    juz probowalem przed pentelka;] i na poczatku wyswietlacza wysweitla mi koncowke tekstu ktory chce tam gdzies dalej;/ np teraz mam
    ter25majster256

    no nie ciekawie;/

    U mnie działo się podobnie.
    Oznacza to , że funkcja _delay_ms jest "za szybka" .Sprawdź #define F_CPU w pliku delay.h czy jest "zakomentowane" i czy zadeklarowana w projekcie F_CPU jest zgodna ze stanem faktycznym :wink:


    Piotrek

Podsumowanie tematu

✨ Dyskusja dotyczy programowania wyświetlaczy LCD sterowanych przez 4-bitową szynę w języku C, w szczególności na mikrokontrolerach AVR z użyciem kompilatora AVR GCC. Poruszono kwestie definiowania pinów danych (D4-D7) oraz linii sterujących RS i EN, które można dowolnie przypisać do portów mikrokontrolera, co różni się od podejścia w Bascomie, gdzie piny definiuje się indywidualnie. Podano przykładowe fragmenty kodu i makra do obsługi 4-bitowego interfejsu LCD, wraz z konfiguracją portów i funkcjami do ustawiania kursora w określonej pozycji (funkcja LCDxy lub locate). Omówiono także problem opóźnień i synchronizacji sygnałów, które mają wpływ na poprawne wyświetlanie tekstu, oraz konieczność inicjalizacji LCD tylko raz, a nie w pętli. Wskazano na potrzebę konwersji zmiennych liczbowych na łańcuchy znaków (np. funkcją itoa) przed wyświetleniem na LCD. Poruszono również zagadnienia związane z różnicami między Bascomem a C, stabilnością programów oraz optymalizacją kodu. Wątek obejmuje także przykłady kodów dla różnych konfiguracji pinów i mikrokontrolerów, w tym ATmega8, ATmega16, AT90S2313, ATmega8515 oraz platformę AVT3500. W końcowej części pojawiły się pytania o obsługę LCD na platformie ARM oraz problemy z kompilacją i działaniem kodu, a także sugestie dotyczące testowania działania wyświetlacza poprzez wyświetlenie prostego tekstu lub obserwację podświetlenia i kontrastu.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA