실제 카메라 사진을 찍기 위한 API를 구현
Arducam에서 제공하는 예제소스를 참고하여 구현하였다.
카메라 및 LWIP 초기화
void StartDefaultTask(void *argument)
{
/* init code for LWIP */
MX_LWIP_Init();
/* USER CODE BEGIN StartDefaultTask */
set_format(JPEG);
initCAM();
set_bit(0x03,0x02);
clear_fifo_flag();
write_reg(0x01,0x00); //VSYNC Active HIGH
OV5642_set_JPEG_size(OV5642_1600x1200);
TcpTaskHandle = osThreadNew(Tcp_Task, NULL, &TcpTask_attributes);
CameraTaskHandle = osThreadNew(Camera_Task, NULL, &CameraTask_attributes);
/* Infinite loop */
for(;;)
{
osThreadTerminate(defaultTaskHandle);
}
/* USER CODE END StartDefaultTask */
}
StartDefaultTask 에서 LWIP 초기화 후 카메라를 초기화 해준다.
initCAM()
void initCAM ()
{
uint16_t reg_val;
wrSensorReg16_8 (0x3008, 0x80);
wrSensorRegs16_8 (OV5642_QVGA_Preview);
HAL_Delay (100);
if (m_fmt == JPEG)
{
wrSensorRegs16_8 (OV5642_JPEG_Capture_QSXGA);
wrSensorRegs16_8 (ov5642_320x240);
HAL_Delay (100);
wrSensorReg16_8 (0x3818, 0xa8);
wrSensorReg16_8 (0x3621, 0x10);
wrSensorReg16_8 (0x3801, 0xb0);
wrSensorReg16_8 (0x4407, 0x04);
}
else
{
wrSensorReg16_8 (0x4740, 0x21);
wrSensorReg16_8 (0x501e, 0x2a);
wrSensorReg16_8 (0x5002, 0xf8);
wrSensorReg16_8 (0x501f, 0x01);
wrSensorReg16_8 (0x4300, 0x61);
rdSensorReg16_8 (0x3818, (uint8_t*) ®_val);
wrSensorReg16_8 (0x3818, (reg_val | 0x60) & 0xff);
rdSensorReg16_8 (0x3621, (uint8_t*) ®_val);
wrSensorReg16_8 (0x3621, reg_val & 0xdf);
}
}
앞서 설정한 set_format으로 JPEG으로 카메라르 초기화 해준다.
초기화 및 레지스터 설정은 첨부한 Application Note에 자세히 설명 되어있다.
Camera_Capture
void Camera_Capture(struct netconn *cmraconn)
{
flush_fifo();
clear_fifo_flag();
HAL_Delay(1);
fstart_capture();
camera_flag = true;
/****** Camera_flag***********/
while (camera_flag)
{
if (get_bit(0x41, 0x08))
{
#ifdef DEBUG
printf("get_bit is true \n\r");
#endif
Camera_Module_length = read_fifo_length();
first_picture_data();
second_picture_data(cmraconn);
camera_flag = false;
}
}
}
void flush_fifo (void)
{
write_reg (0x04, 0x01);
}
void fstart_capture (void)
{
write_reg (0x04, 0x02);
}
void clear_fifo_flag (void)
{
write_reg (0x04, 0x01);
}
flush_fifo와 clear_fifo_flag는 같은 명령어이며 fifo buffer를 모두 clear 한다.
Camera Capture 명령어를 내리고 카메라가 사진이 찍혔으면 0x41 Address에 4번째 비트에 1이 setting 된다.
1이 set 된걸 확인 후 first_picture_data 함수와 second_picture_data 함수를 통해 buffer에 있는 데이터를 가지고 와
TCP로 전송한다.
fist_picture_data
void first_picture_data()
{
uint8_t spi_dummy;
cmra_flag = 0;
Real_length = 0;
cmra_buf[cmra_flag++] = 'T';
cmra_buf[cmra_flag++] = 'E';
cmra_buf[cmra_flag++] = 'S';
cmra_buf[cmra_flag++] = 'T';
set_fifo_burst();
while (1)
{
temp_last = temp;
HAL_SPI_TransmitReceive(&hspi3, (uint8_t*) &spi_dummy, &temp, 1, 1000);
if ((temp == 0xD8) && (temp_last == 0xFF))
{
cmra_buf[cmra_flag++] = temp_last;
Real_length++;
cmra_buf[cmra_flag++] = temp;
Real_length++;
picture_flag = true;
break;
}
}
}
First picture data를 통해 사진의 헤더를 찾는다 JPEG 포멧의 첫 header는 0xff 0xd8로 시작한다.
따라서 0xff와 0xd8이란 데이터가 나오기 전까지는 저장하지 않고 모두 버린다.
만약 0xff와 0xd8을 찾았다면 Cmra_buf에 데이터를 저장 후 함수를 종료한다.
second_picture_data
void second_picture_data(struct netconn *cmraconn)
{
while (picture_flag)
{
temp_last = temp;
HAL_SPI_TransmitReceive(&hspi3, (uint8_t*) &spi_dummy, &temp, 1, 1000);
cmra_buf[cmra_flag++] = temp;
Real_length++;
if ((temp == 0xD9) && (temp_last == 0xFF))
{
picture_flag = false;
cmra_buf[cmra_flag++] = 0xFF;
cmra_buf[cmra_flag++] = 0xFF;
cmra_buf[cmra_flag++] = 0xFF;
cmra_buf[cmra_flag++] = 0xFF;
cmra_buf[cmra_flag++] = Real_length >> 24;
cmra_buf[cmra_flag++] = Real_length >> 16;
cmra_buf[cmra_flag++] = Real_length >> 8;
cmra_buf[cmra_flag++] = Real_length;
clear_fifo_flag();
netconn_write(cmraconn,cmra_buf,cmra_flag,NETCONN_COPY);
cmra_flag = 0;
}
if (cmra_flag == SEND_SIZE)
{
netconn_write(cmraconn,cmra_buf,cmra_flag,NETCONN_COPY);
cmra_flag = 0;
osDelay(1);
}
}
}
second_picture_data 함수에서는 계속 데이터를 cmra_buf에 저장한다.
저장하다가 보내고자하는 buffer size 까지 다 차면 netconn_write 를 호출하여 데이터를 보낸 후
다시 cmra_buf[0]부터 채워 나간다.
채우다가 jpeg의 마지막 패킷을 알리는 0xff 0xd9가 더이상 데이터를 저장하지 않고 0xff 4개와 사진 데이터 길이를 추가로 저장 후 tcp로 전송한다.
그리고 pitcutre_flag는 false가 되어 함수는 종료 된다.
'Firmware > stm32' 카테고리의 다른 글
stm32 uart interrupt 멈추는 현상( RXNEIE disable, overrun) (7) | 2020.06.06 |
---|---|
OV5642_LWIP_RTOS Project -3(최종 구현 및 디버깅) (0) | 2020.05.31 |
OV5642_LWIP_RTOS Project -2(Camera Interface 구현 ) (1) | 2020.04.23 |
OV5642_LWIP_RTOS Project -1(Netconn_write 호출 시 문제) (0) | 2020.04.23 |
OV5642_LWIP_RTOS Project -1(osThreadSetPriority 문제) (0) | 2020.04.17 |