Elektroda.pl
Elektroda.pl
X
Mitronik
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

ATmega128 wew1MHz WINAVR [C] + lcd PG12864 złe wyświetlanie

Sławek-K 20 Lut 2015 19:56 750 5
  • #1 20 Lut 2015 19:56
    Sławek-K
    Poziom 15  

    Witam !
    Tracąc dziesiątki godzin szukania w Internecie i dwa tygodnie prób i błędów z w/w LCD proszę o pomoc (i pokazanie błędu) Dołączam kod w [C] oraz obraz wyświetlany na LCD. Sprzęt jak w tytule , programator Stk500v2. Pierwotnie Atmega była na kwarcu 16 MHz , może za szybko, teraz jest na wewnętrznym generatorze 1 MHz, bez zmian. Później dopisałem kilka opóźnień , bez zmian.
    Założeniem miało być narysowanie kilka linii prostych.
    W celu nie zaśmiecania wątku usunąłem rysowanie na całym ekranie (prawym sterowniku) i ograniczyłem się do lewego półekranu. Proszę o wszelkie sugestie (oprócz google nie parzy i równie pomocne).

    ATmega128 wew1MHz WINAVR [C] + lcd PG12864 złe wyświetlanie

    Kod: c
    Zaloguj się, aby zobaczyć kod

    // --------- sterownik LCD -> chyba NT7108/NT7107 (podobny do KS0108 ) ---------------
    // ATmega 128 + POWERTIP -> LCD PG12864 -> 128x64 punktow
    // F_CPU -> 1 MHz
    #include <math.h>
    #include <avr/io.h>
    #include <util/delay.h>

    #define DDR_Dane DDRA
    #define PORT_Dane PORTA // PORT DANYCH -->> PA 0-7
    #define PIN_Dane PINA

    #define DDR_Sygnaly DDRC // PORT SYGNALOW STERUJACYCH
    #define PORT_Sygnaly PORTC

    #define SET_RESET PORT_Sygnaly |= _BV(2) // RST/ -> PC2 - RESET/
    #define CLR_RESET PORT_Sygnaly &= ~_BV(2)

    #define SET_RW PORT_Sygnaly |= _BV(6) // R/W -> PC6 - READ / WRITE
    #define CLR_RW PORT_Sygnaly &= ~_BV(6)

    #define SET_E PORT_Sygnaly |= _BV(5) // E -> PC5 - ENABLE
    #define CLR_E PORT_Sygnaly &= ~_BV(5)

    #define SET_CS1 PORT_Sygnaly |= _BV(4) // CS1 -> PC4 - CHIP SELECT 1 (seg 0~63)
    #define CLR_CS1 PORT_Sygnaly &= ~_BV(4)

    #define SET_CS2 PORT_Sygnaly |= _BV(3) // CS2 -> PC3 - CHIP SELECT 2 (seg 64~127)
    #define CLR_CS2 PORT_Sygnaly &= ~_BV(3)

    #define SET_DI PORT_Sygnaly |= _BV(7) // D/I -> PC7 DATA/INSTRUCTION
    #define CLR_DI PORT_Sygnaly &= ~_BV(7) // DATA -> H INSTRUCTION -> L


    void write_command_1( unsigned char p) // funkcja -> zapis instrukcji
    {
    CLR_E;
    _delay_us(5);
    CLR_RW;
    CLR_DI; // DI-> niski -> zapis instrukcji
    _delay_us(5);
    SET_E;
    _delay_us(9);
    PORT_Dane=p;
    _delay_us(9);
    CLR_E;
    _delay_us(5);
    SET_RW;
    SET_DI;




    _delay_us(5);
    }


    void write_data_1( unsigned char g) // funkcja -> zapis danych
    {
    CLR_E;
    _delay_us(5);
    CLR_RW;
    SET_DI; // DI-> WYSOKI -> zapis danych
    _delay_us(9);
    PORT_Dane=g;
    _delay_us(9);
    SET_E;
    _delay_us(9);
    CLR_E;
    _delay_us(9);

    }


    unsigned char read_data_1(void) // odczyt danych z LCD
    {
    volatile unsigned char tmp1 ;
    CLR_E;
    _delay_us(9);
    SET_RW; // R/W =1 -> Read
    SET_DI; // DI =1 -> dane
    _delay_us(9);
    SET_E;
    _delay_us(9);
    DDR_Dane = 0x00; // jako wejscia
    _delay_us(9);
    tmp1 = PIN_Dane;
    _delay_us(9);
    CLR_E;
    DDR_Dane = 0xFF;
    _delay_us(9);
    return tmp1;
    }


    void clr_lcd_1(void) // czyszczenie LCD = zapis samych zer
    {
    for (unsigned char aa=0xB8; aa<0xC0; aa++) // 8 razy -> tyle stron na lcd
    {
    write_command_1(aa);
    write_command_1(0x40); // 0x40 set adress Y -> 0b 01xx xxxx
    _delay_us(1);
    for (unsigned char bb=0x40; bb<0x80; bb++) // 64 razy -> tyle kolumn
    {
    write_data_1(0); //przy zapisie danych adres jest automatycznie zwiekszany o 1
    _delay_us(300); // wiec nie potrzeba wysylac zadnych instrukcji
    }
    }
    }


    void set_pixel( uint8_t x, uint8_t y) // zapalanie pixela x1(0,63) y(0,63)
    {
    volatile uint8_t yy, bajt_r, bajt_w;
    yy=y/8; // numer strony LCD
    write_command_1(0xB8|yy); // set page -> 0b10111xxx
    write_command_1(0x40|x); // 0x40 set adress Y -> 0b 01xx xxxx
    bajt_r = read_data_1(); // odczyt bajtu z LCD
    bajt_w = bajt_r | (1<<y%8) ; //przygotowanie bajtu do zapisu
    write_command_1(0xB8|yy); // set page -> 0b10111xxx
    write_command_1(0x40|x); // 0x40 set adress Y -> 0b 01xx xxxx
    write_data_1(bajt_w);
    _delay_us(9);
    }

    int main(void)
    {
    DDRD=0x80; // podlaczona dioda LED
    DDR_Dane = 0xFF; // magistrala danych
    DDR_Sygnaly=0xFF; // sygnaly sterujace
    PORT_Dane=0;
    PORT_Sygnaly=0;
    _delay_us(9);
    SET_RESET;
    SET_CS1;
    write_command_1(63); // 0x01 -> ON LCD_1
    write_command_1(0xC0); // display start line

    while(1)
    {
    PORTD|=_BV(7); // dioda LED -> ON jako wskaznik, ze uP + program pracuje
    clr_lcd_1();
    _delay_ms(500);
    unsigned char zmienna ;
    for (zmienna=1; zmienna<60; zmienna=zmienna+1)
    {
    set_pixel(zmienna,5);
    set_pixel(zmienna,32);
    set_pixel(zmienna,zmienna); // ukosna linia
    set_pixel(zmienna,52); // ukosna linia
    _delay_ms(42);
    }
    _delay_ms(4000);
    PORTD&=~(_BV(7)); // OFF - dioda LED na PD7
    _delay_ms(1000);
    }
    return 0;
    }
    // KONIEC //
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0 5
  • Mitronik
  • Pomocny post
    #2 21 Lut 2015 09:50
    tmf
    Moderator Mikrokontrolery Projektowanie

    Tego typu kontrolery wymagają przy odczycie VRAM tzw. dummy read - po ustawieniu nowego adresu pierwszy odczytany bajt to śmieci, dopiero drugi zawiera użyteczne dane. Tak więc twoja funkcja rysująca piksele jest błędna.

    0
  • Mitronik
  • #3 21 Lut 2015 10:14
    michalko12
    Specjalista - Mikrokontrolery

    W tym przypadku odczyt raczej działa dobrze bo nie odczytuje śmieci. Problem raczej wynika z ustawienia adresu Y i to w zależności od tego jaki jest X.

    Na drugiej połówce LCD jest to samo?

    0
  • #4 21 Lut 2015 10:43
    tmf
    Moderator Mikrokontrolery Projektowanie

    @michalko12 - odczyt w set_pixel jest błędny - należy odczytać jeden bajt, a następnie kolejny i dopiero kolejny zawiera wartość pamięci spod wskazanego adresu - identycznie jest w kontrolerze KS0108. Czyli w tej funkcji odczyt teraz jest o jeden bajt "wstecz", co zresztą wyraźnie widać na screenshocie. Problem jest częściowo maskowany przez fakt, że rysowane są linie poziome i finalnie kolejne bajty zawierają 0xff, w efekcie pomimo odczytu poprzedniego bajtu, linia pozioma jest ok. Podobnie przy linii ukośnej jeśli odczytujemy poprzedni bajt, to ponieważ kolejne są identyczne problemu pozornie nie ma. Dopiero w przypadku krzyżowania linii widać problem.

    0
  • #5 21 Lut 2015 10:49
    michalko12
    Specjalista - Mikrokontrolery

    Jeśli w tym dummy odczycie są dane z poprzedniego odczytu to wszystko zgadzałoby się.

    0
  • #6 21 Lut 2015 16:44
    Sławek-K
    Poziom 15  

    Znów kolega tmf pokazał poziom !
    Z tego co doczytałem mój lcd jest na sterowniku NT7108 (chyba klon KS0108).
    Dopisując jedną linię więcej w set_pixel(), tzn
    bledny= read _data1(); //odczyt zostaje pominięty
    bajt_r=read_data1(); //dopiero jest brany pod uwagę , problem załatwiło ewidentnie. Teraz wszystko rysuje się jak należy .
    Dzięki koledze michalko12 za chęci i "podjęcie tematu", na drugim sterowniku (prawa część LCD) było analogicznie. Dopiszę usunięte funkcje prawej połowy i będzie wtedy już na 100% OK, ale nie przewiduję większych problemów skoro lewa śmiga jak trzeba.
    Dopisałem jeszcze kilka analogicznych linii (w ramach testów). Oto efekt.

    ATmega128 wew1MHz WINAVR [C] + lcd PG12864 złe wyświetlanie

    0