目前有个DEMO需要从FPGA高速接入数据,我选用DCMI+DMA双缓冲的方式来接收数据。参考的正点原子的Camera实验。做了一个简单的demo,是拿正点原子的跑马灯程序作为基础工程文件,然后添加DCMI的代码。
[mw_shl_code=c,true]#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
/************************************************
ALIENTEK 阿波罗STM32H7开发板 实验1
跑马灯实验-HAL库版本
技术支持:
www.openedv.com
淘宝店铺:http://eboard.taobao.com
关注微信公众平台微信号:"正点原子",免费获取STM32资料。
广州市星翼电子科技有限公司
作者:正点原子 @ALIENTEK
************************************************/
DCMI_HandleTypeDef DCMI_Handler; //DCMI句柄
DMA_HandleTypeDef DMADMCI_Handler; //DMA句柄
#define jpeg_buf_size 30*1024*1024 //定义JPEG数据缓存jpeg_buf的大小(1*4M字节)
#define jpeg_line_size 180 //定义DMA接收数据时,一行数据的最大值
u32 dcmi_line_buf[2][jpeg_line_size]; //RGB屏时,摄像头采用一行一行读取,定义行缓存
u32 jpeg_data_buf[jpeg_buf_size] __attribute__((at(0XC0000000+1280*800*2)));//JPEG数据缓存buf,定义在LCD帧缓存之后
static u32 line_buf_num = 0;
static u32 frame_num = 0;
void (*dcmi_rx_callback)(void);
void DCMI_Init(void)
{
DCMI_Handler.Instance = DCMI;
DCMI_Handler.Init.SynchroMode = DCMI_SYNCHRO_HARDWARE;
DCMI_Handler.Init.PCKPolarity = DCMI_PCKPOLARITY_RISING;
DCMI_Handler.Init.VSPolarity = DCMI_VSPOLARITY_LOW;
DCMI_Handler.Init.HSPolarity = DCMI_HSPOLARITY_LOW;
DCMI_Handler.Init.CaptureRate = DCMI_CR_ALL_FRAME;
DCMI_Handler.Init.ExtendedDataMode = DCMI_EXTEND_DATA_8B;
HAL_DCMI_Init(&DCMI_Handler);
DCMI->IER=0x0;
__HAL_DCMI_ENABLE_IT(&DCMI_Handler, DCMI_IT_FRAME);
__HAL_DCMI_ENABLE(&DCMI_Handler);
}
void HAL_DCMI_MspInit(DCMI_HandleTypeDef* hdcmi)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_DCMI_CLK_ENABLE(); //使能DCMI时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
__HAL_RCC_GPIOB_CLK_ENABLE(); //使能GPIOB时钟
__HAL_RCC_GPIOC_CLK_ENABLE(); //使能GPIOC时钟
__HAL_RCC_GPIOD_CLK_ENABLE(); //使能GPIOD时钟
__HAL_RCC_GPIOH_CLK_ENABLE(); //使能GPIOH时钟
//初始化PA6
GPIO_Initure.Pin=GPIO_PIN_6;
GPIO_Initure.Mode=GPIO_MODE_AF_PP; //推挽复用
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //高速
GPIO_Initure.Alternate=GPIO_AF13_DCMI; //复用为DCMI
HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化
//PB7,8,9
GPIO_Initure.Pin=GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
HAL_GPIO_Init(GPIOB,&GPIO_Initure); //初始化
//PC6,7,8,9,11
GPIO_Initure.Pin=GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|
GPIO_PIN_9|GPIO_PIN_11;
HAL_GPIO_Init(GPIOC,&GPIO_Initure); //初始化
//PD3
GPIO_Initure.Pin=GPIO_PIN_3;
HAL_GPIO_Init(GPIOD,&GPIO_Initure); //初始化
//PH8
GPIO_Initure.Pin=GPIO_PIN_8;
HAL_GPIO_Init(GPIOH,&GPIO_Initure); //初始化
HAL_NVIC_SetPriority(DCMI_IRQn,2,2); //抢占优先级1,子优先级2
HAL_NVIC_EnableIRQ(DCMI_IRQn); //使能DCMI中断
}
void DCMI_DMA_Init(u32 mem0addr,u32 mem1addr,u16 memsize,u32 memblen,u32 meminc)
{
__HAL_RCC_DMA1_CLK_ENABLE(); //使能DMA1时钟
__HAL_LINKDMA(&DCMI_Handler,DMA_Handle,DMADMCI_Handler); //将DMA与DCMI联系起来
__HAL_DMA_DISABLE_IT(&DMADMCI_Handler,DMA_IT_TC); //先关闭DMA传输完成中断(否则在使用MCU屏的时候会出现花屏的情况)
DMADMCI_Handler.Instance=DMA1_Stream1; //DMA1数据流1
DMADMCI_Handler.Init.Request=DMA_REQUEST_DCMI; //DCMI的DMA请求
DMADMCI_Handler.Init.Direction=DMA_PERIPH_TO_MEMORY; //外设到存储器
DMADMCI_Handler.Init.PeriphInc=DMA_PINC_DISABLE; //外设非增量模式
DMADMCI_Handler.Init.MemInc=meminc; //存储器增量模式
DMADMCI_Handler.Init.PeriphDataAlignment=DMA_PDATAALIGN_WORD; //外设数据长度:32位
DMADMCI_Handler.Init.MemDataAlignment=memblen; //存储器数据长度:8/16/32位
DMADMCI_Handler.Init.Mode=DMA_CIRCULAR; //使用循环模式
DMADMCI_Handler.Init.Priority=DMA_PRIORITY_HIGH; //高优先级
DMADMCI_Handler.Init.FIFOMode=DMA_FIFOMODE_ENABLE; //使能FIFO
DMADMCI_Handler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_HALFFULL; //使用1/2的FIFO
DMADMCI_Handler.Init.MemBurst=DMA_MBURST_SINGLE; //存储器突发传输
DMADMCI_Handler.Init.PeriphBurst=DMA_PBURST_SINGLE; //外设突发单次传输
HAL_DMA_DeInit(&DMADMCI_Handler); //先清除以前的设置
HAL_DMA_Init(&DMADMCI_Handler); //初始化DMA
//在开启DMA之前先使用__HAL_UNLOCK()解锁一次DMA,因为HAL_DMA_Statrt()HAL_DMAEx_MultiBufferStart()
//这两个函数一开始要先使用__HAL_LOCK()锁定DMA,而函数__HAL_LOCK()会判断当前的DMA状态是否为锁定状态,如果是
//锁定状态的话就直接返回HAL_BUSY,这样会导致函数HAL_DMA_Statrt()和HAL_DMAEx_MultiBufferStart()后续的DMA配置
//程序直接被跳过!DMA也就不能正常工作,为了避免这种现象,所以在启动DMA之前先调用__HAL_UNLOC()先解锁一次DMA。
__HAL_UNLOCK(&DMADMCI_Handler);
if(mem1addr==0) //开启DMA,不使用双缓冲
{
HAL_DMA_Start(&DMADMCI_Handler,(u32)&DCMI->DR,mem0addr,memsize);
__HAL_DMA_ENABLE_IT(&DMADMCI_Handler,DMA_IT_TC); //开启传输完成中断
HAL_NVIC_SetPriority(DMA1_Stream1_IRQn,2,3); //DMA中断优先级
HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
}
else //使用双缓冲
{
HAL_DMAEx_MultiBufferStart(&DMADMCI_Handler,(u32)&DCMI->DR,mem0addr,mem1addr,memsize);//开启双缓冲
__HAL_DMA_ENABLE_IT(&DMADMCI_Handler,DMA_IT_TC); //开启传输完成中断
HAL_NVIC_SetPriority(DMA1_Stream1_IRQn,2,3); //DMA中断优先级
HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
}
}
void rgblcd_dcmi_rx_callback(void)
{
u32 wData, powData;
u8 newData, oldData = 0;
uint32_t i,j = 0;
if(DMA2_Stream1->CR&(1<<19))//DMA使用buf1,读取buf0
{
//pbuf=dcmi_line_buf[0];
}else //DMA使用buf0,读取buf1
{
//pbuf=dcmi_line_buf[1];
}
for (i=0; i<180; i++) {
wData = dcmi_line_buf[0]
;
for (j=0; j<4; j++) {
powData = 8*j;
newData = (wData >> powData) & 0xff;
if (newData != 0 && ((newData - oldData) != 1)) {
break;
}
oldData=newData;
}
}
line_buf_num++;
}
void DMA1_Stream1_IRQHandler(void)
{
if(__HAL_DMA_GET_FLAG(&DMADMCI_Handler,DMA_FLAG_TCIF1_5)!=RESET)//DMA传输完成
{
__HAL_DMA_CLEAR_FLAG(&DMADMCI_Handler,DMA_FLAG_TCIF1_5);//清除DMA传输完成中断标志位
dcmi_rx_callback();
}
}
int main(void)
{
Cache_Enable(); //打开L1-Cache
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(160,5,2,4); //设置时钟,400Mhz
delay_init(400); //延时初始化
uart_init(115200); //串口初始化
LED_Init(); //初始化LED
DCMI_Init(); //DCMI配置
dcmi_rx_callback=rgblcd_dcmi_rx_callback;//RGB屏接收数据回调函数
//DCMI_DMA_Init((u32)dcmi_line_buf[0],(u32)dcmi_line_buf[1],180,DMA_MDATAALIGN_WORD,DMA_MINC_ENABLE);
DCMI_DMA_Init((u32)dcmi_line_buf[0],0,180,DMA_MDATAALIGN_WORD,DMA_MINC_ENABLE);
__HAL_DMA_ENABLE(&DMADMCI_Handler); //使能DMA
DCMI->CR|=DCMI_CR_CAPTURE; //DCMI捕获使能
while(1)
{
}
}
[/mw_shl_code]
是可以接收到数据的,然后尝试使用CubeMX生成工程,只在CubeMX中设置了RCC时钟,其余全部默认。
生成之后也在main.c中添加和上面同样的代码,并且在stm32h7xx_hal_conf.h中放开了DCMI,DMA相关的宏。但是连DMA1_Stream1_IRQHandler()都进不去。
尝试直接使用CubeMX添加上DCMI DMA相关配置:
H7的例程还是少了点,后面还会更新吗
一周热门 更多>