打印
[STM32F2]

STM32F207VCT6 DCMI-DMA到内存数组,求指点!

[复制链接]
9282|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
mrhw|  楼主 | 2014-6-29 10:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 mrhw 于 2014-6-29 10:58 编辑

项目所用MCU型号是STM32F207VCT6, 使用TVP5150视频模数转换芯片,将模拟视频信号转换为带外同步数字信号通过DCMI接收,接收的数据大小是4行,为调试方便,暂且接收一个字节。

在调用以下程序之前已经对TVP5150进行了初始化,TVP5150已经可以输出50HZ的 Vsync 垂直同步信号,16.625K的Hsync水平同步信号,同步信号全部是上升沿触发,TVP5150同时输出PIXCK(像素时钟)27M,也是上升沿数据有效。

程序通过以下几个步骤进行初始化:关键1间接调用关键2,关键2间接调用关键3, 最终完成了初始化

关键4 启动DCMI-DMA接收的,

现在的问题是:一旦调用关键4,DCMI_DMAError 会被立即触发,DMA失败。

关键1.
void MX_DCMI_Init(void)
{

  hdcmi.Instance = DCMI;
  hdcmi.Init.SynchroMode = DCMI_SYNCHRO_HARDWARE;
  hdcmi.Init.PCKPolarity = DCMI_PCKPOLARITY_RISING; //1
  hdcmi.Init.VSPolarity = DCMI_VSPOLARITY_HIGH; //2
  hdcmi.Init.HSPolarity = DCMI_HSPOLARITY_HIGH;//3  通过对123 取不同值也不行
  hdcmi.Init.CaptureRate = DCMI_CR_ALL_FRAME;
  hdcmi.Init.ExtendedDataMode = DCMI_EXTEND_DATA_8B;
  hdcmi.Init.JPEGMode = DCMI_JPEG_DISABLE;
  HAL_DCMI_Init(&hdcmi); //关键2

}

关键2.
HAL_StatusTypeDef HAL_DCMI_Init(DCMI_HandleTypeDef *hdcmi)
{     
  /* Check the DCMI peripheral state */
  if(hdcmi == NULL)
  {
     return HAL_ERROR;
  }
  
  /* Check function parameters */
  assert_param(IS_DCMI_ALL_INSTANCE(hdcmi->Instance));
  assert_param(IS_DCMI_PCKPOLARITY(hdcmi->Init.PCKPolarity));
  assert_param(IS_DCMI_VSPOLARITY(hdcmi->Init.VSPolarity));
  assert_param(IS_DCMI_HSPOLARITY(hdcmi->Init.HSPolarity));
  assert_param(IS_DCMI_SYNCHRO(hdcmi->Init.SynchroMode));
  assert_param(IS_DCMI_CAPTURE_RATE(hdcmi->Init.CaptureRate));
  assert_param(IS_DCMI_EXTENDED_DATA(hdcmi->Init.ExtendedDataMode));
  assert_param(IS_DCMI_MODE_JPEG(hdcmi->Init.JPEGMode));

  if(hdcmi->State == HAL_DCMI_STATE_RESET)
  {
    /* Init the low level hardware */
    HAL_DCMI_MspInit(hdcmi); //关键3
  }
  
  /* Change the DCMI state */
  hdcmi->State = HAL_DCMI_STATE_BUSY;

  /* Configures the HS, VS, DE and PC polarity */
  hdcmi->Instance->CR &= ~(DCMI_CR_PCKPOL | DCMI_CR_HSPOL  | DCMI_CR_VSPOL  | DCMI_CR_EDM_0 |
                           DCMI_CR_EDM_1  | DCMI_CR_FCRC_0 | DCMI_CR_FCRC_1 | DCMI_CR_JPEG  |
                           DCMI_CR_ESS);
  hdcmi->Instance->CR |=  (uint32_t)(hdcmi->Init.SynchroMode | hdcmi->Init.CaptureRate | \
                                     hdcmi->Init.VSPolarity  | hdcmi->Init.HSPolarity  | \
                                     hdcmi->Init.PCKPolarity | hdcmi->Init.ExtendedDataMode | \
                                     hdcmi->Init.JPEGMode);

  if(hdcmi->Init.SynchroMode == DCMI_SYNCHRO_EMBEDDED)
  {
    DCMI->ESCR = (((uint32_t)hdcmi->Init.SyncroCode.FrameStartCode)    |
                  ((uint32_t)hdcmi->Init.SyncroCode.LineStartCode << 8)|
                  ((uint32_t)hdcmi->Init.SyncroCode.LineEndCode << 16) |
                  ((uint32_t)hdcmi->Init.SyncroCode.FrameEndCode << 24));
  }

  /* Enable the Line interrupt */
  __HAL_DCMI_ENABLE_IT(hdcmi, DCMI_IT_LINE);

  /* Enable the VSYNC interrupt */
  __HAL_DCMI_ENABLE_IT(hdcmi, DCMI_IT_VSYNC);

  /* Enable the Frame capture complete interrupt */
  __HAL_DCMI_ENABLE_IT(hdcmi, DCMI_IT_FRAME);

  /* Enable the Synchronization error interrupt */
  __HAL_DCMI_ENABLE_IT(hdcmi, DCMI_IT_ERR);

  /* Enable the Overflow interrupt */
  __HAL_DCMI_ENABLE_IT(hdcmi, DCMI_IT_OVF);

  /* Enable DCMI by setting DCMIEN bit */
  __HAL_DCMI_ENABLE(hdcmi);   //DCMI已经使能了

  /* Update error code */
  hdcmi->ErrorCode = HAL_DCMI_ERROR_NONE;
  
  /* Initialize the DCMI state*/
  hdcmi->State  = HAL_DCMI_STATE_READY;

  return HAL_OK;
}

关键3.

void HAL_DCMI_MspInit(DCMI_HandleTypeDef* hdcmi)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(hdcmi->Instance==DCMI)
  {
    /* Peripheral clock enable */
    __DCMI_CLK_ENABLE();
  
    /**DCMI GPIO Configuration   
    PE4     ------> DCMI_D4
    PE5     ------> DCMI_D6
    PE6     ------> DCMI_D7
    PA4     ------> DCMI_HSYNC
    PA6     ------> DCMI_PIXCK
    PC6     ------> DCMI_D0
    PC7     ------> DCMI_D1
    PC8     ------> DCMI_D2
    PC9     ------> DCMI_D3
    PB6     ------> DCMI_D5
    PB7     ------> DCMI_VSYNC
    */
    GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* Peripheral DMA init*/
  
    hdma_dcmi.Instance = DMA2_Stream1;
    hdma_dcmi.Init.Channel = DMA_CHANNEL_1;
    hdma_dcmi.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_dcmi.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_dcmi.Init.MemInc = DMA_MINC_DISABLE;
    hdma_dcmi.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_dcmi.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_dcmi.Init.Mode = DMA_NORMAL; // 这里改为循环模式也不行
    hdma_dcmi.Init.Priority = DMA_PRIORITY_VERY_HIGH;
    hdma_dcmi.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    HAL_DMA_Init(&hdma_dcmi);  //dma已经初始化好了,没有使能

    __HAL_LINKDMA(hdcmi,DMA_Handle,hdma_dcmi);

    /* Peripheral interrupt init*/
    /* Sets the priority grouping field */
    HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
    HAL_NVIC_SetPriority(DCMI_IRQn, 2, 0);
    HAL_NVIC_EnableIRQ(DCMI_IRQn);
  }

}

关键 4  调用 HAL_DCMI_Start_DMA(&hdcmi, DCMI_MODE_CONTINUOUS, (uint32_t)&data1, 1); //会立即触发DMA错误,&data1数据没有改变

HAL_StatusTypeDef HAL_DCMI_Start_DMA(DCMI_HandleTypeDef* hdcmi, uint32_t DCMI_Mode, uint32_t pData, uint32_t Length)
{  
  /* Initialise 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;

  /* Check the parameters */
  assert_param(IS_DCMI_CAPTURE_MODE(DCMI_Mode));

  /* 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_DMAConvCplt;

  /* Set the DMA error callback */
  hdcmi->DMA_Handle->XferErrorCallback = DCMI_DMAError;  //这个 DCMI_DMAError 会被立即触发

  if(Length <= 0xFFFF)
  {
    /* Enable the DMA Stream */    //步骤5
    HAL_DMA_Start_IT(hdcmi->DMA_Handle, (uint32_t)&hdcmi->Instance->DR, (uint32_t)pData, Length);//这里面使能了DMA
  }
  else /* DCMI_DOUBLE_BUFFER Mode */
  {
    /* Set the DMA memory1 conversion complete callback */
    hdcmi->DMA_Handle->XferM1CpltCallback = DCMI_DMAConvCplt;

    /* Initialise 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 */
  DCMI->CR |= DCMI_CR_CAPTURE; //启动捕获图像

  /* Return function status */
  return HAL_OK;
}





沙发
mrhw|  楼主 | 2014-6-29 10:57 | 只看该作者
步骤5, 步骤4里面间接调用的步骤5
HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
{
  /* Process locked */
  __HAL_LOCK(hdma);

  /* Change DMA peripheral state */
  hdma->State = HAL_DMA_STATE_BUSY;

   /* Check the parameters */
  assert_param(IS_DMA_BUFFER_SIZE(DataLength));

  /* Disable the peripheral */
  __HAL_DMA_DISABLE(hdma);

  /* Configure the source, destination address and the data length */
  DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);

  /* Enable the transfer complete interrupt */
  __HAL_DMA_ENABLE_IT(hdma, DMA_IT_TC);

  /* Enable the Half transfer complete interrupt */
  __HAL_DMA_ENABLE_IT(hdma, DMA_IT_HT);  

  /* Enable the transfer Error interrupt */
  __HAL_DMA_ENABLE_IT(hdma, DMA_IT_TE);

  /* Enable the FIFO Error interrupt */
  __HAL_DMA_ENABLE_IT(hdma, DMA_IT_FE);

  /* Enable the direct mode Error interrupt */
  __HAL_DMA_ENABLE_IT(hdma, DMA_IT_DME);

   /* Enable the Peripheral */
  __HAL_DMA_ENABLE(hdma);

  return HAL_OK;
}

使用特权

评论回复
板凳
zhaofan999| | 2014-8-4 20:02 | 只看该作者
请问问题解决了吗?

使用特权

评论回复
地板
mrhw|  楼主 | 2014-8-15 09:25 | 只看该作者
一直没有解决,闲置了

使用特权

评论回复
5
colin2135| | 2014-12-31 11:33 | 只看该作者
开启了DCMI和DMA中断,如果没有加中断函数就会产生错误。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

9

主题

41

帖子

0

粉丝