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<4D><49><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD>*/
|
|||
|
|
void TMC_DCMI_CpltCallback(DCMI_HandleTypeDef *hdcmi)
|
|||
|
|
{
|
|||
|
|
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ*/
|
|||
|
|
gDCMICaptureFlag = 1;
|
|||
|
|
// DMA_ClearITPendingBit(DMA_IT_TC7);
|
|||
|
|
DMA_Cmd(hdcmi->DMA_Handle->Instance, DISABLE);
|
|||
|
|
DCMI_CaptureCmd(DISABLE);/*<2A>رղ<D8B1><D5B2><EFBFBD>*/
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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); //ʹ<><CAB9>֡<EFBFBD>ж<EFBFBD>
|
|||
|
|
// 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:
|
|||
|
|
/*<2A><><EFBFBD><EFBFBD>LLI<4C><49><EFBFBD><EFBFBD> <20><>ǰһ֡ͼ<D6A1><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>Ϊ320*240<34><30>DCMI һ<>ο<EFBFBD><CEBF>Բɼ<D4B2>һ<EFBFBD><D2BB>word<72><64><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>2<EFBFBD><32><EFBFBD>㣩<EFBFBD><E3A3A9>DMA<4D><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ320*120= 38400<30><30>
|
|||
|
|
DMAһ<EFBFBD>ΰ<EFBFBD><EFBFBD><EFBFBD>2048<EFBFBD><EFBFBD> 38400/2048 = 18.75 <EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>19<EFBFBD><EFBFBD> ǰ18<EFBFBD><EFBFBD>ÿ<EFBFBD>ΰ<EFBFBD><EFBFBD><EFBFBD>2048<EFBFBD>Σ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>ΰ<EFBFBD><EFBFBD><EFBFBD>1536<EFBFBD><EFBFBD>*/
|
|||
|
|
DCMI_DMA_LLI_Init(bufaddr, dcmi_size);
|
|||
|
|
/*<2A><><EFBFBD><EFBFBD>hdcmi<6D><69><EFBFBD><EFBFBD>*/
|
|||
|
|
gHandleDCMI.Instance = DCMI;/*<2A><><EFBFBD><EFBFBD>DCMI<4D>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>ַ*/
|
|||
|
|
gHandleDCMI.DMA_Handle = &gHandleDMA;/*<2A><><EFBFBD><EFBFBD>hdcmi<6D><69>DMAָ<41><D6B8>ָ<EFBFBD><D6B8>hdma*/
|
|||
|
|
gHandleDCMI.DMA_Handle->Instance = DMA_Channel7;/*<2A><><EFBFBD><EFBFBD>DMAͨ<41><CDA8>Ϊͨ<CEAA><CDA8>7*/
|
|||
|
|
gHandleDCMI.DMA_Handle->Init.DestDataAlignment = DMA_DEST_ALIGN_WORD;/*<2A><><EFBFBD><EFBFBD>Ŀ<EFBFBD>İ<EFBFBD><C4B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>ΪWORD*/
|
|||
|
|
gHandleDCMI.DMA_Handle->Init.SrcDataAlignment = DMA_SRC_ALIGN_WORD;/*<2A><><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>ΪWORD*/
|
|||
|
|
gHandleDCMI.DMA_Handle->Init.DestInc = DMA_DEST_INC_ENABLE;/*Ŀ<>İ<EFBFBD><C4B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>*/
|
|||
|
|
gHandleDCMI.DMA_Handle->Init.SrcInc = DMA_SRC_INC_DISABLE;/*Դ<>İ<EFBFBD><C4B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>*/
|
|||
|
|
gHandleDCMI.DMA_Handle->Init.RequestSelect = DMA_REQUEST_DCMI;/*DMA ģʽΪDCMI */
|
|||
|
|
gHandleDCMI.DMA_Handle->Init.Direction = DMA_CTRL_PERIPH_TO_MEMORY;/*DMA <20><><EFBFBD>ƴ<EFBFBD><C6B4><EFBFBD><EFBFBD>赽<EFBFBD>ڴ<EFBFBD>*/
|
|||
|
|
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); }/*<2A><>ʼ<EFBFBD><CABC>DMCI<43>ṹ<EFBFBD><E1B9B9>*/
|
|||
|
|
else if(dcmi_size == DCMI_320_240)
|
|||
|
|
{ DCMI_StructInit_RGB320240(&gHandleDCMI.Init); }
|
|||
|
|
|
|||
|
|
TMC_DCMI_Init(&gHandleDCMI);/*DCMI<4D><49>ʼ<EFBFBD><CABC>*/
|
|||
|
|
TMC_DMA_DeInit(gHandleDCMI.DMA_Handle);/*DMA<4D><41>ʼ<EFBFBD><CABC>*/
|
|||
|
|
TMC_DMA_Init(gHandleDCMI.DMA_Handle);/*DMA<4D><41>ʼ<EFBFBD><CABC>*/
|
|||
|
|
TMC_DCMI_Start_DMA(&gHandleDCMI, DCMI_CAPTURE_SNAPSHOT, (u32)(&dcmi_lli[0]), bufaddr, 0x800); /*<2A>ɼ<EFBFBD><C9BC><EFBFBD>1<EFBFBD><31>2048word DMCI<43><49><EFBFBD><EFBFBD>*/
|
|||
|
|
DCMI_ConfigImageCompress(DCMI_IMAGE_YCBCR, ENABLE);
|
|||
|
|
DCMI_CaptureCmd(ENABLE);/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
|
|||
|
|
TimerHSIClockCount(TIM3, START_TIMER);
|
|||
|
|
gDCMICaptureFlag = 0;
|
|||
|
|
nCount++;
|
|||
|
|
while((gDCMICaptureFlag == 0)&&(nCount<4))/*<2A><><EFBFBD><EFBFBD> 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 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><EFBFBD><EFBFBD>;<EFBFBD>ֵ
|
|||
|
|
* @param[in] ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>С.
|
|||
|
|
* @retval <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD>ֵ
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
#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;
|
|||
|
|
//<2F><><EFBFBD><EFBFBD>DMAʱ<41><CAB1> ʹ<><CAB9>DMA<4D>ж<EFBFBD>
|
|||
|
|
RCC_AHBClockCmd(RCC_AHBPeriph_DMA, ENABLE);
|
|||
|
|
NVIC_SetPriorityGrouping(5);
|
|||
|
|
NVIC_SetPriority(DMA_IRQn, 2);
|
|||
|
|
NVIC_ClearPendingIRQ(DMA_IRQn);
|
|||
|
|
NVIC_EnableIRQ(DMA_IRQn);
|
|||
|
|
//<2F><><EFBFBD><EFBFBD>DCMIʱ<49><CAB1>
|
|||
|
|
RCC_AHBClockCmd(RCC_AHBPeriph_DCMI, ENABLE);
|
|||
|
|
//<2F><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
|
|||
|
|
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
|
|||
|
|
// <20><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>BF3007<30><37><EFBFBD><EFBFBD>ͷ
|
|||
|
|
#endif
|
|||
|
|
ucTimerValue = TMC_CAMERA_Init(&gciCameraInfo);
|
|||
|
|
|
|||
|
|
if(ucTimerValue != 0)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void Sleep_Mode(void)
|
|||
|
|
{
|
|||
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ
|
|||
|
|
GPIO_SetBits(CAMERA_POWER_PORT, CAMERA_POWER_PIN);
|
|||
|
|
PWR_EnterSTOPMode(PWR_STOPEntry_WFE);
|
|||
|
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ
|
|||
|
|
GPIO_ResetBits(CAMERA_POWER_PORT, CAMERA_POWER_PIN);
|
|||
|
|
}
|
|||
|
|
|