/** ****************************************************************************** * @file DCMI_Com.c * @author TMC Terminal Team * @version V1.0.0 * @date 06/21/2018 * @brief DCMI module. * ****************************************************************************** * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, TMC SHALL NOT BE HELD LIABLE FOR ANY * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * *

© COPYRIGHT 2016 TMC

******************************************************************************/ /* Includes ------------------------------------------------------------------*/ #include "global.h" volatile uint8_t gDCMICaptureFlag = 0; DCMI_HandleTypeDef gHandleDCMI; LLI_StructTypeDef dcmi_lli[37]; DMA_HandleTypeDef gHandleDMA; Camera_Info gciCameraInfo; //extern uint16_t Key_Action(); //extern uint8_t Key_Active(void); extern uint8_t gKeyAction; /*DCMI捕获结束回调函数*/ void TMC_DCMI_CpltCallback(DCMI_HandleTypeDef *hdcmi) { /*捕获标记置位*/ gDCMICaptureFlag = 1; // DMA_ClearITPendingBit(DMA_IT_TC7); DMA_Cmd(hdcmi->DMA_Handle->Instance, DISABLE); DCMI_CaptureCmd(DISABLE);/*关闭捕获*/ } void TMC_DCMI_ErrorCallback(DCMI_HandleTypeDef *hdcmi) { //while(1); // ResetChip(6); // JJJ_Prompt("TMC_DCMI_ErrorCallback\r\n"); } /** * @brief DMA SPI half transmit process complete callback. * @param hdma pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA module. * @retval None */ static void TMC_DCMI_DMATransmitCplt(DMA_HandleTypeDef *hdma) { DCMI_HandleTypeDef *hdcmi = (DCMI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; hdcmi->State = HAL_DCMI_STATE_READY; hdcmi->ErrorCode = HAL_DCMI_ERROR_NONE; DCMI_Cmd(DISABLE); TMC_DCMI_CpltCallback(hdcmi); } /** * @brief DMA DCMI communication error callback. * @param hdma pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA module. * @retval None */ static void TMC_DCMI_DMAError(DMA_HandleTypeDef *hdma) { DCMI_HandleTypeDef* hdcmi = (DCMI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; hdcmi->State = HAL_DCMI_STATE_ERROR; hdcmi->ErrorCode = HAL_DCMI_ERROR_DMA; DCMI_Cmd(DISABLE); TMC_DCMI_ErrorCallback(hdcmi); } /** * @brief Returns the DMA channel number * @param[in] hdma: pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Stream. * @retval DMA channel number */ static uint32_t DMA_CalcBitShift(DMA_HandleTypeDef *hdma) { uint32_t channel_number = (((uint32_t)hdma->Instance & 0xFFU)) / 32U; return channel_number; } /** * @brief Initializes the DCMI according to the specified * parameters in the DCMI_InitTypeDef and create the associated handle. * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains * the configuration information for DCMI. * @retval HAL status */ TMC_StatusTypeDef TMC_DCMI_Init(DCMI_HandleTypeDef *hdcmi) { /* Check the DCMI peripheral state */ if(hdcmi == NULL) { return TMC_ERROR; } if(hdcmi->State == HAL_DCMI_STATE_RESET) { /* Allocate lock resource and initialize it */ hdcmi->Lock = HAL_UNLOCKED; /* Init the low level hardware */ TMC_DCMI_MspInit(hdcmi); } /* Change the DCMI state */ hdcmi->State = HAL_DCMI_STATE_BUSY; DCMI_Init(&hdcmi->Init); /* Enable the Line, Vsync, Error and Overrun interrupts */ DCMI_ITConfig(DCMI_IT_LINE_MIS | DCMI_IT_VSYNC_MIS | DCMI_IT_ERR_MIS | DCMI_IT_OVR_MIS | DCMI_IT_FRAME_MIS, DISABLE); /* Update error code */ hdcmi->ErrorCode = HAL_DCMI_ERROR_NONE; /* Initialize the DCMI state*/ hdcmi->State = HAL_DCMI_STATE_READY; return TMC_OK; } /** * @brief Enables DCMI DMA request and enables DCMI capture * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains * the configuration information for DCMI. * @param DCMI_Mode DCMI capture mode snapshot or continuous grab.This parameter can be a value of @ref DCMI_Capture_Mode * @param LLI the NEXT Link Address * @param pData The destination memory Buffer address (LCD Frame buffer). * @param Length The length of capture to be transferred. * @retval HAL status */ TMC_StatusTypeDef TMC_DCMI_Start_DMA(DCMI_HandleTypeDef *hdcmi, uint32_t DCMI_Mode, uint32_t LLI, uint32_t pData, uint32_t Length) { /* Check the DCMI peripheral state */ if(hdcmi == NULL) { return TMC_ERROR; } if((hdcmi->State == HAL_DCMI_STATE_RESET) || (hdcmi->State == HAL_DCMI_STATE_BUSY)) { return TMC_ERROR; } __HAL_LOCK(hdcmi); hdcmi->State = HAL_DCMI_STATE_BUSY; hdcmi->ErrorCode = HAL_DCMI_ERROR_NONE; hdcmi->pBuffPtr = pData; hdcmi->XferSize = 0; hdcmi->XferCount = 0; DCMI_ConfigCaptureMode(DCMI_Mode); DCMI_ITConfig(DCMI_IT_LINE_MIS | DCMI_IT_VSYNC_MIS | DCMI_IT_ERR_MIS | DCMI_IT_OVR_MIS | DCMI_IT_FRAME_MIS, DISABLE); DCMI_ConfigDMA(ENABLE); /* Set the SPI TxDMA Half transfer complete callback */ hdcmi->DMA_Handle->XferCpltCallback = TMC_DCMI_DMATransmitCplt; /* Set the DMA error callback */ hdcmi->DMA_Handle->XferErrorCallback = TMC_DCMI_DMAError; /* Set the DMA AbortCpltCallback */ hdcmi->DMA_Handle->XferAbortCallback = NULL; DMA_SetChainListAddress(hdcmi->DMA_Handle->Instance, LLI); TMC_DMA_Start_IT(hdcmi->DMA_Handle, (uint32_t)(&hdcmi->Instance->DR), (uint32_t)pData, Length); __HAL_UNLOCK(hdcmi); // if(DCMI_Mode == DCMI_CAPTURE_CONTINUOUS_GRAB) // { // DCMI_ITConfig(DCMI_IT_FRAME_MIS,ENABLE); //使能帧中断 // NVIC_ClearPendingIRQ(DCMI_IRQn); // NVIC_EnableIRQ(DCMI_IRQn); // } DCMI_Cmd(ENABLE); return TMC_OK; } /** * @brief Initialize the DMA according to the specified * parameters in the DMA_InitTypeDef and create the associated handle. * @param[in] hdma: Pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Stream. * @retval TMC status */ TMC_StatusTypeDef TMC_DMA_Init(DMA_HandleTypeDef *hdma) { uint32_t tickstart = TMC_GetTick(); /* Check the DMA peripheral state */ if(hdma == NULL) { return TMC_ERROR; } /* Allocate lock resource */ __HAL_UNLOCK(hdma); /* Change DMA peripheral state */ hdma->State = TMC_DMA_STATE_BUSY; /* Disable the peripheral */ DMA_Cmd(hdma->Instance, DISABLE); /* Check if the DMA channel is effectively disabled */ while(DMA_GetCmdStatus(hdma->Instance) != RESET) { // /* Check for the Timeout */ if((TMC_GetTick() - tickstart ) > TMC_TIMEOUT_DMA_ABORT) { // /* Update error code */ hdma->ErrorCode = TMC_DMA_ERROR_TIMEOUT; // /* Process Unlocked */ __HAL_UNLOCK(hdma); // /* Change the DMA state */ hdma->State = TMC_DMA_STATE_TIMEOUT; return TMC_TIMEOUT; } } //-------------jjj2022-07-17 /* init the DMA channel */ DMA_Init(hdma->Instance, &hdma->Init); /* Initialize StreamIndex parameters to be used */ hdma->StreamIndex = DMA_CalcBitShift(hdma); /* Clear all interrupt flags */ DMA_ClearITPendingBit(DMA_IT_TC_OFFS << hdma->StreamIndex); DMA_ClearITPendingBit(DMA_IT_ERR_OFFS << hdma->StreamIndex); /* Initialize the error code */ hdma->ErrorCode = TMC_DMA_ERROR_NONE; /* Initialize the DMA state */ hdma->State = TMC_DMA_STATE_READY; return TMC_OK; } /** * @brief DeInitializes the DMA peripheral * @param[in] hdma: pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Stream. * @retval TMC status */ TMC_StatusTypeDef TMC_DMA_DeInit(DMA_HandleTypeDef *hdma) { /* Check the DMA peripheral state */ if(hdma == NULL) { return TMC_ERROR; } /* Check the DMA peripheral state */ if(hdma->State == TMC_DMA_STATE_BUSY) { /* Return error status */ return TMC_BUSY; } /* Reset DMA channel register */ DMA_DeInit(hdma->Instance); /* Initialize the error code */ hdma->ErrorCode = TMC_DMA_ERROR_NONE; /* Initialize the DMA state */ hdma->State = TMC_DMA_STATE_RESET; /* Release Lock */ __HAL_UNLOCK(hdma); return TMC_OK; } /** * @brief Start the DMA Transfer with interrupt enabled. * @param hdma pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Stream. * @param SrcAddress The source memory Buffer address * @param DstAddress The destination memory Buffer address * @param DataLength The length of data to be transferred from source to destination * @retval TMC status */ TMC_StatusTypeDef TMC_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) { TMC_StatusTypeDef status = TMC_OK; /* Process locked */ __HAL_LOCK(hdma); if(TMC_DMA_STATE_READY == hdma->State) { /* Change DMA peripheral state */ hdma->State = TMC_DMA_STATE_BUSY; /* Initialize the error code */ hdma->ErrorCode = TMC_DMA_ERROR_NONE; /* Configure the source, destination address and the data length */ DMA_SetAddress(hdma->Instance, SrcAddress, DstAddress, DataLength); /* Clear all interrupt flags at correct offset within the register */ DMA_ClearITPendingBit(DMA_IT_TC_OFFS << hdma->StreamIndex); DMA_ClearITPendingBit(DMA_IT_ERR_OFFS << hdma->StreamIndex); /* Enable Common interrupts*/ DMA_ITConfig(hdma->Instance, DMA_IT_TC, ENABLE); DMA_ITConfig(hdma->Instance, DMA_IT_ERR, ENABLE); /* Enable the Peripheral */ DMA_Cmd(hdma->Instance, ENABLE); } else { /* Process unlocked */ __HAL_UNLOCK(hdma); /* Return error status */ status = TMC_BUSY; } return status; } /** * @brief Aborts the DMA Transfer in Interrupt mode. * @param hdma pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Stream. * @retval TMC status */ TMC_StatusTypeDef TMC_DMA_Abort_IT(DMA_HandleTypeDef *hdma) { if(hdma->State != TMC_DMA_STATE_BUSY) { hdma->ErrorCode = TMC_DMA_ERROR_NO_XFER; return TMC_ERROR; } else { /* Set Abort State */ hdma->State = TMC_DMA_STATE_ABORT; /* Disable the stream */ DMA_Cmd(hdma->Instance, DISABLE); } return TMC_OK; } /** * @brief Handles DMA interrupt request. * @param hdma: pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA Stream. * @retval None */ void TMC_DMA_IRQHandler(DMA_HandleTypeDef *hdma) { uint32_t complete_sts, error_sts; __IO uint32_t count = 0U; uint32_t timeout = SystemCoreClock / 9600U; /* calculate DMA base and stream number */ complete_sts = DMA_IT_TC_OFFS << hdma->StreamIndex; error_sts = DMA_IT_ERR_OFFS << hdma->StreamIndex; /* Transfer Error Interrupt management ***************************************/ if(DMA_GetITStatus(error_sts) != RESET) { if(DMA_GetFlagStatus(error_sts) != RESET) { /* Disable the transfer error interrupt */ DMA_ITConfig(hdma->Instance, DMA_IT_ERR, DISABLE); /* Clear the transfer error flag */ DMA_ClearITPendingBit(error_sts); /* Update error code */ hdma->ErrorCode |= TMC_DMA_ERROR_TE; } } /* Transfer Complete Interrupt management ***********************************/ if(DMA_GetITStatus(complete_sts) != RESET) { if(DMA_GetFlagStatus(complete_sts) != RESET) { /* Clear the transfer complete flag */ DMA_ClearITPendingBit(complete_sts); if(TMC_DMA_STATE_ABORT == hdma->State) { /* Disable all the transfer interrupts */ DMA_ITConfig(hdma->Instance, DMA_IT_TC, DISABLE); DMA_ITConfig(hdma->Instance, DMA_IT_ERR, DISABLE); /* Clear all interrupt flags at correct offset within the register */ DMA_ClearITPendingBit(complete_sts); DMA_ClearITPendingBit(error_sts); /* Process Unlocked */ __HAL_UNLOCK(hdma); /* Change the DMA state */ hdma->State = TMC_DMA_STATE_READY; if(hdma->XferAbortCallback != NULL) { hdma->XferAbortCallback(hdma); } return; } /* Disable the transfer complete interrupt if the DMA mode is not CIRCULAR */ /* Disable the transfer complete interrupt */ DMA_ITConfig(hdma->Instance, DMA_IT_TC, DISABLE); /* Process Unlocked */ __HAL_UNLOCK(hdma); /* Change the DMA state */ hdma->State = TMC_DMA_STATE_READY; if(hdma->XferCpltCallback != NULL) { /* Transfer complete callback */ hdma->XferCpltCallback(hdma); } } } /* manage error case */ if(hdma->ErrorCode != TMC_DMA_ERROR_NONE) { if((hdma->ErrorCode & TMC_DMA_ERROR_TE) != RESET) { hdma->State = TMC_DMA_STATE_ABORT; /* Disable the stream */ DMA_Cmd(hdma->Instance, DISABLE); do { if(++count > timeout) { break; } } while(DMA_GetCmdStatus(hdma->Instance) != RESET); /* Process Unlocked */ __HAL_UNLOCK(hdma); /* Change the DMA state */ hdma->State = TMC_DMA_STATE_READY; } if(hdma->XferErrorCallback != NULL) { /* Transfer error callback */ hdma->XferErrorCallback(hdma); } } } /** * @brief DCMI MSP Init. * @param[in] hdcmi: pointer to a DCMI_HandleTypeDef structure that contains * the configuration information for the specified DCMI module. * @retval None */ void TMC_DCMI_MspInit(DCMI_HandleTypeDef *hdcmi) { RCC_APB3PeriphClockCmd(RCC_APB3Periph_GPIO, ENABLE); RCC_AHBClockCmd(RCC_AHBPeriph_DCMI, ENABLE); GPIO_InitTypeDef GPIO_Board_Init; /*DCMI_CLK*/ GPIO_Board_Init.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; GPIO_Board_Init.Speed = GPIO_HIGH_SPEED; GPIO_Board_Init.Pull = GPIO_PULLUP; GPIO_Board_Init.Mode = GPIO_MODE_AF; GPIO_Board_Init.Otype = GPIO_MODE_OUTPUT_PP; GPIO_Board_Init.SMIT = GPIO_INPUTSCHMIT_DISABLE; GPIO_Init(GPIOB, &GPIO_Board_Init); GPIO_PinAFConfig(GPIOB, GPIO_PIN_7, GPIO_AF1_DCMI); GPIO_PinAFConfig(GPIOB, GPIO_PIN_8, GPIO_AF1_DCMI); GPIO_PinAFConfig(GPIOB, GPIO_PIN_9, GPIO_AF1_DCMI); GPIO_PinAFConfig(GPIOB, GPIO_PIN_10, GPIO_AF1_DCMI); GPIO_PinAFConfig(GPIOB, GPIO_PIN_11, GPIO_AF1_DCMI); GPIO_PinAFConfig(GPIOB, GPIO_PIN_12, GPIO_AF1_DCMI); GPIO_PinAFConfig(GPIOB, GPIO_PIN_13, GPIO_AF1_DCMI); GPIO_PinAFConfig(GPIOB, GPIO_PIN_14, GPIO_AF1_DCMI); GPIO_PinAFConfig(GPIOB, GPIO_PIN_15, GPIO_AF1_DCMI); /*DCMI_D6*/ GPIO_Board_Init.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2; GPIO_Board_Init.Speed = GPIO_HIGH_SPEED; GPIO_Board_Init.Pull = GPIO_PULLUP; GPIO_Board_Init.Mode = GPIO_MODE_AF; GPIO_Board_Init.Otype = GPIO_MODE_OUTPUT_PP; GPIO_Board_Init.SMIT = GPIO_INPUTSCHMIT_DISABLE; GPIO_Init(GPIOC, &GPIO_Board_Init); GPIO_PinAFConfig(GPIOC, GPIO_PIN_0, GPIO_AF1_DCMI); GPIO_PinAFConfig(GPIOC, GPIO_PIN_1, GPIO_AF1_DCMI); GPIO_PinAFConfig(GPIOC, GPIO_PIN_2, GPIO_AF1_DCMI); } void DCMI_DMA_LLI_Init(uint32_t bufaddr, ImageSizeType dcmi_size) { uint16_t i, lli_len; switch(dcmi_size) { case DCMI_640_480: lli_len = 37; // (2048*37*4) + (1024*1*4)= 307200=640*480 for(i = 0; i < lli_len; i++) { dcmi_lli[i].source_addr = (uint32_t)&DCMI->DR; dcmi_lli[i].dest_addr = (uint32_t)(&(((uint32_t *)bufaddr)[0x800 * (i + 1)])); dcmi_lli[i].lli_addr = (uint32_t)&dcmi_lli[i + 1]; dcmi_lli[i].ctrl = 0x0A480800; } dcmi_lli[lli_len - 1].lli_addr = 0; dcmi_lli[lli_len - 1].ctrl = 0x8A480400; break; case DCMI_320_240: lli_len = 9; // (2048 * 9 * 4) + (768 * 4)=76800=320*240 for(i = 0; i < lli_len; i++) { dcmi_lli[i].source_addr = (uint32_t)&DCMI->DR; dcmi_lli[i].dest_addr = (uint32_t)(&(((uint32_t *)bufaddr)[0x800 * (i + 1)])); dcmi_lli[i].lli_addr = (uint32_t)&dcmi_lli[i + 1]; dcmi_lli[i].ctrl = 0x0A480800; } dcmi_lli[lli_len - 1].lli_addr = 0; dcmi_lli[lli_len - 1].ctrl = 0x8A480300; break; case DCMI_160_240: break; default: break; } } extern uint8_t HaveToPlay(void); uint8_t DCMI_CaptureOnePic(uint32_t bufaddr, ImageSizeType dcmi_size) { volatile uint8_t nCount; nCount = 0; DCMI_CaptureOnePicStart: /*设置LLI连接 当前一帧图像的像素点为320*240,DCMI 一次可以采集一个word的数据(2个点),DMA搬移总量为320*120= 38400次 DMA一次搬移2048次 38400/2048 = 18.75 次 即需要搬移19次 前18次每次搬移2048次,最后一次搬移1536次*/ DCMI_DMA_LLI_Init(bufaddr, dcmi_size); /*配置hdcmi相关*/ gHandleDCMI.Instance = DCMI;/*设置DCMI寄存器地址*/ gHandleDCMI.DMA_Handle = &gHandleDMA;/*设置hdcmi的DMA指针指向hdma*/ gHandleDCMI.DMA_Handle->Instance = DMA_Channel7;/*设置DMA通道为通道7*/ gHandleDCMI.DMA_Handle->Init.DestDataAlignment = DMA_DEST_ALIGN_WORD;/*设置目的搬移数据长度为WORD*/ gHandleDCMI.DMA_Handle->Init.SrcDataAlignment = DMA_SRC_ALIGN_WORD;/*设置源搬移数据长度为WORD*/ gHandleDCMI.DMA_Handle->Init.DestInc = DMA_DEST_INC_ENABLE;/*目的搬移增长使能*/ gHandleDCMI.DMA_Handle->Init.SrcInc = DMA_SRC_INC_DISABLE;/*源的搬移增长使能*/ gHandleDCMI.DMA_Handle->Init.RequestSelect = DMA_REQUEST_DCMI;/*DMA 模式为DCMI */ gHandleDCMI.DMA_Handle->Init.Direction = DMA_CTRL_PERIPH_TO_MEMORY;/*DMA 控制从外设到内存*/ gHandleDCMI.DMA_Handle->Init.IT_Enable = DMA_DEST_INC_DISABLE; gHandleDCMI.DMA_Handle->Parent = &gHandleDCMI; if(dcmi_size == DCMI_640_480) { DCMI_StructInit_Y640480(&gHandleDCMI.Init); }/*初始化DMCI结构体*/ else if(dcmi_size == DCMI_320_240) { DCMI_StructInit_RGB320240(&gHandleDCMI.Init); } TMC_DCMI_Init(&gHandleDCMI);/*DCMI初始化*/ TMC_DMA_DeInit(gHandleDCMI.DMA_Handle);/*DMA初始化*/ TMC_DMA_Init(gHandleDCMI.DMA_Handle);/*DMA初始化*/ TMC_DCMI_Start_DMA(&gHandleDCMI, DCMI_CAPTURE_SNAPSHOT, (u32)(&dcmi_lli[0]), bufaddr, 0x800); /*采集第1个2048word DMCI数据*/ DCMI_ConfigImageCompress(DCMI_IMAGE_YCBCR, ENABLE); DCMI_CaptureCmd(ENABLE);/*启动捕获*/ TimerHSIClockCount(TIM3, START_TIMER); gDCMICaptureFlag = 0; nCount++; while((gDCMICaptureFlag == 0)&&(nCount<4))/*捕获 DCMI_Flag*/ { if(HaveToPlay()||gKeyAction) { TMC_DCMI_DMAError(gHandleDCMI.DMA_Handle); TimerHSIClockCount(TIM3, STOP_TIMER); return 0; } if(TimerHSIClockCount(TIM3, GET_TIMER) >= CAMERA_TIMEOUE) //150ms { AppCameraInit(); TimerHSIClockCount(TIM3, STOP_TIMER); goto DCMI_CaptureOnePicStart; } } TimerHSIClockCount(TIM3, STOP_TIMER); return 1; } /** * @brief 计算两次图像的平方和均值 * @param[in] 图像大小. * @retval 计算的均值 */ #define BLK_X_NUM 5 #define BLK_Y_NUM 3 #define BLK_W (320/BLK_X_NUM) #define BLK_H (240/BLK_Y_NUM) #define P(x,y,i,j) (y*BLK_H*320+x*BLK_W+i*320+j) int DCMI_Differ(uint32_t dcmi_size) { uint32_t i,j,x,y, num,resu; uint8_t *pData = (uint8_t *) DCMIBUFADDR; for(x=0;x gConfgBuf.sensitivity) { return TMC_OK; } } return TMC_ERROR; } void AppCameraInit(void) { uint8_t ucTimerValue = 0; //打开DMA时钟 使能DMA中断 RCC_AHBClockCmd(RCC_AHBPeriph_DMA, ENABLE); NVIC_SetPriorityGrouping(5); NVIC_SetPriority(DMA_IRQn, 2); NVIC_ClearPendingIRQ(DMA_IRQn); NVIC_EnableIRQ(DMA_IRQn); //打开DCMI时钟 RCC_AHBClockCmd(RCC_AHBPeriph_DCMI, ENABLE); //输出时钟 GPIO_MonitorClkOut(1, OSC_SOURCE_CLOCK_PLL_H, 3); //3 : 24MHz gciCameraInfo.I2C_SCL.GPIOx = (void *)VBAT_GPIO; gciCameraInfo.I2C_SCL.GPIO_PIN_x = 3; gciCameraInfo.I2C_SDA.GPIOx = (void *)VBAT_GPIO; gciCameraInfo.I2C_SDA.GPIO_PIN_x = 2; gciCameraInfo.Camera_ClockSource = 1; gciCameraInfo.Camera_PowerControl.GPIOx = (void *)GPIOD; gciCameraInfo.Camera_PowerControl.GPIO_PIN_x = 10; gciCameraInfo.Camera_Reset.GPIOx = (void *)GPIOD; gciCameraInfo.Camera_Reset.GPIO_PIN_x = 4; #if BCTCTEST // 务必使用BF3007摄像头 #endif ucTimerValue = TMC_CAMERA_Init(&gciCameraInfo); if(ucTimerValue != 0) { return; } } void Sleep_Mode(void) { //禁用摄像头 GPIO_SetBits(CAMERA_POWER_PORT, CAMERA_POWER_PIN); PWR_EnterSTOPMode(PWR_STOPEntry_WFE); //开启摄像头 GPIO_ResetBits(CAMERA_POWER_PORT, CAMERA_POWER_PIN); }