OV5640-ADARFRUIT는 OV5640에 클럭을 연결해준 조그만한 보드로 구성되어 있다.
이를 적용하기 위해서는 용어 들을 살펴 볼 필요가 있다.
밑에는 Scheamtic 이다.
CAMERA_I2C Pin은 SCL과 SDA로 나뉘는데, I2C는 카메라에 있는 레지스터 주소의 있는 Value를 접근하기 위한 프로토콜이다. 이를 통해 카메라 제어를 할 수 있다.
다음으로는 DCMI Pin은 8개인데 8비트로 이미지를 송신하는 통신 프토토콜이다. 그래서 D0부터 D7까지 MCU에 연결해줬다.
DCMI_PIXCLK, DCMI_VSYNC, DCMI_HSYNC들은 이미지를 처리하기 위한 클락의 일종이다.
POWERDOWN Pin은 전원을 켰다 껐다 하는 부분이다. High 일때 전원을 종료하고 Low 일때 전원을 켜는 시스템이다.
다음으로 CAMERA_RESET Pin은 카메라를 초기화하기 위한 Pin이다.
EXTCLK은 혹시나 고해상도의 처리가 필요할 때 클락을 부족할 시 외부로 해서 연결해 줄 수 있는 Pin인데 우리는 그런 고해상도를 사용하지 않아서 NC저항으로 연결해줘 접지 시켜줬다. 대신 CUT OUT JUMPER로 내부 클락( 보드에 탑재되어 있는) 를 사용해줬다.
void CAMERA_IO_Write(uint16_t Reg, uint16_t Value)
{
uint16_t tmp = Value;
HAL_I2C_Mem_Write(&hi2c2, (uint8_t)0x78, Reg, (uint16_t)2, (uint8_t*)&tmp, 1, 1000);
HAL_Delay(1);
}
위 코드는 I2C를 통해 카메라 모듈의 레지스터에 데이터를 쓰는 함수이다.
1. Reg주소에서 Value를 써준다.
2. I2C_Mem_Write 함수는 Value 저장을 포인터 타입으로 하기 때문에 Value를 tmp에 저장한 후 &tmp로 값을 불러왔다.
3. 지연 시간은 1000이다.
const uint16_t OV5640_TEMP[][2] = // data size = 0x2EE00
{
{0x3808, 0x03},
{0x3809, 0x20},
{0x380a, 0x01},
{0x380b, 0xE0},
{0x4300, 0x6F},
{0x4740, 0x22},
{0x501f, 0x01},
};
const uint16_t OV5640_Init[][2] =
{
{0x3103, 0x11},
{0x3008, 0x82},
{0x3103, 0x03},
... //중략
{0x3008, 0x02},
};
//초기화 함수 부분
for(uint8_t index = 0; index < sizeof(OV5640_Init)/4; index++){
CAMERA_IO_Write(OV5640_Init[index][0], OV5640_Init[index][1]);
}
//해상도 함수 부분
for(uint8_t index = 0; index < sizeof(OV5640_TEMP)/4; index++){
CAMERA_IO_Write(OV5640_TEMP[index][0], OV5640_TEMP[index][1]);
}
위 코드는 카메라의 I2C로 접근하여 카메라를 초기화 해주고 해상도를 변경해주는 부분이다.
초기화 할 변수가 많아서 2차원 배열로 선언해주었으며, for문으로 반복 실행했다. 실행한 것은 위에서 선언해줬던 CAMER_IO_Write 이다.
다음은 DCMI에 대해서 설명을 해보겠다.
DCMI는 현재 Slave 8bits External Synchro 로 설정했고, 이는 8bits 데이터 선으로 이미지를 빠르게 전송하는 프로토콜이다. 이 규격 말고도 8,10,12,14 bits 가 있다.
타이밍 다이어그램을 보면 HSYNC와 VSYNC가 교차하면서 2D 데이터가 전송됨을 볼 수 있다. (DMA2D로 나중에 DATA tranfer 된다 )
우리는 RGB565 타입으로 DCMI 반환 받았다. 위와 같은 데이터 타입을 가진다. 이는 OV5640이 RGB888도 지원하지만
데이터가 커서 Refresh rate가 너무 떨어지기 때문에 RGB565 타입으로 했다.
void CAMERA_ContinuousStart(uint8_t *buff)
{
HAL_DCMI_Start_DMA(&hdcmi, 0, (uint32_t)buff, (uint32_t)0x2EE00);
}
위와 같은 함수를 선언하여 DMA로 DCMI 데이터를 전송 받았다.
buff는 DMA하고자하는 대상 주소로 설정 해주면 된다.
LTDC는 디스플레이 (TFT LCD)를 구동하기 위한 드라이버의 일종이다. DMA2D가 이를 보조하며 일종의 그래픽 기능이다.
위는 FFC 타입으로 연결 된 LCD Scheamtic이다. LTDC Pin은 RGB888 타입으로 CAD 되어 있으며 이는 마지막에 RGB565타입으로 Casting 되어 표현되게 된다. BACKLIGHT_A 와 BACKLIGHT_ K는 LCD 드라이버의 백라이트를 구동시키기 위한 Voltage로 드라이버IC가 설치되어 있다. 밑에 Schaemtic을 참조한다.
간단히 말하면 위 Schaemtic은 일종의 Boost Converter(FAN5333B)이며 18V로 백라이트를 구동시키기 위한 Voltage이다.
R24은 Feedback Volage가 적정 값이기 위한 값인 7.5옴으로 결정해주었다. (데이터 시트)
위의 Pin들을 다시 보면 LTDC_CLK는 Logic 클락이고 HSYNC와 VSYNC는 교차하며 2D 데이터를 transfer하는 Reference 클락이다.
LTDC_DE는 Data Enable이라는 뜻으로 RGB 값이 어떤 파형으로써 인가될 때 High가 됨으로 데이터가 transfer 될 수 있게 해주는 Pin이다.
다음으로는 X+ ,X-, Y+,Y- 핀이 있는데 이들은 압전식 터치를 지원하기 위한 Pin들이다. (SPI 터치에서 자세히 다룬다)
위는 CUBE IDE에서 LTDC 설정 파라메타 값이다. Porch와 Synchronization Width/Height는 정확한 값이 아니여도 동작하긴 하지만 LCD 화면이 노이즈가 끼거나 깨질 수 있기에 정확한 입력이 있으면 좋다. (LCD데이터 시트 참고)
HAL_DMA2D_Start(&hdma2d, 0xFF00FF00, (uint32_t)hltdc.LayerCfg[0].FBStartAdress , 800, 480);
HAL_Delay(1000);
HAL_LTDC_SetPixelFormat_NoReload(&hltdc, LTDC_PIXEL_FORMAT_RGB565, 0);
HAL_LTDC_SetWindowSize_NoReload(&hltdc, 800, 480, 0);
//HAL_LTDC_SetWindowPosition(&hltdc, 80, 0, 0);
HAL_Delay(100);
HAL_LTDC_Reload(&hltdc,LTDC_RELOAD_IMMEDIATE);
위는 DMA2D와 LTDC 설정의 일부이다. MX_LTDC_Init으로 자동설정된 초기화 값 입력 후. 위와 같은 함수를 입력해줬다.
hltdc.LayerCfg[0].FBStartAdress는 0xC0000000로 지정했으며 이는 DRAM에 로딩 되기 위한 적정한 주소 값이다. PixelFormat은 RGB565로 Casting 해줬으며 Reload 함수로 다시 Refresh 시켜주었다.
작동 동영상 첨부 예정
'한남대 졸업작품' 카테고리의 다른 글
STM32 DRAM(IS42S32800J-6TL) Artwork와 LED (1) | 2024.12.01 |
---|---|
MBX7843을 이용한 TOUCH 구현 + 최종 결과물 사진 (0) | 2024.11.18 |
TPS54302 BUCK CONVERTER (전원부) (1) | 2024.11.13 |