|
函数HAL_DCMI_Start_DMA封装的通用定时器DMA1,DMA2。使用这个定时器的特点是限制单轮最大65535次传输,这样使用大分辨率摄像头非常不方便。
使用这个函数的话,解决了这个问题,程序里面做了一个处理,对于需要大于65536次传输的情况,使用了双缓冲,不断动态调整地址,直到一帧传输完毕后会使能DCMI的帧中断
- /**
- * @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.
- * @param pData: The destination memory Buffer address (LCD Frame buffer).
- * @param Length: The length of capture to be transferred.
- * @retval HAL status
- */
- HAL_StatusTypeDef HAL_DCMI_Start_DMA(DCMI_HandleTypeDef* hdcmi, uint32_t DCMI_Mode, uint32_t pData, uint32_t Length)
- {
- /* Initialize the second memory address */
- uint32_t SecondMemAddress = 0;
- /* Check function parameters */
- assert_param(IS_DCMI_CAPTURE_MODE(DCMI_Mode));
- /* Process Locked */
- __HAL_LOCK(hdcmi);
-
- /* Lock the DCMI peripheral state */
- hdcmi->State = HAL_DCMI_STATE_BUSY;
- /* Enable DCMI by setting DCMIEN bit */
- __HAL_DCMI_ENABLE(hdcmi);
-
- /* Configure the DCMI Mode */
- hdcmi->Instance->CR &= ~(DCMI_CR_CM);
- hdcmi->Instance->CR |= (uint32_t)(DCMI_Mode);
- /* Set the DMA memory0 conversion complete callback */
- hdcmi->DMA_Handle->XferCpltCallback = DCMI_DMAXferCplt;
- /* Set the DMA error callback */
- hdcmi->DMA_Handle->XferErrorCallback = DCMI_DMAError;
- /* Set the dma abort callback */
- hdcmi->DMA_Handle->XferAbortCallback = NULL;
- /* Reset transfer counters value */
- hdcmi->XferCount = 0;
- hdcmi->XferTransferNumber = 0;
-
- if(Length <= 0xFFFF)
- {
- /* Enable the DMA Stream */
- HAL_DMA_Start_IT(hdcmi->DMA_Handle, (uint32_t)&hdcmi->Instance->DR, (uint32_t)pData, Length);
- }
- else /* DCMI_DOUBLE_BUFFER Mode */
- {
- /* Set the DMA memory1 conversion complete callback */
- hdcmi->DMA_Handle->XferM1CpltCallback = DCMI_DMAXferCplt;
- /* Initialize transfer parameters */
- hdcmi->XferCount = 1;
- hdcmi->XferSize = Length;
- hdcmi->pBuffPtr = pData;
-
- /* Get the number of buffer */
- while(hdcmi->XferSize > 0xFFFF)
- {
- hdcmi->XferSize = (hdcmi->XferSize/2);
- hdcmi->XferCount = hdcmi->XferCount*2;
- }
- /* Update DCMI counter and transfer number*/
- hdcmi->XferCount = (hdcmi->XferCount - 2);
- hdcmi->XferTransferNumber = hdcmi->XferCount;
- /* Update second memory address */
- SecondMemAddress = (uint32_t)(pData + (4*hdcmi->XferSize));
- /* Start DMA multi buffer transfer */
- HAL_DMAEx_MultiBufferStart_IT(hdcmi->DMA_Handle, (uint32_t)&hdcmi->Instance->DR, (uint32_t)pData, SecondMemAddress, hdcmi->XferSize);
- }
-
- /* Enable Capture */
- hdcmi->Instance->CR |= DCMI_CR_CAPTURE;
- /* Release Lock */
- __HAL_UNLOCK(hdcmi);
- /* Return function status */
- return HAL_OK;
- }
复制代码
DMA传输完成中断里面的关键地方:
- /**
- * @}
- */
- /* Private functions ---------------------------------------------------------*/
- /** @defgroup DCMI_Private_Functions DCMI Private Functions
- * @{
- */
- /**
- * @brief DMA conversion complete callback.
- * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
- * the configuration information for the specified DMA module.
- * @retval None
- */
- static void DCMI_DMAXferCplt(DMA_HandleTypeDef *hdma)
- {
- uint32_t tmp = 0;
- DCMI_HandleTypeDef* hdcmi = ( DCMI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
- if(hdcmi->XferCount != 0)
- {
- /* Update memory 0 address location */
- tmp = ((((DMA_Stream_TypeDef *)(hdcmi->DMA_Handle->Instance))->CR) & DMA_SxCR_CT);
- if(((hdcmi->XferCount % 2) == 0) && (tmp != 0))
- {
- tmp = ((DMA_Stream_TypeDef *)(hdcmi->DMA_Handle->Instance))->M0AR;
- HAL_DMAEx_ChangeMemory(hdcmi->DMA_Handle, (tmp + (8*hdcmi->XferSize)), MEMORY0);
- hdcmi->XferCount--;
- }
- /* Update memory 1 address location */
- else if((((DMA_Stream_TypeDef *)(hdcmi->DMA_Handle->Instance))->CR & DMA_SxCR_CT) == 0)
- {
- tmp = ((DMA_Stream_TypeDef *)(hdcmi->DMA_Handle->Instance))->M1AR;
- HAL_DMAEx_ChangeMemory(hdcmi->DMA_Handle, (tmp + (8*hdcmi->XferSize)), MEMORY1);
- hdcmi->XferCount--;
- }
- }
- /* Update memory 0 address location */
- else if((((DMA_Stream_TypeDef *)(hdcmi->DMA_Handle->Instance))->CR & DMA_SxCR_CT) != 0)
- {
- ((DMA_Stream_TypeDef *)(hdcmi->DMA_Handle->Instance))->M0AR = hdcmi->pBuffPtr;
- }
- /* Update memory 1 address location */
- else if((((DMA_Stream_TypeDef *)(hdcmi->DMA_Handle->Instance))->CR & DMA_SxCR_CT) == 0)
- {
- tmp = hdcmi->pBuffPtr;
- ((DMA_Stream_TypeDef *)(hdcmi->DMA_Handle->Instance))->M1AR = (tmp + (4*hdcmi->XferSize));
- hdcmi->XferCount = hdcmi->XferTransferNumber;
- }
- /* Check if the frame is transferred */
- if(hdcmi->XferCount == hdcmi->XferTransferNumber)
- {
- /* Enable the Frame interrupt */
- __HAL_DCMI_ENABLE_IT(hdcmi, DCMI_IT_FRAME);
-
- /* When snapshot mode, set dcmi state to ready */
- if((hdcmi->Instance->CR & DCMI_CR_CM) == DCMI_MODE_SNAPSHOT)
- {
- hdcmi->State= HAL_DCMI_STATE_READY;
- }
- }
- }
复制代码
|
|