赞
踩
初始化分析,首先定义一个camera_config_t类型的结构体变量,然后给结构中的成员赋值,再调用err = esp_camera_init(&camera_config);函数进行初始化,代码如下:
- esp_err_t err;
-
- camera_config_t camera_config = {
- .pin_pwdn = CAM_PWDN,
- .pin_reset = CAM_RET,
- .pin_xclk = CAM_XCLK,
- .pin_sscb_sda = CAM_SDA,
- .pin_sscb_scl = CAM_SCL,
-
- .pin_d7 = CAM_D7,
- .pin_d6 = CAM_D6,
- .pin_d5 = CAM_D5,
- .pin_d4 = CAM_D4,
- .pin_d3 = CAM_D3,
- .pin_d2 = CAM_D2,
- .pin_d1 = CAM_D1,
- .pin_d0 = CAM_D0,
- .pin_vsync = CAM_VSYNC,
- .pin_href = CAM_HSYNC,
- .pin_pclk = CAM_PCLK,
-
- //XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental)
- .xclk_freq_hz = 24000000,
- .ledc_timer = LEDC_TIMER_0,
- .ledc_channel = LEDC_CHANNEL_0,
- #ifdef CONFIG_CAMERA_JPEG_MODE
- .pixel_format = PIXFORMAT_JPEG, //YUV422,GRAYSCALE,RGB565,JPEG
- #else
- .pixel_format = PIXFORMAT_GRAYSCALE,
- #endif
- .frame_size = FRAMESIZE_QVGA, //QQVGA-UXGA Do not use sizes above QVGA when not JPEG
- .jpeg_quality = 12, //0-63 lower number means higher quality
- .fb_count = 2, //if more than one, i2s runs in continuous mode. Use only with JPEG
- .grab_mode = CAMERA_GRAB_WHEN_EMPTY//CAMERA_GRAB_LATEST. Sets when buffers should be filled
- };
- //initialize the camera
- err = esp_camera_init(&camera_config);
esp_camera_init()函数过程分析,调用cam_init()初始化camera外设;接着调用camera_probe()检测sensor是否存在,如果存在,则对senor进行初始化,包括硬件复位,通过i2c接口对寄存器初始化;接着调用cam_config(),设置窗口模式,初始化cam_obj结构,创建cam_task任务并启动;最后调用cam_start()使能vsync_pin的中断接收服务,vsync为帧同步信号。
- esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint16_t sensor_pid)
- {
- CAM_CHECK(NULL != config, "config pointer is invalid", ESP_ERR_INVALID_ARG);
- esp_err_t ret = ESP_OK;
-
- ret = ll_cam_set_sample_mode(cam_obj, (pixformat_t)config->pixel_format, config->xclk_freq_hz, sensor_pid);
-
- cam_obj->jpeg_mode = config->pixel_format == PIXFORMAT_JPEG;
- #if CONFIG_IDF_TARGET_ESP32
- cam_obj->psram_mode = false;
- #else
- cam_obj->psram_mode = (config->xclk_freq_hz == 16000000);
- #endif
- cam_obj->frame_cnt = config->fb_count;
- cam_obj->width = resolution[frame_size].width;
- cam_obj->height = resolution[frame_size].height;
-
- if(cam_obj->jpeg_mode){
- cam_obj->recv_size = cam_obj->width * cam_obj->height / 5;
- cam_obj->fb_size = cam_obj->recv_size;
- } else {
- cam_obj->recv_size = cam_obj->width * cam_obj->height * cam_obj->in_bytes_per_pixel;
- cam_obj->fb_size = cam_obj->width * cam_obj->height * cam_obj->fb_bytes_per_pixel;
- }
-
- ret = cam_dma_config(config);
- CAM_CHECK_GOTO(ret == ESP_OK, "cam_dma_config failed", err);
-
- cam_obj->event_queue = xQueueCreate(cam_obj->dma_half_buffer_cnt - 1, sizeof(cam_event_t));
- CAM_CHECK_GOTO(cam_obj->event_queue != NULL, "event_queue create failed", err);
-
- size_t frame_buffer_queue_len = cam_obj->frame_cnt;
- if (config->grab_mode == CAMERA_GRAB_LATEST && cam_obj->frame_cnt > 1) {
- frame_buffer_queue_len = cam_obj->frame_cnt - 1;
- }
- cam_obj->frame_buffer_queue = xQueueCreate(frame_buffer_queue_len, sizeof(camera_fb_t*));
- CAM_CHECK_GOTO(cam_obj->frame_buffer_queue != NULL, "frame_buffer_queue create failed", err);
-
- ret = ll_cam_init_isr(cam_obj);
- CAM_CHECK_GOTO(ret == ESP_OK, "cam intr alloc failed", err);
-
-
- #if CONFIG_CAMERA_CORE0
- xTaskCreatePinnedToCore(cam_task, "cam_task", 2048, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle, 0);
- #elif CONFIG_CAMERA_CORE1
- xTaskCreatePinnedToCore(cam_task, "cam_task", 2048, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle, 1);
- #else
- xTaskCreate(cam_task, "cam_task", 2048, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle);
- #endif
-
- ESP_LOGI(TAG, "cam config ok");
- return ESP_OK;
-
- err:
- cam_deinit();
- return ESP_FAIL;
- }
cam_config()中有一句代码设置是否使用PSRAM方式,如果是ESP32-S2处理器,xclk_freq_hz为16000000Hz,则使用PSRAM方式。
esp_camera_init()之后,sensor会不断的输出图像,cam_task任务会不断的被唤醒。
ESP32/8266技术交流QQ群:1018891543
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。