Interfejs DCMI w STM32: jak dołączyć kamerę CCD do mikrokontrolerów STM32F2 i STM32F4
Przedstawiamy prostą aplikację na mikrokontroler STM32F4 obsługującą kamerę modCAM_2MP_2 i wyświetlacz modTFT32T, które podłączono do zestawu ZL41ARM. Dodatkowo dodano także obsługę komunikacji z komputerem PC przez port USB, dzięki czemu można łatwo konfigurować parametry kamery z poziomu aplikacji i obserwować efekty w czasie rzeczywistym bez konieczności programowania mikrokontrolera.
Schemat elektryczny
Schemat elektryczny przedstawiający sposób podłączenia modułu z kamerą oraz wyświetlacza LCD z panelem dotykowym do komputera jednopłytkowego z mikrokontrolerem STM32F417VG przedstawiono na rysunku 1 (pozostała część schematu znajduje się w dokumentacji zestawu ZL41ARM). Obecność dużej liczby połączeń powoduje, że w czasie pracy układu mogą występować w nich zakłócenia mające wpływ zarówno na odbierane dane z kamery jak i wysyłane do wyświetlacza. Jednym ze sposobów ich zmniejszenia jest przeplatanka przewodów połączeniowych jak widać na fotografii 1. Również ważnym jest aby chronić tylną część kamery przed światłem, gdyż w przeciwnym wypadku obraz może być w pewnych miejscach nieprawidłowy (inny kolor, dziwne piksele) lub prześwietlony.
Rys. 1. Schemat elektryczny podłączenia kamery i wyświetlacza
Do zasilania kamery potrzebne jest napięcie maksymalnie 3 V (na płytce komputera występuje napięcie 3,3 V), dlatego został wykorzystany zewnętrzny stabilizator LM2950. Dodatkowo linie D+ oraz D- z gniazdka USB typu mini A zostały na stałe połączone z odpowiednimi wyprowadzeniami mikrokontrolera poprzez przylutowanie cienkich przewodów, ponieważ fabrycznie takich połączeń nie ma (w tabeli 1 przedstawiono jak to zostało zrobione). Interfejs USB pracuje w trybie Full Speed i nie jest wymaganym umieszczanie zewnętrznego rezystora podciągającego na linii D+ (jest on wbudowany w mikrokontroler).
Tab. 1. Opis zewnętrznych wyprowadzeń gniazdka USB typu mini A
Numer | Oznaczenie | Opis |
1 | VCC | Napięcie zasilania +5 V |
2 | D- | Linia transmisji danych podłączona do nóżki PA11 mikrokontrolera |
3 | D+ | Linia transmisji danych podłączona do nóżki PA12 mikrokontrolera |
4 | NC | Nie podłączone |
5 | GND | Masa |
Moduł wyświetlacza modTFT32T posiada kolorowy wyświetlacz z rozdzielczością 240RGBx320 pikseli sterowany przez kontroler SSD1289 oraz panel dotykowy obsługiwany przez kontroler ADS7843. Do komunikacji z kontrolerem SSD1289 wykorzystuje się interfejs równoległy typu (Intel) 8080 w którym transmisja odbywa się asynchronicznie i który posiada następujące linie sterujące/danych:
- linia wyboru chipu – CS,
- linia wyboru rejestru/pamięci RAM – RS,
- linia wyboru trybu zapisu – nWS,
- linia wyboru trybu odczytu – nRD,
- linia sygnału zerującego – nRESET,
- 16-bitowa szyna danych – D0:D15.
Do poprawnej pracy wyświetlacza oprócz zasilania podawanego na wejścia +5 V <–> GND wymagane jest jeszcze włączenie podświetlenia LED: BLVDD(+5 V) <–> BLGND(GND). Brak podświetlenia uniemożliwia zobaczenie jakichkolwiek efektów zapisu do pamięci GDDRAM (Graphics Display Data RAM). Komunikacja z kontrolerem wyświetlacza odbywa się za pośrednictwem kontrolera FSMC (Flexible Static Memory Controller) przeznaczonym do zapisu/odczytu do/z zewnętrznych pamięci takich jak pamięć SRAM lub FLASH, a także do obsługi wyświetlaczy z interfejsem równoległym zgodnym ze standardem 6800 lub i8080.
Rys. 2. Podłączenie wyświetlacza do FSMC
Komunikacja z komputerem przez USB
Gotowy projekt obsługi komunikacji z wykorzystaniem portu USB został skopiowany z pliku archiwalnego o nazwie STM32F105/7, STM32F2 and STM32F4 USB on-the-go Host and device library (wersja 2.1.0), który jest dostępny na stronie producenta danego mikrokontrolera w zakładce Design support -> Firmware. Jest to projekt urządzenia realizującego funkcję wirtualnego portu COM (znajduje się w katalogu Project -> USB_Device_Examples -> VCP). Część projektu została zmodyfikowana na potrzeby komunikacji z prostą aplikacją PC i zostały dołączone pliki obsługi wyświetlacza LCD minimalnie zmodyfikowane do pracy z kontrolerem SSD1289 (również dostępne w powyższym pliku archiwalnym).
Komunikacja między aplikacją PC, a układem ZL41ARM sprowadza się do zapisu/odczytu rejestrów/zmiennych sterownika kamery, a funkcje które to umożliwiają po stronie mikrokontrolera znajdują się w pliku usbd_cdc_vcp.c:
uint16_t VCP_DataTx (uint8_t* Buffer, uint32_t Length) { uint32_t i; //loop through buffer for(i = 0; i < Length; i++) { APP_Rx_Buffer[APP_Rx_ptr_in] = (uint8_t) Buffer[i]; //increase pointer value APP_Rx_ptr_in++; /* To avoid buffer overflow */ if(APP_Rx_ptr_in == APP_RX_DATA_SIZE) { APP_Rx_ptr_in = 0; } } return USBD_OK; } static uint16_t VCP_DataRx (uint8_t* Buffer, uint32_t Len) { if(Buffer[0] == MT9D111_RD_REG_CMD){ MT9D111_WriteReg(PAGE_SELECT_REG, Buffer[2]); // Select Page reg_value = MT9D111_ReadReg(Buffer[1]); // Select and Read Register TxBuffer[0] = reg_value >> 8; // MS Byte TxBuffer[1] = reg_value & 0xFF; // LS Byte VCP_DataTx(TxBuffer,2); // Write to USB output buffer } else if(Buffer[0] == MT9D111_WR_REG_CMD){ reg_value = (Buffer[3] << 8) + Buffer[4]; // Get 16-bit value MT9D111_WriteReg(PAGE_SELECT_REG, Buffer[2]); // Select Page MT9D111_WriteReg(Buffer[1], reg_value); // Select and Write Register */ } else if(Buffer[0] == MT9D111_WR_VAR_CMD){ var_addr = (Buffer[1] << 8) + Buffer[2]; // Get 16-bit address var_data = (Buffer[3] << 8) + Buffer[4]; // Get 16-bit value MT9D111_WriteReg(PAGE_SELECT_REG, 0x1); // Select Page MT9D111_WriteReg(UC_VAR_ADDR_REG, var_addr); // Select Variable MT9D111_WriteReg(UC_VAR_DATA_REG, var_data); // Write Variable } else if(Buffer[0] == MT9D111_RD_VAR_CMD){ var_addr = (Buffer[1] << 8) + Buffer[2]; MT9D111_WriteReg(PAGE_SELECT_REG, 0x1); // Select Page MT9D111_WriteReg(UC_VAR_ADDR_REG, var_addr); // Select Variable var_data = MT9D111_ReadReg(UC_VAR_DATA_REG); // Read Variable TxBuffer[0] = var_data >> 8; // MS Byte TxBuffer[1] = var_data & 0xFF; // LS Byte VCP_DataTx(TxBuffer,2); // Write to USB output buffer } return USBD_OK; }
Funkcja VCP_DataRx() jest wywoływana automatycznie za każdym razem jak tylko zostały odebrane nowe dane z portu USB komputera i wykonywane jest w niej przetworzenie rodzaju komendy (zapis/odczyt, rejestr/zmienna) oraz jej argumentów (adres, dane). Natomiast funkcja VCP_DataTx() jest wywoływana jawnie w celu przekopiowania danych do endpointa IN urządzenia, w wyniku czego zostaną one wysłane do komputera.