I have to interface my STM32F401RE with an OV7670 camera module without external AL422. I followed some of the many tutorials for Arduino, and I was able to capture images using Arduino UNO. Unfortunately my requirements force me to use STM as board and to program it using the HAL library from ST. So my aim is to be able to capture an image on request, so I tried to adapt the code structure used for Arduino to my board and library but the results are quite frustrating because all I could get are messy noisy images, like these
At the moment what my code does is taking an image and send it via UART where a Java application is listening the COM port and shows the image. Some more details:
- I'm sure about the Java code correctness because if I send an image made of a single color it is perfectly shown;
- I set the camera using QQVGA resolution and YUV color mode, the register values are the same that can be found surfing a bit on the net;
- I tried both sending the image in stream, as in the first picture, and saving it in SRAM and then sending, second picture (there is a quite notable difference because the second case seems largely pure noise);
- At the moment the camera is fed with a 8MHz clock form MCO pin that according many users seems to work even if the datasheets states 10MHz as minimum;
- I played a bit with clock prescaling, but always striped messy images;
- Sender and receiver baud rates are correct.
I am almost sure that there is some problem in reading signals correctly according the camera timing but I really cannot spot the problem. In my current settings PCLK does not toggle during horizontal blanking. The main function to capture the image is the following (almost the same that can be found surfing Arduino Forum):
int camera_capture_image(uint8_t image_buffer[][2*COLS]) {
uint16_t hg = 120, wg = 320, lg2;
int num = 0;
uint8_t buf[320];
while(HAL_GPIO_ReadPin(VSYNC_PORT, VSYNC_PIN) == GPIO_PIN_RESET);
while(HAL_GPIO_ReadPin(VSYNC_PORT, VSYNC_PIN) == GPIO_PIN_SET);
while(hg--){
uint8_t*b=buf,*b2=buf;
lg2=wg/5;
while(lg2--){
while(HAL_GPIO_ReadPin(PCLK_PORT, PCLK_PIN) == GPIO_PIN_SET);
*b++=(uint8_t)GPIOC->IDR;
while(HAL_GPIO_ReadPin(PCLK_PORT, PCLK_PIN) == GPIO_PIN_RESET);//wait for high
while(HAL_GPIO_ReadPin(PCLK_PORT, PCLK_PIN) == GPIO_PIN_SET);//wait for low
*b++=(uint8_t)GPIOC->IDR;
while(HAL_GPIO_ReadPin(PCLK_PORT, PCLK_PIN) == GPIO_PIN_RESET);//wait for high
while(HAL_GPIO_ReadPin(PCLK_PORT, PCLK_PIN) == GPIO_PIN_SET);//wait for low
*b++=(uint8_t)GPIOC->IDR;
while(HAL_GPIO_ReadPin(PCLK_PORT, PCLK_PIN) == GPIO_PIN_RESET);//wait for high
while(HAL_GPIO_ReadPin(PCLK_PORT, PCLK_PIN) == GPIO_PIN_SET);//wait for low
*b++=(uint8_t)GPIOC->IDR;
while(HAL_GPIO_ReadPin(PCLK_PORT, PCLK_PIN) == GPIO_PIN_RESET);//wait for high
while(HAL_GPIO_ReadPin(PCLK_PORT, PCLK_PIN) == GPIO_PIN_SET);//wait for low
*b++=(uint8_t)GPIOC->IDR;
image_buffer[hg][lg2] = *b2++;
num++;
//HAL_UART_Transmit(&huart2, b2++, sizeof(b2), HAL_MAX_DELAY);
while(HAL_GPIO_ReadPin(PCLK_PORT, PCLK_PIN) == GPIO_PIN_RESET);//wait for high
}
/* Finish sending the remainder during blanking */
lg2=320-(wg/5);
while(lg2--) {
image_buffer[hg][lg2] = *b2++;
num++;
//HAL_UART_Transmit(&huart2, b2++, sizeof(b2), HAL_MAX_DELAY);
}
}
return num;
}
If you need any other detail I am ready to provide it.