Project에 사용 된 OV5642 는 DCMI or MIPI Interface가 아닌 SPI, I2C ineterface를 통해 사진데이터를 출력한다.
https://www.devicemart.co.kr/goods/view?no=1383721
(https://www.arducam.com/downloads/shields/ArduCAM_Camera_Shield_Software_Application_Note.pdf)
먼저 카메라의 SPI 하기 위한 Timing Diagram이다.
코드 구현
uint8_t bus_write (int address, int value)
{
GPIOC->BSRR = CS_Pin << 16;
HAL_SPI_Transmit (&hspi3, (uint8_t*) &address, 1, 1000); //Command phase
HAL_SPI_Transmit (&hspi3, (uint8_t*) &value, 1, 1000); //Data phase
GPIOC->BSRR = CS_Pin;
return 1;
}
void write_reg (uint8_t addr, uint8_t data)
{
bus_write (addr | 0x80, data); // Write address = address | 0x80
}
SPI는 통신을 통해 데이터를 Write 할려면, CS Pin을 내려준 다음 Address에 MSB에 1로 set 해야만
데이터를 쓸 수 있다. write_reg함수는 or연산을 통해 MSB에 1로 set해주고 bus_write 는 실제 SPI 통신한다.
아래 파형은 0x00에 0x55 값을 넣었을 시 출력 되는 파형이다.
SPI Read timing
실제 코드 구현
uint8_t bus_read (int address)
{
uint8_t value;
int dummy = 0x00;
GPIOC->BSRR = CS_Pin << 16;
HAL_SPI_Transmit (&hspi3, (uint8_t*) &address, 1, 1000); //Command Phase
HAL_SPI_TransmitReceive (&hspi3, (uint8_t*) &dummy, &value, 1, 1000); // Data Phase
GPIOC->BSRR = CS_Pin;
return value;
}
uint8_t read_reg (uint8_t addr)
{
uint8_t data;
data = bus_read (addr & 0x7F);
return data;
}
SPI 통신을 통해 데이터를 Read 할려면 Write와 반대로 MSB를 0으로 set 해야 한다.
read_reg 함수는 arg 통해 받아온 address를 and 연산을 통해 MSB를 0으로 set 한다.
bus_read는 실제 SPI 통신을 통해 데이터를 읽기 위해 구현한 함수이다.
아래 파형은 Address 에 0x55를 쓴 다음 read_reg를 호출하여 읽어 오는 파형이다.
I2C 타이밍
코드 구현
void wrSensorReg16_8 (uint16_t tx_addr, unsigned char rx_buf)
{
if(HAL_I2C_Mem_Write (&hi2c1, 0x78, tx_addr, 2, &rx_buf, 1, 1000) != HAL_OK)
{
#ifdef DEBUG
printf("I2c Write Problem \n\r");
#endif
}
HAL_Delay (1);
}
void rdSensorReg16_8 (uint16_t tx_addr, uint8_t* rx_buf)
{
if((HAL_I2C_Mem_Read(&hi2c1, 0x78, tx_addr, 2, rx_buf, 1, 1000))!= HAL_OK)
{
#ifdef DEBUG
printf("I2c Read Problem \n\r");
#endif
}
HAL_Delay (1);
}
I2C는 SPI와 다르게 MSB가 아닌 LSB값이 0이냐 1이냐를 확인하여 Read Address 인지 Write Address인지 판단한다.
앞서 SPI는 코드에서 and or 연산을 통해 set 해주었지만 I2C는 따로 set 해줄 필요 없이 I2C API 함수 안에서 자동으로 set 한다.
실제 HAL_I2C_Mem_Read(&hi2c1,0x78,tx_addr,2, rx_buf,1,1000); 실행 후 찍은 파형
앞서 올린 데이터시트 타이밍대로 자동으로 0x79가 되어 데이터 값을 읽어 온다.
다만 주의할 점은 Cortex M4로 할 경우 i2c read or Write 후 에는 Delay를 줘야 Camera가 i2c 처리할
시간을 줘야한다.
실제 Delay를 추가한 코드
int wrSensorRegs16_8 (const struct sensor_reg reglist[])
{
unsigned int reg_addr = 0;
unsigned char reg_val = 0;
const struct sensor_reg *next = reglist;
while ((reg_addr != 0xffff) | (reg_val != 0xff))
{
reg_addr = next->reg;
reg_val = next->val;
if((HAL_I2C_Mem_Write(&hi2c1, 0x78, reg_addr, 2, ®_val, 1, 1000))!= HAL_OK)
{
#ifdef DEBUG
printf("I2c Write Problem \n\r");
#endif
}
next++;
HAL_Delay (1); //없을 시 log 창에 I2c Write Problem 문구를 볼 수 있다.
}
return 1;
}
'Firmware > stm32' 카테고리의 다른 글
OV5642_LWIP_RTOS Project -3(최종 구현 및 디버깅) (0) | 2020.05.31 |
---|---|
OV5642_LWIP_RTOS Project -2(Camera API) (0) | 2020.04.24 |
OV5642_LWIP_RTOS Project -1(Netconn_write 호출 시 문제) (0) | 2020.04.23 |
OV5642_LWIP_RTOS Project -1(osThreadSetPriority 문제) (0) | 2020.04.17 |
OV5642_LWIP_RTOS Project -1 (0) | 2020.04.12 |