/* Includes ------------------------------------------------------------------*/ #include "ov2640.h" #include "nrf_drv_gpiote.h" #include "app_scheduler.h" #include "user_twim.h" #include "app_timer.h" static custome_event ov2640_event; static void Set_Ov2640_Queue(OV2640_QUEUE_TYPE type); static ov2640_work_e ov2640_work = OV2640_WORK_RST; APP_TIMER_DEF(ov2640_timer_id); static uint32_t ov2640_timer_tick = 0; static bool ov2640_timer_end = true; static bool ov2640_timer_stat = false; //TWI传输完成标志 static volatile bool m_xfer_done = false; //TWI传输超时标志 static volatile bool m_xfer_timeout = false; static uint8_t OV2640_ReadReg(uint16_t Addr); static ret_code_t OV2640_WriteReg(uint16_t Addr, uint8_t Data); /** @addtogroup * @{ */ /** @addtogroup DCMI_Camera * @{ */ /* Exported types ------------------------------------------------------------*/ /* Camera devices enumeration */ /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ const unsigned char OV2640_JPEG_INIT[][2]= { 0xff, 0x00, 0x2c, 0xff, 0x2e, 0xdf, 0xff, 0x01, 0x3c, 0x32, 0x11, 0x00, 0x09, 0x02, 0x04, 0x28, 0x13, 0xe5, 0x14, 0x48, 0x2c, 0x0c, 0x33, 0x78, 0x3a, 0x33, 0x3b, 0xfB, 0x3e, 0x00, 0x43, 0x11, 0x16, 0x10, 0x39, 0x92, 0x35, 0xda, 0x22, 0x1a, 0x37, 0xc3, 0x23, 0x00, 0x34, 0xc0, 0x36, 0x1a, 0x06, 0x88, 0x07, 0xc0, 0x0d, 0x87, 0x0e, 0x41, 0x4c, 0x00, 0x48, 0x00, 0x5B, 0x00, 0x42, 0x03, 0x4a, 0x81, 0x21, 0x99, 0x24, 0x40, 0x25, 0x38, 0x26, 0x82, 0x5c, 0x00, 0x63, 0x00, 0x61, 0x70, 0x62, 0x80, 0x7c, 0x05, 0x20, 0x80, 0x28, 0x30, 0x6c, 0x00, 0x6d, 0x80, 0x6e, 0x00, 0x70, 0x02, 0x71, 0x94, 0x73, 0xc1, 0x12, 0x40,//0x40 0x17, 0x11, 0x18, 0x43, 0x19, 0x00, 0x1a, 0x4b, 0x32, 0x09, 0x37, 0xc0, 0x4f, 0x60, 0x50, 0xa8, 0x6d, 0x00, 0x3d, 0x38, 0x46, 0x3f, 0x4f, 0x60, 0x0c, 0x3c, 0xff, 0x00, 0xe5, 0x7f, 0xf9, 0xc0, 0x41, 0x24, 0xe0, 0x14, 0x76, 0xff, 0x33, 0xa0, 0x42, 0x20, 0x43, 0x18, 0x4c, 0x00, 0x87, 0xd5, 0x88, 0x3f, 0xd7, 0x03, 0xd9, 0x10, 0xd3, 0x82, 0xc8, 0x08, 0xc9, 0x80, 0x7c, 0x00, 0x7d, 0x00, 0x7c, 0x03, 0x7d, 0x48, 0x7d, 0x48, 0x7c, 0x08, 0x7d, 0x20, 0x7d, 0x10, 0x7d, 0x0e, 0x90, 0x00, 0x91, 0x0e, 0x91, 0x1a, 0x91, 0x31, 0x91, 0x5a, 0x91, 0x69, 0x91, 0x75, 0x91, 0x7e, 0x91, 0x88, 0x91, 0x8f, 0x91, 0x96, 0x91, 0xa3, 0x91, 0xaf, 0x91, 0xc4, 0x91, 0xd7, 0x91, 0xe8, 0x91, 0x20, 0x92, 0x00, 0x93, 0x06, 0x93, 0xe3, 0x93, 0x05, 0x93, 0x05, 0x93, 0x00, 0x93, 0x04, 0x93, 0x00, 0x93, 0x00, 0x93, 0x00, 0x93, 0x00, 0x93, 0x00, 0x93, 0x00, 0x93, 0x00, 0x96, 0x00, 0x97, 0x08, 0x97, 0x19, 0x97, 0x02, 0x97, 0x0c, 0x97, 0x24, 0x97, 0x30, 0x97, 0x28, 0x97, 0x26, 0x97, 0x02, 0x97, 0x98, 0x97, 0x80, 0x97, 0x00, 0x97, 0x00, 0xc3, 0xed, 0xa4, 0x00, 0xa8, 0x00, 0xc5, 0x11, 0xc6, 0x51, 0xbf, 0x80, 0xc7, 0x10, 0xb6, 0x66, 0xb8, 0xA5, 0xb7, 0x64, 0xb9, 0x7C, 0xb3, 0xaf, 0xb4, 0x97, 0xb5, 0xFF, 0xb0, 0xC5, 0xb1, 0x94, 0xb2, 0x0f, 0xc4, 0x5c, 0xc0, 0x64, 0xc1, 0x4B, 0x8c, 0x00, 0x86, 0x3D, 0x50, 0x00, 0x51, 0xC8, 0x52, 0x96, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x5a, 0xC8, 0x5b, 0x96, 0x5c, 0x00, 0xd3, 0x7f, 0xc3, 0xed, 0x7f, 0x00, 0xda, 0x00, 0xe5, 0x1f, 0xe1, 0x67, 0xe0, 0x00, 0xdd, 0x7f, 0x05, 0x00, 0x12, 0x40,//0x40 0xd3, 0x7f, 0xc0, 0x16, 0xC1, 0x12, 0x8c, 0x00, 0x86, 0x3d, 0x50, 0x00, 0x51, 0x2C, 0x52, 0x24, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x5A, 0x2c, 0x5b, 0x24, 0x5c, 0x00, }; const unsigned char OV2640_YUV422[][2]= { 0xFF, 0x00, 0x05, 0x00, 0xDA, 0x10, 0xD7, 0x03, 0xDF, 0x00, 0x33, 0x80, 0x3C, 0x40, 0xe1, 0x77, 0x00, 0x00, }; const unsigned char OV2640_JPEG[][2]= { 0xe0, 0x14, 0xe1, 0x77, 0xe5, 0x1f, 0xd7, 0x03, 0xda, 0x10, 0xe0, 0x00, 0xFF, 0x01, 0x04, 0x08, }; /* JPG 320x240 */ const unsigned char OV2640_800x600_JPEG[][2]= { {0xff, 0x01}, {0x11, 0x01}, {0x12, 0x00}, // Bit[6:4]: Resolution selection//0x02为彩条 {0x17, 0x11}, // HREFST[10:3] {0x18, 0x75}, // HREFEND[10:3] {0x32, 0x36}, // Bit[5:3]: HREFEND[2:0]; Bit[2:0]: HREFST[2:0] {0x19, 0x01}, // VSTRT[9:2] {0x1a, 0x97}, // VEND[9:2] {0x03, 0x0f}, // Bit[3:2]: VEND[1:0]; Bit[1:0]: VSTRT[1:0] {0x37, 0x40}, {0x4f, 0xbb}, {0x50, 0x9c}, {0x5a, 0x57}, {0x6d, 0x80}, {0x3d, 0x34}, {0x39, 0x02}, {0x35, 0x88}, {0x22, 0x0a}, {0x37, 0x40}, {0x34, 0xa0}, {0x06, 0x02}, {0x0d, 0xb7}, {0x0e, 0x01}, //////////////// /* //176*144 0xff, 0x00, 0xc0, 0xC8, 0xc1, 0x96, 0x8c, 0x00, 0x86, 0x3D, 0x50, 0x9B, 0x51, 0x90, 0x52, 0x2C, 0x53, 0x00, 0x54, 0x00, 0x55, 0x88, 0x5a, 0x2C, 0x5b, 0x24, 0x5c, 0x00, 0xd3, 0x7F, //////////// */ /* //////////////// //320*240 0xff, 0x00, 0xe0, 0x04, 0xc0, 0xc8, 0xc1, 0x96, 0x86, 0x3d, 0x50, 0x92, 0x51, 0x90, 0x52, 0x2c, 0x53, 0x00, 0x54, 0x00, 0x55, 0x88, 0x57, 0x00, 0x5a, 0x50, 0x5b, 0x3c, 0x5c, 0x00, 0xd3, 0x7F, 0xe0, 0x00, /////////////////// */ /* 0xff, 0x00, 0xe0, 0x04, 0xc0, 0xc8, 0xc1, 0x96, 0x86, 0x35, 0x50, 0x92, 0x51, 0x90, 0x52, 0x2c, 0x53, 0x00, 0x54, 0x00, 0x55, 0x88, 0x57, 0x00, 0x5a, 0x58, 0x5b, 0x48, 0x5c, 0x00, 0xd3, 0x08, 0xe0, 0x00 */ /* //640*480 0xff, 0x00, 0xe0, 0x04, 0xc0, 0xc8, 0xc1, 0x96, 0x86, 0x3d, 0x50, 0x89, 0x51, 0x90, 0x52, 0x2c, 0x53, 0x00, 0x54, 0x00, 0x55, 0x88, 0x57, 0x00, 0x5a, 0xa0, 0x5b, 0x78, 0x5c, 0x00, 0xd3, 0x04, 0xe0, 0x00 */ ///////////////////// //800*600 0xff, 0x00, 0xe0, 0x04, 0xc0, 0xc8, 0xc1, 0x96, 0x86, 0x35, 0x50, 0x89, 0x51, 0x90, 0x52, 0x2c, 0x53, 0x00, 0x54, 0x00, 0x55, 0x88, 0x57, 0x00, 0x5a, 0xc8, 0x5b, 0x96, 0x5c, 0x00, 0xd3, 0x02, 0xe0, 0x00 /* //1280*1024 0xff, 0x00, 0xe0, 0x04, 0xc0, 0xc8, 0xc1, 0x96, 0x86, 0x3d, 0x50, 0x00, 0x51, 0x90, 0x52, 0x2c, 0x53, 0x00, 0x54, 0x00, 0x55, 0x88, 0x57, 0x00, 0x5a, 0x40, 0x5b, 0xf0, 0x5c, 0x01, 0xd3, 0x02, 0xe0, 0x00 */ /* ///////////////////// //1600*1200 0xff, 0x00, 0xe0, 0x04, 0xc0, 0xc8, 0xc1, 0x96, 0x86, 0x3d, 0x50, 0x00, 0x51, 0x90, 0x52, 0x2c, 0x53, 0x00, 0x54, 0x00, 0x55, 0x88, 0x57, 0x00, 0x5a, 0x90, 0x5b, 0x2C, 0x5c, 0x05,//bit2->1;bit[1:0]->1 0xd3, 0x02, 0xe0, 0x00 ///////////////////// */ /* //1024*768 0xff, 0x00, 0xc0, 0xC8, 0xc1, 0x96, 0x8c, 0x00, 0x86, 0x3D, 0x50, 0x00, 0x51, 0x90, 0x52, 0x2C, 0x53, 0x00, 0x54, 0x00, 0x55, 0x88, 0x5a, 0x00, 0x5b, 0xC0, 0x5c, 0x01, 0xd3, 0x02 */ }; /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ //启动毫秒计时应用定时器。启动后,即开始产生毫秒计时,也就是提供了一个以毫秒为单位的计时基准 static void ov2640_timers_stop(void) { if(ov2640_timer_stat==true) { ret_code_t err_code = app_timer_stop(ov2640_timer_id); APP_ERROR_CHECK(err_code); ov2640_timer_stat=false; } } //启动毫秒计时应用定时器。启动后,即开始产生毫秒计时,也就是提供了一个以毫秒为单位的计时基准 static void ov2640_timers_start(uint32_t ms) { ret_code_t err_code = app_timer_start(ov2640_timer_id, APP_TIMER_TICKS(ms), NULL); APP_ERROR_CHECK(err_code); ov2640_timer_stat=true; } static void ov2640_timers_work(uint32_t ms) { ov2640_timers_stop(); if(ov2640_timer_stat==false) { if(ms>APP_TIMER_SAFE_WINDOW_MS) { ov2640_timers_start(APP_TIMER_SAFE_WINDOW_MS); ov2640_timer_end=false; ov2640_timer_tick=ms-APP_TIMER_SAFE_WINDOW_MS; } else{ ov2640_timers_start(ms); ov2640_timer_end=true; ov2640_timer_tick=0; } } } //ov2640定时器回调 static void ov2640_timers_handler(void * p_context) { UNUSED_PARAMETER(p_context); ov2640_timer_stat=false; if(ov2640_timer_end==true) { Set_Ov2640_Queue(OV2640_QUEUE_TIME); } else{ ov2640_timers_work(ov2640_timer_tick); } } /**@brief Function for the Timer initialization. * * @details Initializes the timer module. */ void ov2640_timers_init(void) { // Initialize timer module, making it use the scheduler // ret_code_t err_code = app_timer_init(); // APP_ERROR_CHECK(err_code); //创建一个应用定时器,产生秒计时。模式:周期性应用定时器,注册应用定时器事件句柄 ret_code_t err_code = app_timer_create(&ov2640_timer_id, APP_TIMER_MODE_SINGLE_SHOT, ov2640_timers_handler); APP_ERROR_CHECK(err_code); } /** * @brief Initializes the hardware resources (I2C and GPIO) used to configure * the OV2640 camera. * @param None * @retval None */ void OV2640_Gpio_Init(void) { nrf_gpio_cfg_input(CAM_D0_PIN,NRF_GPIO_PIN_NOPULL); nrf_gpio_cfg_input(CAM_D1_PIN,NRF_GPIO_PIN_NOPULL); nrf_gpio_cfg_input(CAM_D2_PIN,NRF_GPIO_PIN_NOPULL); nrf_gpio_cfg_input(CAM_D3_PIN,NRF_GPIO_PIN_NOPULL); nrf_gpio_cfg_input(CAM_D4_PIN,NRF_GPIO_PIN_NOPULL); nrf_gpio_cfg_input(CAM_D5_PIN,NRF_GPIO_PIN_NOPULL); nrf_gpio_cfg_input(CAM_D6_PIN,NRF_GPIO_PIN_NOPULL); nrf_gpio_cfg_input(CAM_D7_PIN,NRF_GPIO_PIN_NOPULL); } void OV2640_CaptureGpioInit(nrf_drv_gpiote_in_config_t *config,nrfx_gpiote_evt_handler_t evt_handler) { ret_code_t err_code; //配置引脚为GPIOTE输入 config->pull=NRF_GPIO_PIN_PULLUP; err_code = nrf_drv_gpiote_in_init(CAM_PCLK_PIN, config, evt_handler); APP_ERROR_CHECK(err_code); err_code = nrf_drv_gpiote_in_init(CAM_VSYNC_PIN, config, evt_handler); APP_ERROR_CHECK(err_code); err_code = nrf_drv_gpiote_in_init(CAM_HREF_PIN, config, evt_handler); APP_ERROR_CHECK(err_code); //使能事件模式 nrf_drv_gpiote_in_event_enable(CAM_PCLK_PIN,true); nrf_drv_gpiote_in_event_enable(CAM_VSYNC_PIN,true); nrf_drv_gpiote_in_event_enable(CAM_HREF_PIN,true); } static void ov2640_i2s_done(void) { m_xfer_done = true; } static void ov2640_i2s_timeout(void) { m_xfer_timeout = true; } void OV2640_i2s_init(void) { twim0_init(ov2640_i2s_done, ov2640_i2s_timeout); } void OV2640_i2s_uninit(void) { twim0_uinit(); } /** * @brief Resets the OV2640 camera. * @param None * @retval None */ static void OV2640_Reset(void) { OV2640_WriteReg(OV2640_DSP_RA_DLMT, 0x01); OV2640_WriteReg(OV2640_SENSOR_COM7, 0x80); } /** * @brief Reads the OV2640 Manufacturer identifier. * @param OV2640ID: Pointer to the OV2640 Manufacturer identifier * @retval None */ static void OV2640_ReadID(OV2640_IDTypeDef *OV2640ID) { OV2640_WriteReg(OV2640_DSP_RA_DLMT, 0x01); OV2640ID->Manufacturer_ID1 = OV2640_ReadReg(OV2640_SENSOR_MIDH); OV2640ID->Manufacturer_ID2 = OV2640_ReadReg(OV2640_SENSOR_MIDL); OV2640ID->PIDH = OV2640_ReadReg(OV2640_SENSOR_PIDH); OV2640ID->PIDL = OV2640_ReadReg(OV2640_SENSOR_PIDL); } static void ov2640_cmd_jpeg_init(void) { /* Initialize OV2640 */ for(int i=0; i<(sizeof(OV2640_JPEG_INIT)/2); i++) { OV2640_WriteReg(OV2640_JPEG_INIT[i][0], OV2640_JPEG_INIT[i][1]); nrf_delay_us(100); } } static void ov2640_cmd_yuv422(void) { /* Set to output YUV422 */ for(int i=0; i<(sizeof(OV2640_YUV422)/2); i++) { OV2640_WriteReg(OV2640_YUV422[i][0], OV2640_YUV422[i][1]); nrf_delay_us(100); } } static void ov2640_cmd_jpeg(void) { OV2640_WriteReg(0xff, 0x01); OV2640_WriteReg(0x15, 0x00); /* Set to output JPEG */ for(int i=0; i<(sizeof(OV2640_JPEG)/2); i++) { OV2640_WriteReg(OV2640_JPEG[i][0], OV2640_JPEG[i][1]); nrf_delay_us(100); } } /** * @brief Configures the OV2640 camera in JPEG mode. * @param JPEGImageSize: JPEG image size * @retval None */ void OV2640_JPEGConfig(void) { for(int i=0; i<(sizeof(OV2640_800x600_JPEG)/2); i++) { OV2640_WriteReg(OV2640_800x600_JPEG[i][0], OV2640_800x600_JPEG[i][1]); nrf_delay_us(100); } } /** * @brief Configures the OV2640 camera brightness. * @param Brightness: Brightness value, where Brightness can be: * 0x40 for Brightness +2, * 0x30 for Brightness +1, * 0x20 for Brightness 0, * 0x10 for Brightness -1, * 0x00 for Brightness -2, * @retval None */ void OV2640_BrightnessConfig(uint8_t Brightness) { OV2640_WriteReg(0xff, 0x00); OV2640_WriteReg(0x7c, 0x00); OV2640_WriteReg(0x7d, 0x04); OV2640_WriteReg(0x7c, 0x09); OV2640_WriteReg(0x7d, Brightness); OV2640_WriteReg(0x7d, 0x00); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const static uint8_t OV2640_AUTOEXPOSURE_LEVEL0[]= { 0xFF, 0x01, 0xff, 0x24, 0x20, 0xff, 0x25, 0x18, 0xff, 0x26, 0x60, 0xff, 0x00, 0x00, 0x00 }; const static uint8_t OV2640_AUTOEXPOSURE_LEVEL1[]= { 0xFF, 0x01, 0xff, 0x24, 0x34, 0xff, 0x25, 0x1c, 0xff, 0x26, 0x70, 0xff, 0x00, 0x00, 0x00 }; const static uint8_t OV2640_AUTOEXPOSURE_LEVEL2[]= { 0xFF, 0x01, 0xff, 0x24, 0x3e, 0xff, 0x25, 0x38, 0xff, 0x26, 0x81, 0xff, 0x00, 0x00, 0x00 }; const static uint8_t OV2640_AUTOEXPOSURE_LEVEL3[]= { 0xFF, 0x01, 0xff, 0x24, 0x48, 0xff, 0x25, 0x40, 0xff, 0x26, 0x81, 0xff, 0x00, 0x00, 0x00 }; const static uint8_t OV2640_AUTOEXPOSURE_LEVEL4[]= { 0xFF, 0x01, 0xff, 0x24, 0x58, 0xff, 0x25, 0x50, 0xff, 0x26, 0x92, 0xff, 0x00, 0x00, 0x00 }; void SCCB_WriteRegs(const uint8_t* pbuf) { while(1) { if((*pbuf == 0) && (*(pbuf + 1) == 0)) { break; } else { OV2640_WriteReg(*pbuf, *(pbuf+1)); pbuf += 2; } } } void OV2640_AutoExposure(uint8_t level) { switch(level) { case 0: SCCB_WriteRegs(OV2640_AUTOEXPOSURE_LEVEL0); break; case 1: SCCB_WriteRegs(OV2640_AUTOEXPOSURE_LEVEL1); break; case 2: SCCB_WriteRegs(OV2640_AUTOEXPOSURE_LEVEL2); break; case 3: SCCB_WriteRegs(OV2640_AUTOEXPOSURE_LEVEL3); break; case 4: SCCB_WriteRegs(OV2640_AUTOEXPOSURE_LEVEL4); break; default: SCCB_WriteRegs(OV2640_AUTOEXPOSURE_LEVEL0); break; } } /** * @brief Configures the OV2640 camera Black and white mode. * @param BlackWhite: BlackWhite value, where BlackWhite can be: * 0x18 for B&W, * 0x40 for Negative, * 0x58 for B&W negative, * 0x00 for Normal, * @retval None */ void OV2640_BandWConfig(uint8_t BlackWhite) { OV2640_WriteReg(0xff, 0x00); OV2640_WriteReg(0x7c, 0x00); OV2640_WriteReg(0x7d, BlackWhite); OV2640_WriteReg(0x7c, 0x05); OV2640_WriteReg(0x7d, 0x80); OV2640_WriteReg(0x7d, 0x80); } /** * @brief Configures the OV2640 camera color effects. * @param value1: Color effects value1 * @param value2: Color effects value2 * where value1 and value2 can be: * value1 = 0x40, value2 = 0xa6 for Antique, * value1 = 0xa0, value2 = 0x40 for Bluish, * value1 = 0x40, value2 = 0x40 for Greenish, * value1 = 0x40, value2 = 0xc0 for Reddish, * @retval None */ void OV2640_ColorEffectsConfig(uint8_t value1, uint8_t value2) { OV2640_WriteReg(0xff, 0x00); OV2640_WriteReg(0x7c, 0x00); OV2640_WriteReg(0x7d, 0x18); OV2640_WriteReg(0x7c, 0x05); OV2640_WriteReg(0x7d, value1); OV2640_WriteReg(0x7d, value2); } /** * @brief Configures the OV2640 camera contrast. * @param value1: Contrast value1 * @param value2: Contrast value2 * where value1 and value2 can be: * value1 = 0x28, value2 = 0x0c for Contrast +2, * value1 = 0x24, value2 = 0x16 for Contrast +1, * value1 = 0x20, value2 = 0x20 for Contrast 0, * value1 = 0x1c, value2 = 0x2a for Contrast -1, * value1 = 0x18, value2 = 0x34 for Contrast -2, * @retval None */ void OV2640_ContrastConfig(uint8_t value1, uint8_t value2) { OV2640_WriteReg(0xff, 0x00); OV2640_WriteReg(0x7c, 0x00); OV2640_WriteReg(0x7d, 0x04); OV2640_WriteReg(0x7c, 0x07); OV2640_WriteReg(0x7d, 0x20); OV2640_WriteReg(0x7d, value1); OV2640_WriteReg(0x7d, value2); OV2640_WriteReg(0x7d, 0x06); } /** * @brief Writes a byte at a specific Camera register * @param Addr: OV2640 register address. * @param Data: Data to be written to the specific register * @retval 0x00 if write operation is OK. * 0xFF if timeout condition occured (device not connected or bus error). */ static ret_code_t OV2640_WriteReg(uint16_t Addr, uint8_t Data) { uint8_t sdata[3] = {0}; memcpy(sdata, &Addr, 2); sdata[2] = Data; m_xfer_done = false; nrf_drv_twim0_tx(OV2640_DEVICE_WRITE_ADDRESS, sdata, 3, false); while((m_xfer_done == false) && (m_xfer_timeout == false)) { } if(m_xfer_done == false) { return NRF_ERROR_TIMEOUT; } /* If operation is OK, return 0 */ return NRF_SUCCESS; } /** * @brief Reads a byte from a specific Camera register * @param Addr: OV2640 register address. * @retval data read from the specific register or 0xFF if timeout condition * occured. */ static uint8_t OV2640_ReadReg(uint16_t Addr) { uint8_t recv_data = 0; uint8_t sdata[2] = {0}; memcpy(sdata, &Addr, 2); m_xfer_done = false; nrf_drv_twim0_tx(OV2640_DEVICE_WRITE_ADDRESS, sdata, 2, true); while((m_xfer_done == false) && (m_xfer_timeout == false)) { } if(m_xfer_done == false) { return NRF_ERROR_TIMEOUT; } nrf_drv_twim0_rx(OV2640_DEVICE_WRITE_ADDRESS, &recv_data, 1); while((m_xfer_done == false) && (m_xfer_timeout == false)) { } if(m_xfer_done == false) { return NRF_ERROR_TIMEOUT; } /* return the read data */ return recv_data; } static uint8_t get_ov2640_data(void) { uint8_t data = 0; uint8_t temp = nrf_gpio_pin_read(CAM_D0_PIN); data <<= 1; data |= temp; temp = nrf_gpio_pin_read(CAM_D1_PIN); data <<= 1; data |= temp; temp = nrf_gpio_pin_read(CAM_D2_PIN); data <<= 1; data |= temp; temp = nrf_gpio_pin_read(CAM_D3_PIN); data <<= 1; data |= temp; temp = nrf_gpio_pin_read(CAM_D4_PIN); data <<= 1; data |= temp; temp = nrf_gpio_pin_read(CAM_D5_PIN); data <<= 1; data |= temp; temp = nrf_gpio_pin_read(CAM_D6_PIN); data <<= 1; data |= temp; temp = nrf_gpio_pin_read(CAM_D7_PIN); data <<= 1; data |= temp; return data; } //void ov2640_init(void) //{ // OV2640_ReadID(&OV2640_Camera_ID); //读取OV2640ID,测试硬件,依次为:0x7F,0xA2,0x26,0x42 // OV2640_JPEGConfig(JPEG_320x240); //配置OV2640输出320*240像素的JPG图片 // // OV2640_BrightnessConfig(0x20); // OV2640_AutoExposure(2); //} static void ov2640_pro(void) { switch(ov2640_work) { case OV2640_WORK_I2C_INIT:{ OV2640_i2s_init(); ov2640_work = OV2640_WORK_RST; ov2640_timers_work(1); }break; case OV2640_WORK_RST:{ OV2640_Reset(); ov2640_work = OV2640_WORK_JPEG_INIT; ov2640_timers_work(100); }break; case OV2640_WORK_JPEG_INIT:{ ov2640_cmd_jpeg_init(); ov2640_work = OV2640_WORK_YUV422; ov2640_timers_work(1); }break; case OV2640_WORK_YUV422:{ ov2640_cmd_yuv422(); ov2640_work = OV2640_WORK_JPEG; ov2640_timers_work(1); }break; case OV2640_WORK_JPEG:{ ov2640_cmd_jpeg(); ov2640_work = OV2640_WORK_JPEGCONFIG; ov2640_timers_work(1); }break; case OV2640_WORK_JPEGCONFIG:{ OV2640_JPEGConfig(); ov2640_work = OV2640_WORK_BNCONFIG; ov2640_timers_work(1); }break; case OV2640_WORK_BNCONFIG:{ OV2640_BrightnessConfig(0x20); ov2640_work = OV2640_WORK_AUTOEXP; ov2640_timers_work(1); }break; case OV2640_WORK_AUTOEXP:{ OV2640_AutoExposure(2); ov2640_work = OV2640_WORK_I2C_UNINIT; ov2640_timers_work(1); }break; case OV2640_WORK_VSYNC:{ }break; case OV2640_WORK_PCLK:{ }break; case OV2640_WORK_HREF:{ }break; case OV2640_WORK_I2C_UNINIT:{ OV2640_i2s_uninit(); ov2640_work = OV2640_WORK_I2C_INIT; }break; } } static void ov2640_queue(void *p_event_data, uint16_t event_size) { custome_event *evt = (custome_event*)p_event_data; if((ov2640_event.flag & (1 << OV2640_QUEUE_INT)) != 0) { ov2640_pro(); ov2640_event.flag &= (~(1 << OV2640_QUEUE_INT)); } if((ov2640_event.flag & (1 << OV2640_QUEUE_TIME)) != 0) { ov2640_pro(); ov2640_event.flag &= (~(1 << OV2640_QUEUE_TIME)); } } static void Set_Ov2640_Queue(OV2640_QUEUE_TYPE type) { ov2640_event.flag |= (1<