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

[STM32F4] - Układ DMA: DCMI -> SRAM

rezontor 28 Gru 2014 01:34 5373 60
  • #1 28 Gru 2014 01:34
    rezontor
    Poziom 15  

    Witam.

    Piszę właśnie program, którego zadaniem jest pobranie 1 klatki (zrobienie zdjęcia) z kamery MT9D111 (nota katalogowa: http://www.dragonwake.com/download/camera/MT9D111/mt9d111_rev5.pdf ) Klatki z kamery będzie pobierał mikrokontroler STM32F429, taktowany częstotliwością 180MHz.

    Wzoruję się na informacjach zawartych na stronie: http://www.stm32.eu/node/307

    Napisałem podstawowe funkcje, konfigurujące:

    - PORTY GPIO, wykorzystane do komunikacji z kamerą:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    - RCC (dołączenie sygnałów taktujących do peryferii)

    Kod: c
    Zaloguj się, aby zobaczyć kod


    - układ interfejsu kamery DCMI oraz DMA:

    Kod: c
    Zaloguj się, aby zobaczyć kod



    - układ przerwań NVIC

    Kod: c
    Zaloguj się, aby zobaczyć kod


    - oraz układ I2C do wysyłania ustawień do kamery:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Później, w programie głównym, wywołuje powyższe funkcje konfigurujące:

    Kod: c
    Zaloguj się, aby zobaczyć kod



    Następnie, sprawdzam, czy kamera jest podłączona i inicjalizuję kamerę:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Jeżeli chodzi o funkcję inicjalizującą kamerę i inne funkcje związane z kamerą - są one w osobnym pliku i przedstawiają się tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod




    Teraz, gdybym chciał wykonać zdjęcie, wywołuję w pętli głównej funkcję wykonaj_foto():

    Kod: c
    Zaloguj się, aby zobaczyć kod



    Czyli w tym momencie, po wywołaniu funkcji wykonaj_foto(), układ DMA powinien wysłać dane do RAMU - do tablicy, zdefiniowanej wcześniej w programie:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    do której DMA powinien wysyłać dane z DCMI, jak zostało skonfigurowane w 3 funkcji w poście (czyli DCMI_Config() ):

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Tablica ma rozmiar 9600, ponieważ będą przesyłane obrazy o rozdzielczości (tak ustaliłem) 160 x 120 pikseli, w formacie 565RGB (czyli po 2B na piksel). Wynika z tego, że potrzebuję 160*120*2 = 38 400 bajtów w tablicy. Każda komórka tablicy ma 4B, więc potrzebuję 38 400 / 4 - 9600 komórek typu uint32.

    Teraz chciałbym zapytać, co robię źle... Program, po wgraniu do mikrokontrolera nie działa. Efektem wywołania funkcji robiącej zdjęcie powinna być zapełniona tablica bufor_RAM_danych_obrazka, jednak tak nie jest. Czym to może być spowodowane?

    Czy jest może źle układ DMA skonfigurowany? - mam wątpliwości w miejscach:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0 29
  • Metal Work Pneumatic
  • Pomocny post
    #2 28 Gru 2014 23:42
    A.T.
    Poziom 20  

    Sam napisałeś 38400 / 4 to czemu zapisujesz do DMA 38400, a nie 9600?
    No i to:
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    też bym ustawił na DMA_MemoryDataSize_Word.

    Pozdrawiam

    Dodano po 3 [minuty]:

    No i tak jak masz teraz ustawione DMA w trybie Normal to ta funkcja wykonaj_foto zadziała tylko raz, później będziesz musiał na nowo konfigurować DMA. Lepiej przestaw je w opcję circular.

    0
  • #3 31 Gru 2014 13:56
    rezontor
    Poziom 15  

    A.T. napisał:
    Sam napisałeś 38400 / 4 to czemu zapisujesz do DMA 38400, a nie 9600?

    Poprawiłem.
    A.T. napisał:
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    też bym ustawił na DMA_MemoryDataSize_Word.

    Chciałbym, aby dane w RAMIE były zapisane jako struktury 8 bitowe - łatwiej później będzie to przetwarzać.

    Dodano po 3 [sekundy]:

    A czy taka konfiguracja przerwań od układu DCMI jest poprawna?

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • Pomocny post
    #4 31 Gru 2014 15:13
    A.T.
    Poziom 20  

    To nie jest konfiguracja tylko funkcja obsługi przerwania. Ta pętla while czekająca na koniec odbioru wygląda nie najlepiej w funkcji przerwania. Na początek spróbuj bez przerwań czy w ogóle działa.

    0
  • #5 01 Sty 2015 00:53
    rezontor
    Poziom 15  

    Niestety, ale nie działa. Program zatrzymuje się na:

    Kod: c
    Zaloguj się, aby zobaczyć kod
    w funkcji
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Dodano po 19 [minuty]:

    2 rzecz. Przykład ze strony http://www.stm32.eu/node/307/page/0/3 zakłada, że częstotliwość taktowania mikrokontrolera jest równa 168MHz. Wtedy sygnał taktujący kamerę, po podzieleniu przez 3, wynosi XCLK = 56MHz. W moim przypadku częstotliwość taktowania wynosi 180MHz i dzieląc ją przez 3, otrzymuję 60MHz. Czy ta zmiana zegara wiąże się ze zmianami wartości wpisywanych do rejestrów kamery? Na stronie http://www.stm32.eu/node/310 jest napisane, że "Oprócz tego do podłączenia pozostał jeszcze jeden sygnał: sygnał zegara taktującego który trzeba podać do modułu.. Zazwyczaj częstotliwość zegara w przypadku różnego typu modułów zawiera się w granicach 6...80 MHz." Więc mieści się w tym przedziale...

    Chodzi mi o fragment:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • Pomocny post
    #6 01 Sty 2015 08:59
    TvWidget
    Poziom 32  

    Kamery zwykle mają wewnętrzny PLL. Częstotliwość sygnału XCLK i wartości wpisywane do rejestrów kamery muszą być odpowiednio dobrane.

    0
  • Metal Work Pneumatic
  • Pomocny post
    #7 01 Sty 2015 11:19
    A.T.
    Poziom 20  

    A rejestry Ci się konfigurują? Bo jak nie ma sygnału zegarowego XCLK albo jest niepoprawny to nawet rejestrów przez I2C nie da się skonfigurować.
    Zgadza się w kamerze jest PLL, w datasheet masz wzór gdzie dobierasz 3 wartości i wpisujesz to tych dwóch rejestrów:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #8 01 Sty 2015 13:42
    rezontor
    Poziom 15  

    Dzisiaj wszystko jeszcze raz uruchomiłem i o dziwo zaczęły przychodzić dane z kamery, a program się nie zawiesza.

    Dodałem w programie takie polecenia:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Najpierw jest zerowana tablica, do której trafią dane z kamery. Następnie kamera jest uruchamiana i jest robione zdjęcie. W efekcie w tablicy bufor_RAM_danych_obrazka otrzymuję wartości, które przy pomocy funkcji USART_puts() wysyłam przez terminal.

    Otrzymuję następujące dane, które - jako log z terminala - zamieszczam w załączniku.


    Załącznik:

    0
  • #9 01 Sty 2015 14:26
    A.T.
    Poziom 20  

    Ten bufor zadeklarowałeś wcześniej o rozmiarze 9600, to skąd bierzesz tam jakieś 19200? Rozumiem, że nie masz wyświetlacza żeby zobaczyć co zwraca kamera. To spróbuj dodać nagłówek bmp do twoich danych i zobacz czy to co dostajesz to jest jakiś obraz.

    0
  • #10 01 Sty 2015 14:51
    rezontor
    Poziom 15  

    A.T. napisał:
    Ten bufor zadeklarowałeś wcześniej o rozmiarze 9600, to skąd bierzesz tam jakieś 19200? R


    Zmieniłem rozdzielczość obrazu na większą.
    A.T. napisał:
    To spróbuj dodać nagłówek bmp do twoich danych i zobacz czy to co dostajesz to jest jakiś obraz.




    W Internecie znalazłem program enkodera.

    Kod: c
    Zaloguj się, aby zobaczyć kod



    Nie wiem tylko za bardzo, w jaki sposób mogę przekazać moje dane do tej funkcji przetwarzającej do postaci BMP...

    0
  • #11 01 Sty 2015 15:28
    A.T.
    Poziom 20  

    Hmm nie rozumiem problemu, wystarczy, że wywołasz tę funkcję z odpowiednimi argumentami:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Jako pierwszy argument podajesz wskaźnik do Twojego bufora z surowymi danymi czyli bufor_RAM_danych_obrazka, a jako przed ostatni wskaźnik do Twojego nowego bufora gdzie zostanie przepisany Twój obrazek i dodatkowo jeszcze dodany nagłówek bmp. Musisz jednak uważać, żeby zmieścić się w RAMie procka.

    0
  • #12 01 Sty 2015 16:42
    rezontor
    Poziom 15  

    Rozumiem. Dziękuję za pomoc.

    Poczyniłem kilka zmian w programie. Utworzyłem drugą tablice - pierwsza to ta, która przyjmuje dane z kamery (bufor_RAM_danych_obrazka), a druga jest tablicą wyjściową z przekonwertowanym plikiem (p_bufor_RAM_pliku).

    W wcześniejszych definicjach tablic i określaniu danych do przesłania popełniłem błąd - nie wziąłem pod uwagę tego, że każdy piksel to 2B. Więc przy rozdzielczości 320 * 240, liczba danych wynosi: 76800 * 2B = 153600B = 150kB. Wynika z tego, że 2 tablice (dane z kamery i dane przekonwertowane) w wbudowanej pamięci RAM się nie zmieszczą (STMF429 ma 256kB RAMU).

    Muszę zatem zmniejszyć rozdzielczość do np. QCIF = 176 x 144 (szerokość = 176, wysokość = 144). Dane o obrazie będą wtedy zajmowały 50688 bajtów i dwie tablice się zmieszczą.

    Pomyślałem też nad zmianą typów tablic z:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    na
    Kod: c
    Zaloguj się, aby zobaczyć kod



    Czyli po podstawieniu za szerokość i wysokość konkretnych liczb mamy:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Zmiany wymusiły modyfikacje w konfiguracji DMA:

    Kod: c
    Zaloguj się, aby zobaczyć kod



    W pętli głównej planuję umieścić takie wywołanie funkcji:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Po wywołaniu funkcji dostanę tablicę bajtów p_bufor_RAM_pliku , w której jest zdjęcie z kamery wraz z nagłówkiem BMP. Teraz wystarczy wysłać dane do komputera i ten ciąg liczb 8 bitowych zapisać w postaci pliku BMP.

    Chciałbym zapytać, czy powyższy tok pisania programu jest prawidłowy?

    0
  • #13 01 Sty 2015 17:00
    A.T.
    Poziom 20  

    Dobrze kombinujesz, jednak źle zmieniłeś wartość danych jakie ma przesłać DMA. Tam podajesz ilość 4bajtowych paczek. Czyli dla Twojego nowego formatu będzie to: 176*144*2/4=12672, i tą wartość wpisujesz do DMA. Reszta wydaje mi si poprawna. Jedyne co, to przyglądnij się dokładnie ustawieniom formatu wyjściowego obrazu kamery. Nie może być ustawiona opcja "Swap even and odd bytes". Jeśli jest to uzyskasz obraz z zamienionymi kolorami bodajże R z B.

    0
  • #14 02 Sty 2015 01:29
    rezontor
    Poziom 15  

    Aby otrzymać rozdzielczość 176 x 144, ustawiam rejestry w taki sposób:

    Kod: c
    Zaloguj się, aby zobaczyć kod



    Po wywołaniu funkcji robiącej zdjęcie oraz konwertującej do postaci BMP, otrzymuję następujący ciąg bajtów (załącznik) - każdy bajt jest przedstawiony przy pomocy tekstu (0-255), a poszczególne bajty są oddzielone od siebie przecinkami.

    Zastanawiam się, w jaki sposób mógłbym zapisać teraz plik BMP. Czy wszystkie bajty zamienić na postać zero-jedynkową (bin) i zapisać pod rozszerzeniem *bmp?

    0
  • #15 03 Sty 2015 03:28
    rezontor
    Poziom 15  

    Zamieniłem otrzymane dane z kamery na postać binarną. Niestety, ale przeglądarka grafiki Windows informuje o uszkodzeniu pliku... Czym to może być spowodowane?

    0
  • #17 03 Sty 2015 12:49
    rezontor
    Poziom 15  

    Dydelmax napisał:
    rezontor napisał:
    Czym to może być spowodowane?

    Brakiem nagłówka dla BMP?


    Naglówek jest automatycznie dodawany w funkcji Kodowanie_z_bufor_RAM_danych_na_BMP_do_RAM_pliku, którą wywołuję.

    0
  • Pomocny post
    #18 03 Sty 2015 12:59
    Dydelmax
    Poziom 35  

    Jakoś nie widzę tego nagłówka... (może po prostu nie mogę go znaleźć - sugeruję się tym: http://pl.wikipedia.org/wiki/Windows_Bitmap):
    [STM32F4] - Układ DMA: DCMI -> SRAM
    Dla porównania nagłówek pliku BMP (176x144) wypełnionego białymi pikselami:
    [STM32F4] - Układ DMA: DCMI -> SRAM

    0
  • Pomocny post
    #19 03 Sty 2015 13:52
    atom1477
    Poziom 43  

    Błędem jest zamienianie danych na "postać zero-jedynkową (bin)".
    Tzn. błędem nie jest samo zamienianie, co założenie że taką zmianę należy zrobić.
    Choć po pliku nie widać żebyś w rzeczywistości robił taką zamianę.
    Rozmiar pliku sugeruje że zapis jest w formacie 16-bitowym, a to dość niepopularne.
    Widzę że nawet IrfanVIew tego nie łyka (nie pozwala na zapis w takim formacie).
    Dodatkowo nagłówek wychodziło by że ma 101 bajtów, a taki też chyba nie może być (co najmniej wielokrotność 2). Treść tego nagłówka oczywiście też jest błędna (kompletne krzaczory).

    0
  • #20 03 Sty 2015 14:35
    rezontor
    Poziom 15  

    Popełniłem błąd przy wywoływaniu funkcji konwertującej.

    Teraz otrzymuję taki plik, który nadal wydaje się być uszkodzony:

    0
  • Pomocny post
    #21 03 Sty 2015 15:00
    Dydelmax
    Poziom 35  

    Przeszczepiłem (na chybił trafił) kilka bajtów z innego pliku BMP. Wynikiem przeszczepu jest to "coś" poniżej, co udało mi się otworzyć programem PhotoFiltre i zapisać jako PNG.
    [STM32F4] - Układ DMA: DCMI -> SRAM
    Tak wygląda nagłówek zmodyfikowanego pliku:
    [STM32F4] - Układ DMA: DCMI -> SRAM
    Nie znam się na strukturze plików BMP, więc nie wiem czemu plik wygląda tak a nie inaczej. Może paleta kolorów w pliku jest źle skonstruowana?
    EDIT: Bez modyfikacji nagłówka PhotoFiltre również odczytuje ten plik, pokazując to samo co wrzuciłem powyżej.
    EDIT2: Dane w pliku wyglądają na losowe śmieci. Wkleiłem fragment innego obrazka do tego pliku w hexedytorze i PhotoFiltre wyświetlił ten fragment poprawnie.
    [STM32F4] - Układ DMA: DCMI -> SRAM

    0
  • #22 03 Sty 2015 15:12
    rezontor
    Poziom 15  

    Podobny obraz otrzymuję dla poprzedniego pliku, który został poprawiony: [STM32F4] - Układ DMA: DCMI -> SRAM Wygląda to na całkowicie losowe wartości.

    0
  • Pomocny post
    #23 03 Sty 2015 15:27
    Dydelmax
    Poziom 35  

    rezontor napisał:
    Wygląda to na całkowicie losowe wartości.

    Całkowicie losowe one jednak nie są. Pionowe linie w pliku powyżej przebiegają tak: linia z tylko zielonym kolorem (lub jego brakiem), linia z czerwonym i/lub niebieskim kolorem (lub ich brakiem). Wygląda to tak: G, R+B, G, R+B, G, R+B itd.
    EDIT: Końcówka pliku wygląda na uciętą. Po doklejeniu szumu do końca pliku poprzez dopisanie kolejnych bajtów (skutkujące zwiększeniem rozmiaru pliku), czarny pas na górze pliku zmienia się w doklejoną treść, w tym przypadku szum:
    [STM32F4] - Układ DMA: DCMI -> SRAM
    Dodatkowo, po uzupełnieniu końcówki plik można bezproblemowo otworzyć w innych programach (dodaję go w załączniku).

    0
  • Pomocny post
    #24 03 Sty 2015 15:36
    atom1477
    Poziom 43  

    Zrób zdjęcie jakiegoś obrazu testowego, to będzie łatwiej dojść co jest nie tak (będzie można się chociaż w przybliżeniu domyślać jakie wartości mają mieć poszczególne pixele).

    0
  • #25 03 Sty 2015 18:33
    rezontor
    Poziom 15  

    Aktualnie najważniejsze pliki programu wyglądają następująco:

    main.c:

    Kod: c
    Zaloguj się, aby zobaczyć kod



    stm32f4xx_it.c:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    konfigPeryf.c:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    kamera.c:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    BMP_enkoder.c

    Kod: c
    Zaloguj się, aby zobaczyć kod


    usart.c:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • Pomocny post
    #26 03 Sty 2015 21:40
    kemot55
    Poziom 30  

    Rozumiem, że z kamery oczekujesz obrazu w formacie 565. Jeżeli będzie to BMP 2-bajtowa, to dobrze by było jednak nagłówek skopiować z tego co wytwarza zastosowana procedura tworzenia struktury BMP. Z przykładów i sztucznego dodawania "końcówki" wynika, że dekoder oczekuje formatu 24bit.

    0
  • #27 04 Sty 2015 01:31
    rezontor
    Poziom 15  

    Sprawdziłem, jaką wartość zwracała funkcja

    Kod: c
    Zaloguj się, aby zobaczyć kod


    zgodnie z opisem konwertera (http://www.stm32.eu/node/346), funkcja powinna zwracać wartość inną niż zero - w moim przypadku zwracała zero, a to oznacza, że bufor wyjściowy jest za mały.

    Zwiększyłem więc bufor wyjściowy do wartości [76032+100]:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Po tym zwiększeniu, funkcja zaczęła zwracać wartość 76086. Oznacza to, że tyle bajtów jest w buforze wyjściowym, po konwersji. Wykorzystałem ten fakt w pętli wysyłającej dane do komputera:

    Kod: c
    Zaloguj się, aby zobaczyć kod



    Pliki są wysyłane do komputera w postaci:

    66;77;54;99;0;0;0;0;0;0;54; ... itd

    Napisałem program w JAVIE, który odczytuje te dane dzieląc je wg separatora ";" i zapisując w tablicy int (po przekształceniu z tekstu na liczbę):
    Kod: java
    Zaloguj się, aby zobaczyć kod


    Następnie jest wywoływana funkcja zapisująca plik:
    Kod: java
    Zaloguj się, aby zobaczyć kod


    któa wygląda tak:

    Kod: java
    Zaloguj się, aby zobaczyć kod


    Efektem działania funkcji jest plik bmp. Okazało się, że po tych modyfikacjach, pliki bmp są PRAWIDŁOWO zapisywane. Można je otworzyć przy pomocy systemowego programu do otwierania zdjęć. Problem jest z tym, że to, co jest na tych zdjęciach, jest całkowicie nieczytelne. Wykonałem 2 klatki przy różnych ustawieniach kamery - obrazek pierwszy powstał w zaciemnionym miejscu, a w przypadku obrazka drugiego - kamera patrzyła w kierunku światła. Mimo tych różnic w oświetleniu i położeniu obiektywu, zdjęcia są niemal identyczne (załącznik). Czym to może być spowodowane?

    0
  • #28 04 Sty 2015 03:11
    rezontor
    Poziom 15  

    Tutaj jeszcze zamieszczam rozkład pinów, połączonych z kamerą:

    Code:
    PA9 - DCMI_D0
    
    PC7 - DCMI_D1
    PC8 - DCMI_D2
    PC9 - DCMI_D3
    PC11 - DCMI_D4
    PD3  - SCMI_D5
    PE5 - DCMI_D6
    PE6 - DCMI_D7
    PB7 - DCMI_VSYNC
    PA4 - DCMI_HSYNC (HREF)
    PF0/PF1 - SDA/SCL'
    PA6 - DCMI_PIXCLK
    PA8 - XCLK

    Code:
    PB8 - USART2_TX
    
    PB9 - USART2_RX

    ---
    Dodam, że gdy zmieniłem częstotliwość XCLK (na wyższą - podział 180MHz przez 2 a nie przez 3), otrzymałem zupełnie inne obrazy (załącznik; zdjęcia z 2 perspektyw).

    0
  • Pomocny post
    #29 04 Sty 2015 10:36
    kemot55
    Poziom 30  

    Jeżeli kamera zwraca obraz w formacie 565 to on nie może być zapisany do postaci 24bitowej ot tak sobie. Procedura p. Szymaniaka nie konwertuje obrazu z 565 (16bit) do 888 (24bit). Co prawda pojawia się parametr liczby bajtów na piksel, ale tylko po to żeby go przepisać do nagłówka bitmapy :-)

    0
  • #30 04 Sty 2015 10:55
    A.T.
    Poziom 20  

    Jeśli potrafisz to zmierz zegar xclk. Jeśli nie, to zamień go na jakiś zdecydowanie niższy do 20MHz, a PLL w kamerze ustaw tak, aby zegar pclk nie przekraczał 30MHz. Najlepiej, żeby był z zewnętrznego generatora.

    Dodano po 1 [minuty]:

    A i którą wersję ustawienia bloku PLL masz odkomentowaną?

    0
  Szukaj w 5mln produktów