ESP32CAM自带OV2640.硬件:esp32cam,ov2640.系统环境:arduino+esp32;
图1为2640时序图
esp32cam驱动ov摄像头案例很多,此文为读取OV2640的ID实例.代码较为简洁.方便理解.当然去掉了众多冗余代码,难免使得代码通用性,完整性较为不理想.仅为方便学习理解OV时序.后期部分包括读取像素显示于显示屏,可参考前一篇文章,读取像素显示在网络可参考arduino或esp32自带实例.不打算继续深入.因为写到这步,已经完成整个驱动camera的80%.后面的部分EPS32自带的实例,网络上案例较多,可自行参考.
图2为串口输出的ID值
以下为代码:混杂了esp32与arduino语法.
#include "driver/i2c.h" #include "esp_camera.h" #include "sdkconfig.h" #include <freertos/task.h> #include <stdio.h>
#define PWDN_GPIO_NUM GPIO_NUM_32 //(输入)(掉电/省电模式,高电平有效) #define RESET -1 //(系统复位)(低电平有效) #define XCLK_GPIO_NUM GPIO_NUM_0 //(外部时钟输入端口,可接外部晶振) #define SCL_PIN GPIO_NUM_27 /*!< gpio number for I2C master clock */ #define SDA_PIN GPIO_NUM_26 /*!< gpio number for I2C master data */ #define VSYNC GPIO_NUM_25 //帧同步信号 #define HREF_GPIO_NUM GPIO_NUM_23 //行同步信号 #define PCLK_GPIO_NUM GPIO_NUM_22 //像素同步时钟输出信号
#define Y9_GPIO_NUM 35 #define Y8_GPIO_NUM 34 #define Y7_GPIO_NUM 39 #define Y6_GPIO_NUM 36 #define Y5_GPIO_NUM 21 #define Y4_GPIO_NUM 19 #define Y3_GPIO_NUM 18 #define Y2_GPIO_NUM 3
#define ESP_SLAVE_ADDR 0x30 #define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */ #define READ_BIT I2C_MASTER_READ /*!< I2C master read */ #define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/ #define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */ #define ACK_VAL I2C_MASTER_ACK /*!< I2C ack value */ #define NACK_VAL I2C_MASTER_NACK /*!< I2C nack value */
static const char *TAG = "sccb"; #define LITTLETOBIG(x) ((x << 8) | (x >> 8))
int SCCB_Init(void) { ESP_LOGI(TAG, "pin_sda %d pin_scl %d", pin_sda, pin_scl); i2c_config_t conf; memset(&conf, 0, sizeof(i2c_config_t)); conf.mode = I2C_MODE_MASTER; conf.sda_io_num = GPIO_NUM_26; conf.sda_pullup_en = GPIO_PULLUP_ENABLE; conf.scl_io_num = GPIO_NUM_27; conf.scl_pullup_en = GPIO_PULLUP_ENABLE; conf.master.clk_speed = 100000;
i2c_param_config(I2C_NUM_1, &conf); i2c_driver_install(I2C_NUM_1, conf.mode, 0, 0, 0);
return 0; }
int32_t camera_out_clock(void) {
ledc_timer_config_t timer_conf; mer_conf.duty_resolution = LEDC_TIMER_1_BIT; timer_conf.freq_hz = 10000000; timer_conf.speed_mode = LEDC_LOW_SPEED_MODE; timer_conf.timer_num = LEDC_TIMER_0; ledc_timer_config(&timer_conf);
ledc_channel_config_t ch_conf; ch_conf.gpio_num = XCLK_GPIO_NUM; ch_conf.speed_mode = LEDC_LOW_SPEED_MODE; ch_conf.channel = LEDC_CHANNEL_0; ch_conf.intr_type = LEDC_INTR_DISABLE; ch_conf.timer_sel = LEDC_TIMER_0; ch_conf.duty = 1; ch_conf.hpoint = 0; ledc_channel_config(&ch_conf); }
void pwdn_reset_re(int pin_pwdn, int pin_reset) {
pinMode(pin_pwdn, OUTPUT);
delay(5);
digitalWrite(pin_pwdn, 1);
delay(5);
digitalWrite(pin_pwdn, 0);
delay(5);
//-----------------------------------------------
pinMode(pin_reset, OUTPUT);
delay(5);
digitalWrite(pin_reset, 0);
delay(5);
digitalWrite(pin_reset, 1);
delay(5); }
uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg) {
uint8_t data = 0;
esp_err_t ret = ESP_FAIL;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (slv_addr << 1) | WRITE_BIT, ACK_CHECK_EN);
i2c_master_write_byte(cmd, reg, ACK_CHECK_EN);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_NUM_1, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK)
return -1;
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (slv_addr << 1) | READ_BIT, ACK_CHECK_EN);
i2c_master_read_byte(cmd, &data, I2C_MASTER_NACK);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_NUM_1, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "SCCB_Read Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr,
reg, data, ret);
}
return data;
}
uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data)
{
esp_err_t ret = ESP_FAIL;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (slv_addr << 1) | WRITE_BIT, ACK_CHECK_EN);
i2c_master_write_byte(cmd, reg, ACK_CHECK_EN);
i2c_master_write_byte(cmd, data, ACK_CHECK_EN);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(I2C_NUM_1, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "SCCB_Write Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr,
reg, data, ret);
}
return ret == ESP_OK ? 0 : -1;
}
/*
void href_pclk_Y2_Y9_Init(void)
{
pinMode(PWDN_GPIO_NUM , OUTPUT);
pinMode(HREF_GPIO_NUM, OUTPUT);
pinMode(VSYNC, INPUT_PULLUP);
pinMode(Y2_GPIO_NUM, INPUT);
pinMode(Y3_GPIO_NUM, INPUT);
pinMode(Y4_GPIO_NUM, INPUT);
pinMode(Y5_GPIO_NUM, INPUT);
pinMode(Y6_GPIO_NUM, INPUT);
pinMode(Y7_GPIO_NUM, INPUT);
pinMode(Y8_GPIO_NUM, INPUT);
pinMode(Y9_GPIO_NUM, INPUT);
}
*/
void setup()
{
Serial.begin(115200);
camera_out_clock();
SCCB_Init();
pwdn_reset_re(PWDN_GPIO_NUM, RESET);
while(1){
SCCB_Write(0X30,0X12,0X01);
Serial.println(SCCB_Read(0X30,0x0A),HEX);
Serial.println(SCCB_Read(0X30,0x0B),HEX);
Serial.println(SCCB_Read(0X30,0x1C),HEX);
Serial.println(SCCB_Read(0X30,0x1D),HEX);
Serial.println("-----------------------------");
delay(5000);
}
/*
OV2640init()//ov2640寄存器初始化
href_pclk_Y2_Y9_Init();//将以上循环换成这个即可完成整个OV时序输出,后面的就只是将输出的图像装进屏幕或传至IP输出显示了.
*/
}
void loop()
{
}