本帖最后由 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;
}
|