打印

DCMI接口用DMA传输到内存数组,数组没有数据,求高手指点

[复制链接]
265|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
采用STM32H7的dcmi接口,像素时钟50MHZ,用DMA2 sream1搬运数据,相机模组采用8位,像素分辨率480x480问题:
采用单帧捕获,内存数组大小【480*480】,dma传输完成中断能够正常进入,但是数组里面没有数据,貌似DMA没搬运成功,
上源码:
DCMI和DMA配置
#include "sys.h"
#include "dcmi.h"



DCMI_HandleTypeDef  DCMI_Handler;           //DCMI句柄
DMA_HandleTypeDef   DMA_DCMI_Handler;        //DMA句柄





/***********************************************************************************************
***DCMI初始化
************************************************************************************************/
void DCMI_Init(void)
{
    DCMI_Handler.Instance=DCMI;

    DCMI_Handler.Init.SynchroMode=DCMI_SYNCHRO_HARDWARE;    //硬件同步HSYNC,VSYNC
    DCMI_Handler.Init.PCKPolarity=DCMI_PCKPOLARITY_RISING;//DCMI_PCKPOLARITY_RISING;//DCMI_PCKPOLARITY_FALLING;  //PCLK 上升沿有效
    DCMI_Handler.Init.VSPolarity=DCMI_VSPOLARITY_LOW;       //VSYNC 低电平有效
    DCMI_Handler.Init.HSPolarity=DCMI_HSPOLARITY_LOW;       //HSYNC 低电平有效
    DCMI_Handler.Init.CaptureRate=DCMI_CR_ALL_FRAME;//DCMI_CR_ALL_FRAME;        //全帧捕获 DCMI_CR_ALTERNATE_4_FRAME
    DCMI_Handler.Init.ExtendedDataMode=DCMI_EXTEND_DATA_8B; //8位数据格式
    HAL_DCMI_Init(&DCMI_Handler);                           //初始化DCMI,此函数会开启帧中断  


}


/***********************************************************************************************
//DCMI底层驱动,引脚配置,时钟使能,中断配置
//此函数会被HAL_DCMI_Init()调用
//@hdcmiCMI句柄
************************************************************************************************/
    /**DCMI GPIO Configuration   
    PA4     ------> DCMI_HSYNC
    PA6     ------> DCMI_PIXCLK
    PC6     ------> DCMI_D0
    PC7     ------> DCMI_D1
    PC8     ------> DCMI_D2
    PC9     ------> DCMI_D3
    PC11     ------> DCMI_D4
    PD3     ------> DCMI_D5
    PG9     ------> DCMI_VSYNC
    PB8     ------> DCMI_D6
    PB9     ------> DCMI_D7
    */
void HAL_DCMI_MspInit(DCMI_HandleTypeDef* hdcmi)
{
        GPIO_InitTypeDef GPIO_InitStruct;
        
//使能DCMI时钟,挂载在AHB2 总线上
    __HAL_RCC_DCMI_CLK_ENABLE();               

//初始化DCMI引脚  
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;

    GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_6;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    //
    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_11;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_3;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    //DCMI_VSYNC
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

    //
    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
        
//设置中断   
    HAL_NVIC_SetPriority(DCMI_IRQn,1,1);        //抢占优先级1,子优先级1
    HAL_NVIC_EnableIRQ(DCMI_IRQn);              //使能DCMI中断

//开始传输
//调用DMA_Config 函数开始DMA 数据传输,每传输完一帧数据需要调用一次,它包含本次传输的目的首地址及传输的数据量;

}


/* 配置DMA 从DCMI 中获取数据*/
//@DMA_Memory0BaseAddr:本次DMA 传输的目的首地址
//@DMA_BufferSize:指示本次DMA传输的数据量,单位是一个字,即4 字节
void DCMI_DMA_Init(uint32_t DMA_Memory0BaseAddr,uint32_t DMA_BufferSize)
{
    __HAL_RCC_DMA2_CLK_ENABLE();                                    //使能DMA2时钟
        
    DMA_DCMI_Handler.Instance=DMA2_Stream1;                          //DMA2数据流1   
        DMA_DCMI_Handler.Init.Request=DMA_REQUEST_DCMI;                                        //DCMI的DMA请求
    DMA_DCMI_Handler.Init.Direction=DMA_PERIPH_TO_MEMORY;            //外设到存储器
    DMA_DCMI_Handler.Init.PeriphInc=DMA_PINC_DISABLE;                //外设非增量模式
    DMA_DCMI_Handler.Init.MemInc=DMA_MINC_ENABLE;                  //存储器增量模式
    DMA_DCMI_Handler.Init.PeriphDataAlignment=DMA_PDATAALIGN_WORD;   //外设数据长度:32位
    DMA_DCMI_Handler.Init.MemDataAlignment=DMA_MDATAALIGN_BYTE;//DMA_MDATAALIGN_BYTE;             //存储器数据长度:8/16/32位
    DMA_DCMI_Handler.Init.Mode=DMA_CIRCULAR;//DMA_CIRCULAR;//DMA_NORMAL;                         //非循环模式
    DMA_DCMI_Handler.Init.Priority=MDMA_PRIORITY_HIGH;//MDMA_PRIORITY_HIGH;//MDMA_PRIORITY_VERY_HIGH;                //高优先级
    DMA_DCMI_Handler.Init.FIFOMode=DMA_FIFOMODE_ENABLE;              //使能FIFO
    DMA_DCMI_Handler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_HALFFULL; //使用1/2的FIFO
    DMA_DCMI_Handler.Init.MemBurst=DMA_MBURST_SINGLE;                //存储器突发传输
    DMA_DCMI_Handler.Init.PeriphBurst=DMA_PBURST_SINGLE;             //外设突发单次传输



    __HAL_LINKDMA(&DCMI_Handler, DMA_Handle, DMA_DCMI_Handler);

    //DMA 中断配置
    HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);

    HAL_DMA_DeInit(&DMA_DCMI_Handler);                               //先清除以前的设置
    HAL_DMA_Init(&DMA_DCMI_Handler);


    //使能DCMI 采集数据
    //DCMI_MODE_CONTINUOUS
    //DCMI_MODE_SNAPSHOT
    HAL_DCMI_Start_DMA(&DCMI_Handler, DCMI_MODE_SNAPSHOT,(uint32_t)DMA_Memory0BaseAddr,DMA_BufferSize);
}


主程序
#define img_width   480 //图像的宽度,单位字节
#define img_height  480 //图像的高度,单位字节
#define img_size    (img_width*img_height)//图像的大小,单位字节

u8 Img_Frame_Buffer[img_size];//对应img_width*img_height个像素灰度值

u16 CMOS_Frame_TakeOver=0;  




//DMA2 中断服务函数
void DMA2_Stream1_IRQHandler(void)
{
   // if ((__HAL_DMA_GET_FLAG(DMA2_Stream0, DMA_IT_TCIF0) != RESET))
    if(__HAL_DMA_GET_FLAG(&DMA_DCMI_Handler,DMA_FLAG_TCIF1_5)!=RESET)//DMA传输完成
    {

        __HAL_DMA_CLEAR_FLAG(&DMA_DCMI_Handler,DMA_FLAG_TCIF1_5);//清除DMA传输完成中断标志位
        if(HAL_DMA_GetState(&DMA_DCMI_Handler)!=HAL_DMA_STATE_BUSY)//
        {
            CMOS_Frame_TakeOver=1;
        }
    }
    //HAL_DMA_IRQHandler(&DMA_DCMI_Handler);
}


//DCMI中断服务函数
void DCMI_IRQHandler(void)
{

    HAL_DCMI_IRQHandler(&DCMI_Handler);//此函数会调用HAL_DCMI_FrameEventCallback回调函数

}

void HAL_DCMI_VsyncEventCallback(DCMI_HandleTypeDef *hdcmi)
{
    //每次帧同步来临是重新设置一次DMA 传输数据
    //DCMI_DMA_Init((u32)Img_Frame_Buffer,img_size/4);
   // CMOS_Frame_TakeOver=1;
}

int main(void)
{
    Usart4RevState=0;
    CMOS_Frame_TakeOver=0;


        Cache_Enable();//打开 L1-Cache
        HAL_Init();//初始化 HAL 库,可修改中断优先级分组

    SystemClock_Config();
   delay_init(400);//延时
   GPIO_Init();

    uart4_init(115200);   
    SimSPI_Init();
    NOIL300A_Init();   
    DCMI_Init();
    DCMI_DMA_Init((u32)Img_Frame_Buffer,img_size/4);


        while(1)
        {


        CMOS_Test();//用串口传出测试
        }
}

void CMOS_Test()
{
    u32 uPixNum=0;

    if(CMOS_Frame_TakeOver==1)//接收完一帧图像
    {


        for(uPixNum=0;uPixNum<img_size;uPixNum++)
        {
            UART4_SendChar(Img_Frame_Buffer[uPixNum]);//传出测试查看数据
        }

        CMOS_Frame_TakeOver=0;

    }

}
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

  /** Supply configuration update enable
  */
  MODIFY_REG(PWR->CR3, PWR_CR3_SCUEN, 0);
  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  while ((PWR->D3CR & (PWR_D3CR_VOSRDY)) != PWR_D3CR_VOSRDY)
  {

  }
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 2;
  RCC_OscInitStruct.PLL.PLLN = 64;
  RCC_OscInitStruct.PLL.PLLP = 2;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  RCC_OscInitStruct.PLL.PLLFRACN = 0;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    //Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    //Error_Handler();
  }
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_UART4|RCC_PERIPHCLK_UART5
                              |RCC_PERIPHCLK_I2C1|RCC_PERIPHCLK_QSPI
                              |RCC_PERIPHCLK_FMC;
  PeriphClkInitStruct.FmcClockSelection = RCC_FMCCLKSOURCE_D1HCLK;
  PeriphClkInitStruct.QspiClockSelection = RCC_QSPICLKSOURCE_D1HCLK;
  PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
  PeriphClkInitStruct.I2c123ClockSelection = RCC_I2C123CLKSOURCE_D2PCLK1;
  if (HAL_RCCEx_PeriphCLKConfig(&amperiphClkInitStruct) != HAL_OK)
  {
    //Error_Handler();
  }
}

使用特权

评论回复

相关帖子

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

本版积分规则

432

主题

439

帖子

0

粉丝