• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Problem z programowaniem mikrokontrolera Atmega1284
#1
Witam! Spotkałem się z dziwnym zachowaniem mikrokontrolera Atmega1284 (lub kompilatora). mianowicie uruchomiłem pewny wyświetlacz LCD (24bit kolor, 160x240) tego typu obrazek zajmuje 115200 bajtów. W ramach testu chciałem zapisać w pamięci mikrokontrolera obrazek i wyświetlić na tym ekranie. Kompilator nie pozwolił mi stworzyć jednej tak dużej tablicy. Zmieściłem w czterech. Efekt -  jak widać zdj, w pewnym momencie grafika się psuje. Zauważyłem że moment kiedy pojawia się problem to dokładnie 65536 (czyli gdy bit 16 adresu pamięci zmienia się na 1).
   
I może ktoś pomyśleć po co mi system wyświetlania jednej grafiki. Oczywiście nie o to chodzi - posiadam parę projektów z tym mikrokontrolerem, a ten który teraz tworze niebezpiecznie zbliża się do tej granicy 65KB. Poza tym czysta ciekawość, nie podoba mi się, że to nie działa tak jak chce Tongue 

Kod: (jest tu tylko część odpowiadająca za wysyłanie faktycznego obrazu bo kod jest długi i ciężko się od razu połapać)
Kod:
  for (byte j = 0; j < 60; j++) // linie od 1 do 60
  {
    // 1 HORIZONTAL LINE --------------
    PORTB = 0b000001; // thsw
    PORTB = 0b000101;
    for (byte i = 0; i < 99; i++) // thbp-thsw
    {
      PORTB = 0b000011;
      PORTB = 0b000111;
    }
    for (int i = 0; i < 480; i++) // thd
    {
      PORTB = 0b000011;
      PORTC = pgm_read_byte(&img0[i + (j * 480)]);
      PORTB = 0b000111;
    }

    for (byte i = 0; i < 37; i++) // thfp
    {
      PORTB = 0b000011;
      PORTB = 0b000111;
    }
    // 1 HORIZONTAL LINE END ----------
  }
  for (byte j = 0; j < 60; j++) // linie od 61 do 120
  {
    // 1 HORIZONTAL LINE --------------
    PORTB = 0b000001; // thsw
    PORTB = 0b000101;
    for (byte i = 0; i < 99; i++) // thbp-thsw
    {
      PORTB = 0b000011;
      PORTB = 0b000111;
    }
    for (int i = 0; i < 480; i++) // thd
    {
      PORTB = 0b000011;
      PORTC = pgm_read_byte(&img1[i + (j * 480)]);
      PORTB = 0b000111;
    }

    for (byte i = 0; i < 37; i++) // thfp
    {
      PORTB = 0b000011;
      PORTB = 0b000111;
    }
    // 1 HORIZONTAL LINE END ----------
  }
  for (byte j = 0; j < 60; j++) // linie od 121 do 180
  {
    // 1 HORIZONTAL LINE --------------
    PORTB = 0b000001; // thsw
    PORTB = 0b000101;
    for (byte i = 0; i < 99; i++) // thbp-thsw
    {
      PORTB = 0b000011;
      PORTB = 0b000111;
    }
    for (int i = 0; i < 480; i++) // thd
    {
      PORTB = 0b000011;
      PORTC = pgm_read_byte(&img2[i + (j * 480)]);
      PORTB = 0b000111;
    }

    for (byte i = 0; i < 37; i++) // thfp
    {
      PORTB = 0b000011;
      PORTB = 0b000111;
    }
    // 1 HORIZONTAL LINE END ----------
  }
  for (byte j = 0; j < 60; j++) // linie od 181 do 240
  {
    // 1 HORIZONTAL LINE --------------
    PORTB = 0b000001; // thsw
    PORTB = 0b000101;
    for (byte i = 0; i < 99; i++) // thbp-thsw
    {
      PORTB = 0b000011;
      PORTB = 0b000111;
    }
    for (int i = 0; i < 480; i++) // thd
    {
      PORTB = 0b000011;
      PORTC = pgm_read_byte(&img3[i + (j * 480)]);
      PORTB = 0b000111;
    }

    for (byte i = 0; i < 37; i++) // thfp
    {
      PORTB = 0b000011;
      PORTB = 0b000111;
    }
    // 1 HORIZONTAL LINE END ----------
  }

PS: Na pewno nie chodzi o komunikację z wyświetlaczem bo gdy wyświetlam np. czarno-białą grafikę, aby zająć mniej niż 65KB pamięci to wszystko jest OK.

Z góry dziękuję za pomoc i pozdrawiam!
 
Odpowiedź
#2
Pobierając dane z pamięci o adresie większym niż 65536 musisz ustawić RAMPZ. Użyj funkcji z sufiksem _far. O pamięć programu się nie martw bo problem pojawia się po przekroczeniu 128kB ponieważ licznik rozkazów AVR liczy słowa a nie bajty.
Ile czasu rysuje się obrazek? Pewnie kilka sekund?
 
Odpowiedź
#3
(26-04-2020, 08:56)RPI86 napisał(a): Pobierając dane z pamięci o adresie większym niż 65536 musisz ustawić RAMPZ. Użyj funkcji z sufiksem _far. O pamięć programu się nie martw bo problem pojawia się po przekroczeniu 128kB ponieważ licznik rozkazów AVR liczy słowa a nie bajty.
Ile czasu rysuje się obrazek? Pewnie kilka sekund?
A to zaskakujące bo 1 obraz rysuje się około 100ms. I nie mogło by wolniej bo ten wyświetlacz nie ma pamięci sram więc jak by było wolniej to na ekranie było by widać ewidentne "fale" obrazu. I dzięki za pomoc, pomogło.
 
Odpowiedź
#4
Mnie wychodzi bliżej 200ms niż 100. Jak mierzyłeś ten czas?
 
Odpowiedź
#5
(25-04-2020, 18:40)ElektronPL napisał(a): Kompilator nie pozwolił mi stworzyć jednej tak dużej tablicy.
AVR-GCC tak ma, niczym Pascal ograniczający tablice do 64kB, AVR-GCC, nie wiadomo czemu, ogranicza tablice dla odmiany do 32kB ale jest na to sposób.
 
Odpowiedź
#6
(26-04-2020, 14:34)RPI86 napisał(a):
(25-04-2020, 18:40)ElektronPL napisał(a): Kompilator nie pozwolił mi stworzyć jednej tak dużej tablicy.
AVR-GCC tak ma, niczym Pascal ograniczający tablice do 64kB, AVR-GCC, nie wiadomo czemu, ogranicza tablice dla odmiany do 32kB ale jest na to sposób.
Zdradzisz jaki to sposób? Czasu nie mierzyłem raczej masz racje. Mój pomiar polegał na tym że rozregulowałem pokrętło w wyświetlaczu (wtedy widać falowanie obrazu) i na kamerze sobie policzyłem ile w sekundzie. I chyba powinienem swój pomiar podzielić na dwa jak teraz na to patrze bo ten ekran robi linie 1,3,5 i 2,4,6 w przeplocie.
   
 
Odpowiedź
#7
Sposób prosty, stworzyć plik .o. Biorać jednak pod uwagę, że wyświetlacz działa wolno, obrazek zajmuje prawie całą pamięć, kompresja raczej nie wchodzi w grę bo AVR jest wolny, to należałoby zmienić AVR na coś mocniejszego a przy okazji tańszego.
 
Odpowiedź
#8
(26-04-2020, 19:00)RPI86 napisał(a): Sposób prosty, stworzyć plik .o. Biorać jednak pod uwagę, że wyświetlacz działa wolno, obrazek zajmuje prawie całą pamięć, kompresja raczej nie wchodzi w grę bo AVR jest wolny, to należałoby zmienić AVR na coś mocniejszego a przy okazji tańszego.
Tak, przetestowałem go na Arduino DUE. Nie dość ze działa szybciej to w jednej zmiennej bez problemu mieści się cała grafika. Dodatkowo teoretycznie można zmieścić 4. Tak czy inaczej to był tylko eksperyment jak Arduino sobie poradzi z obsłużeniem takiego wyświetlacza - i bardzo dobrze bo dowiedziałem się czegoś nowego o mikrokontrolerach Smile . Dzisiaj kupiłem specjalny driver, który ma pamięć SRAM i wtedy ten wyświetlacz będzie miał więcej sensu - oczywiście mówiąc o Arduino.
Btw bardzo mi się podoba na tym forum, że uznaje słowo Arduino za błąd ortograficzny - piękna ironia.
Dziękuję za pomoc, pozdrawiam!
 
Odpowiedź
#9
Driver, sram. Jaki to koszt? Nie taniej użyć lepszego CPU?
 
Odpowiedź
#10
Mega1284 kosztuje 30zł, STM32G070RBT6 6zł a ma 2 razy więcej RAM i inne dodatki. Na LCD przydałoby się 128kB RAM. STM32F411RET6 wychodzi drogo 24zł, tani jest L412 ale ma tylko 80kB RAM.
Masz dwa wyjścia, albo drogo ale i tak taniej niż mega1284 i szybko, łatwo i przyjemnie albo tanio, bardzo tanio porównując do mega1284 i trochę zabawy w sofcie aby konwertować dane przy wysyłaniu do LCD.
Nie napisałeś co chcesz zbudować bo może zupełnie inny CPU trzeba dać.Może potrzeba bardzo dużo RAM? A może FLASH? Może sprzętowe szyfrowanie?
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości