TMC32_QJB/Camera/camara_main.c
2026-04-30 16:23:12 +08:00

667 lines
20 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
******************************************************************************
* @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.
*
* <h2><center>&copy; COPYRIGHT 2016 TMC</center></h2>
******************************************************************************/
/* 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*240DCMI 一次可以采集一个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<BLK_X_NUM;x++)
for(y=0;y<BLK_Y_NUM;y++)
{
resu = 0;
for(i = 0; i < BLK_H; i++)
for(j = 0; j < BLK_W; j++)
{
num = P(x,y,i,j);
resu += (pData[num] - pData[num + dcmi_size])*(pData[num] - pData[num + dcmi_size]);
}
if(resu/BLK_W/BLK_H > 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);
}