667 lines
20 KiB
C
667 lines
20 KiB
C
/**
|
||
******************************************************************************
|
||
* @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>© 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*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<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);
|
||
}
|
||
|