用F4、OV9655和DCMI通过DMA双缓存到内部SRAM,然后再把两个缓存的图像片段搬到外部SRAM组成一帧图像,最后在另一外部SRAM数组中转化成RGB565格式在通过LCD_WriteRAM()显示到LCD上的配置问题: 1.我想用以上方法获取YUV422格式的图片,是否OV9655要设定成YUV422输出,并且输出格式是YUYV顺序;然后DCMI也设定成YUV422输出,而且DMA时是输出32位的字?这里能否设成16位的半字?
2.然后进内部SRAM数组buf[]时,用半字传送,是否也是buf[]={Y0U0Y1V1Y2U2.......}这个顺序?
3.从外部SRAM把YUV422格式转化成RGB565格式图片时,RGB在半字中的顺序是什么?送LCD显示时是否可以用函数LCD__WriteRAM()按顺序p0p1p2p3......半字半字的送?
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
//uint32_t Dma_bufsize= PICTURE_dma_bufsize;
extern u16 PICTURE_buf0;
extern u16 PICTURE_buf1;
extern u16 *PICTURE_data_buf;
extern void PICTURE_data_process(void); //PICTURE数据处理函数
extern NVIC_InitTypeDef NVIC_InitStructure;
void OV9655_Init(ImageFormat_TypeDef ImageFormat)
{
DCMI_InitTypeDef DCMI_InitStructure;
/*** Configures the DCMI to interface with the OV9655 camera module ***/
/* Enable DCMI clock */
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);
/* DCMI configuration */
DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous; //连续捕获:DCMI_CaptureMode_Continuous;单帧:DCMI_CaptureMode_SnapShot
DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Falling;
DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;
DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_High;
DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame; //All_Frame;DCMI_CaptureRate_1of4_Frame
DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;
DCMI_Init(&DCMI_InitStructure);
// DCMI_ITConfig(DCMI_IT_FRAME,ENABLE);//开启帧中断
DCMI_Cmd(ENABLE); //DCMI使能
NVIC_InitStructure.NVIC_IRQChannel = DCMI_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority =2; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、
}
//DCMI DMA配置
//memaddr:存储器地址 将要存储摄像头数据的内存地址(也可以是外设地址)
//DMA_BufferSize:存储器长度 0~65535
//DMA_MemoryDataSize:存储器位宽 @defgroup DMA_memory_data_size MA_MemoryDataSize_Byte/DMA_MemoryDataSize_HalfWord/DMA_MemoryDataSize_Word
//DMA_MemoryInc:存储器增长方式 @defgroup DMA_memory_incremented_mode /** @defgroup DMA_memory_incremented_mode : DMA_MemoryInc_Enable/DMA_MemoryInc_Disable
void DCMI_DMA_Init(u32 DMA_Memory0BaseAddr,u32 DMA_Memory1BaseAddr,u16 DMA_BufferSize,u32 DMA_MemoryDataSize,u32 DMA_MemoryInc)
{
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能
DMA_DeInit(DMA2_Stream1);//等待DMA2_Stream1
while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE){}//等待DMA2_Stream1可配置
/* 配置 DMA Stream */
DMA_InitStructure.DMA_Channel = DMA_Channel_1; //通道1 DCMI通道
DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;//外设地址为CMI->DR
DMA_InitStructure.DMA_Memory0BaseAddr = DMA_Memory0BaseAddr;//DMA 存储器0地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//外设到存储器模式
DMA_InitStructure.DMA_BufferSize = DMA_BufferSize;//数据传输量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc;//存储器增量模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;//外设数据长度:32位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize;//存储器数据长度
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// 使用循环模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; //FIFO模式
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;//使用全FIFO
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//外设突发单次传输
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//存储器突发单次传输
DMA_Init(DMA2_Stream1, &DMA_InitStructure);//初始化DMA Stream
if(DMA_Memory1BaseAddr)
{
DMA_DoubleBufferModeCmd(DMA2_Stream1,ENABLE);//双缓冲模式
DMA_MemoryTargetConfig(DMA2_Stream1,DMA_Memory1BaseAddr,DMA_Memory_1);//配置目标地址1
DMA_ITConfig(DMA2_Stream1,DMA_IT_TC,ENABLE);//开启传输完成中断
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0; //子优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、
}
}
//DCMI,启动传输
void DCMI_Start(void)
{
LCD_SetCursor(0,0);
LCD_WriteRAM_Prepare(); //开始写入GRAM
DMA_Cmd(DMA2_Stream1, ENABLE);//开启DMA2,Stream1
DCMI_CaptureCmd(ENABLE);//DCMI捕获使能
}
//DCMI,关闭传输
void DCMI_Stop(void)
{
DCMI_CaptureCmd(DISABLE);//DCMI捕获使关闭
while(DCMI->CR&0X01); //等待传输结束
DMA_Cmd(DMA2_Stream1,DISABLE);//关闭DMA2,Stream1
}
//DCMI中断服务函数
void DCMI_IRQHandler(void)
{
uint16_t * p;
uint32_t i;
p= PICTURE_data_buf;
if(DCMI_GetITStatus(DCMI_IT_FRAME)==SET)//捕获到一帧图像
{
DCMI_Stop();
PICTURE_data_process(); //jpeg数据处理
DCMI_ClearITPendingBit(DCMI_IT_FRAME);//清除帧中断
// LED1=!LED1;
p=(uint16_t)((uint32_t)0x68000000);
for(i=0;i<320*240;i++)
{
LCD_WriteRAM(*p++);
}
ov_frame++;
DCMI_Start();
}
}
void (*dcmi_rx_callback)(void);//DCMI DMA接收回调函数
//DMA2_Stream1中断服务函数(仅双缓冲模式会用到)
void DMA2_Stream1_IRQHandler(void)
{
if(DMA_GetFlagStatus(DMA2_Stream1,DMA_FLAG_TCIF1)==SET)//DMA2_Steam1,传输完成标志
{
DMA_ClearFlag(DMA2_Stream1,DMA_FLAG_TCIF1);//清除传输完成中断
dcmi_rx_callback(); //执行摄像头接收回调函数,读取数据等操作在这里面处理
}
}
#define BUFFER_SIZE 0x400 /*定义读写BUFFER大小*/
#define WRITE_READ_ADDR 0x0000 /*定义SRAM读写的地址*/
#define Bank1_SRAM3_ADDR ((uint32_t)0x68000000)
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
ErrorStatus HSEStartUpStatus;
u16 TxBuffer[BUFFER_SIZE];
u16 RxBuffer[BUFFER_SIZE];
u32 WriteReadStatus = 0, Index = 0;
u8 count=0;
extern Camera_TypeDef Camera;
extern ImageFormat_TypeDef ImageFormat;
extern __IO uint8_t ValueMax;
extern const uint8_t *ImageForematArray[];
#define PICTURE_dma_bufsize (uint32_t)0xF00 //定义JPEG DMA接收时数据缓存PICTURE_buf0/1的大小(*4字节),320X24X2/4=3840,每帧10次DMA中断
volatile u32 PICTURE_data_len=0; //buf中的PICTURE有效数据长度(*4字节)
volatile u8 PICTURE_data_ok=0; //PICTURE数据采集完成标志
//0,数据没有采集完;
//1,数据采集完了,但是还没处理;
//2,数据已经处理完成了,可以开始下一帧接收
#define SRAM3_BASE ((uint32_t)0x20020000) /*!< SRAM3(64 KB) base address in the alias region */
u16 *PICTURE_buf0= (u16 *)((uint32_t)SRAM3_BASE); //PICTURE数据缓存buf0,内部SRAM1
u16 *PICTURE_buf1= (u16 *)(SRAM3_BASE+PICTURE_dma_bufsize*4); //PICTURE数据缓存buf1,内部SRAM1
u16 *PICTURE_data_buf= (uint16_t *) Bank1_SRAM3_ADDR ; //(SRAM1_BASE+PICTURE_dma_bufsize*4*2); //PICTURE数据缓存buf,外部SRAM
/* Private function prototypes -----------------------------------------------*/
void ADC_Config(void);
//当采集完一帧JPEG数据后,调用此函数,切换JPEG BUF.开始下一帧采集.
void PICTURE_data_process(void)
{
u16 i;
u16 rlen;//剩余数据长度
u16 *pbuf;
if(PICTURE_data_ok==0) //jpeg数据还未采集完?
{
DMA_Cmd(DMA2_Stream1,DISABLE); //停止当前传输
while(DMA_GetCmdStatus(DMA2_Stream1) != DISABLE); //等待DMA2_Stream1可配置
rlen=PICTURE_dma_bufsize-DMA_GetCurrDataCounter(DMA2_Stream1);//得到剩余数据长度
pbuf=(uint16_t*)(PICTURE_data_buf+PICTURE_data_len*4);//偏移到有效数据末尾,继续添加
if(DMA2_Stream1->CR&(1<<19))for(i=0;i<rlen*2;i++)pbuf[i]=PICTURE_buf1[i];//读取buf1里面的剩余数据
else for(i=0;i<rlen*2;i++)pbuf[i]=PICTURE_buf0[i];//读取buf0里面的剩余数据
PICTURE_data_len+=rlen; //加上剩余长度
PICTURE_data_ok=2; //标记JPEG数据采集完按成,等待其他函数处理
}
if(PICTURE_data_ok==2) //上一次的jpeg数据已经被处理了
{ DMA_SetCurrDataCounter(DMA2_Stream1,PICTURE_dma_bufsize);//传输长度为jpeg_buf_size*4字节
DMA_Cmd(DMA2_Stream1,ENABLE); //重新传输
PICTURE_data_ok=0; //标记数据未采集
PICTURE_data_len=0; //数据重新开始
}
}
//jpeg数据接收回调函数
void PICTURE_dcmi_rx_callback(void)
{
u16 i;
u16 *pbuf;
pbuf=(uint16_t*)(PICTURE_data_buf+PICTURE_data_len*4);//偏移到有效数据末尾
if(DMA2_Stream1->CR&(1<<19))//buf0已满,DMA正在处理buf1
{
for(i=0;i<ICTURE_dma_bufsize*2;i++)pbuf[i]=PICTURE_buf0[i];//读取buf0里面的数据
PICTURE_data_len+=PICTURE_dma_bufsize;//偏移
}else //buf1已满,DMA正在处理buf0
{
for(i=0;i<ICTURE_dma_bufsize*2;i++)pbuf[i]=PICTURE_buf1[i];//读取buf1里面的数据
PICTURE_data_len+=PICTURE_dma_bufsize;//偏移
}
}
int main(void)
{
u8 keynum;
u32 i;
u16 p=0;
uint32_t WriteAddr=0;
/* SysTick end of count event each 10ms */
RCC_GetClocksFreq(&RCC_Clocks);
SysTick_Config(RCC_Clocks.HCLK_Frequency / 100);
GPIO_KEY_Config(); //按键使用的GPIO初始化
/* Initialize the LCD */
STM324xG_LCD_Init();
LCD_Clear(Red);
LCD_SetTextColor(White);
LCD_LOG_SetHeader("STM32F407 Camera Demo");
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
SRAM_Init();
/* Initializes the DCMI interface (I2C and GPIO) used to configure the camera */
OV9655_HW_Init();
OV9655_ReadID(&OV9655_Camera_ID);
if(OV9655_Camera_ID.PID == 0x96)
{
Camera = OV9655_CAMERA;
sprintf((char*)buffer, "OV9655 Camera ID 0x%x", OV9655_Camera_ID.PID);
}
LCD_SetTextColor(LCD_COLOR_YELLOW);
LCD_DisplayStringLine(LINE(4), (uint8_t*)buffer);
LCD_SetTextColor(LCD_COLOR_WHITE);
Delay(200);
/* Configure the Camera module mounted on STM324xG-EVAL board */
OV9655_QVGAConfig();
OV9655_Init(BMP_QVGA);
// /* Enable DMA2 stream 1 and DCMI interface then start image capture */
DMA_Cmd(DMA2_Stream1, ENABLE);
DCMI_Cmd(ENABLE);
// /* Insert 100ms delay: wait 100ms */
Delay(200);
dcmi_rx_callback=PICTURE_dcmi_rx_callback;//回调函数
DCMI_CaptureCmd(ENABLE);
/* LCD Display window */
LCD_SetDisplayWindow(239, 319, 240, 320);
LCD_WriteReg(LCD_REG_3, 0x1038);
LCD_WriteRAM_Prepare();
ImageFormat = BMP_QVGA;
DCMI_DMA_Init((u32)FSMC_LCD_ADDRESS,0,1,DMA_MemoryDataSize_HalfWord,DMA_MemoryInc_Disable);//DCMI DMA配置
DCMI_Start();
while(1)
{
/* 按键按下时为低电平,如果按键按下则改变指示灯状态 */
keynum =ReadKeyDown();
if(keynum != 0)
{
switch(keynum)
{
case 1:
LCD_WriteReg(LCD_REG_3, 0x1030);
DCMI_DMA_Init((u32)PICTURE_buf0,(u32)PICTURE_buf1,PICTURE_dma_bufsize,DMA_MemoryDataSize_Word,DMA_MemoryInc_Enable);//DCMI DMA配置(双缓冲模式)
DMA_ITConfig(DMA2_Stream1,DMA_IT_TC,ENABLE); //开启传输完成中断
DCMI_ITConfig(DCMI_IT_FRAME,ENABLE); //开启帧中断
DCMI_Start(); //启动传输
break;
case 2:
OV9655_Init(BMP_QVGA);
LCD_WriteReg(LCD_REG_3, 0x1038);
DCMI_ITConfig(DCMI_IT_FRAME,DISABLE);//开启帧中断
DMA_ITConfig(DMA2_Stream1,DMA_IT_TC,DISABLE);//开启传输完成中断
DCMI_DMA_Init((u32)FSMC_LCD_ADDRESS,0,1,DMA_MemoryDataSize_HalfWord,DMA_MemoryInc_Disable);//DCMI DMA配置
DCMI_Start();
break;
case 3:
// Led_Turn_on(2); /* 改变指示灯3状态 */
break;
case 4:
// Led_Turn_on(3); /* 改变指示灯4状态 */
break;
default:
;
}
/* 等待按键释放 */
while(keynum == ReadKeyDown());
p=0x1234;
/* Insert 100ms delay */
Delay(10);
ADCVal = 130;
OV9655_BrightnessConfig(ADCVal);
}
}
}
//uint32_t Dma_bufsize= PICTURE_dma_bufsize;
extern u16 PICTURE_buf0;
extern u16 PICTURE_buf1;
extern u16 *PICTURE_data_buf;
extern void PICTURE_data_process(void); //PICTURE数据处理函数
extern NVIC_InitTypeDef NVIC_InitStructure;
void OV9655_Init(ImageFormat_TypeDef ImageFormat)
{
DCMI_InitTypeDef DCMI_InitStructure;
/*** Configures the DCMI to interface with the OV9655 camera module ***/
/* Enable DCMI clock */
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);
/* DCMI configuration */
DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous; //连续捕获:DCMI_CaptureMode_Continuous;单帧:DCMI_CaptureMode_SnapShot
DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Falling;
DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;
DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_High;
DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame; //All_Frame;DCMI_CaptureRate_1of4_Frame
DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;
DCMI_Init(&DCMI_InitStructure);
// DCMI_ITConfig(DCMI_IT_FRAME,ENABLE);//开启帧中断
DCMI_Cmd(ENABLE); //DCMI使能
NVIC_InitStructure.NVIC_IRQChannel = DCMI_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority =2; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、
}
//DCMI DMA配置
//memaddr:存储器地址 将要存储摄像头数据的内存地址(也可以是外设地址)
//DMA_BufferSize:存储器长度 0~65535
//DMA_MemoryDataSize:存储器位宽 @defgroup DMA_memory_data_size MA_MemoryDataSize_Byte/DMA_MemoryDataSize_HalfWord/DMA_MemoryDataSize_Word
//DMA_MemoryInc:存储器增长方式 @defgroup DMA_memory_incremented_mode /** @defgroup DMA_memory_incremented_mode : DMA_MemoryInc_Enable/DMA_MemoryInc_Disable
void DCMI_DMA_Init(u32 DMA_Memory0BaseAddr,u32 DMA_Memory1BaseAddr,u16 DMA_BufferSize,u32 DMA_MemoryDataSize,u32 DMA_MemoryInc)
{
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能
DMA_DeInit(DMA2_Stream1);//等待DMA2_Stream1
while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE){}//等待DMA2_Stream1可配置
/* 配置 DMA Stream */
DMA_InitStructure.DMA_Channel = DMA_Channel_1; //通道1 DCMI通道
DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;//外设地址为CMI->DR
DMA_InitStructure.DMA_Memory0BaseAddr = DMA_Memory0BaseAddr;//DMA 存储器0地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//外设到存储器模式
DMA_InitStructure.DMA_BufferSize = DMA_BufferSize;//数据传输量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc;//存储器增量模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;//外设数据长度:32位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize;//存储器数据长度
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// 使用循环模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; //FIFO模式
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;//使用全FIFO
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//外设突发单次传输
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//存储器突发单次传输
DMA_Init(DMA2_Stream1, &DMA_InitStructure);//初始化DMA Stream
if(DMA_Memory1BaseAddr)
{
DMA_DoubleBufferModeCmd(DMA2_Stream1,ENABLE);//双缓冲模式
DMA_MemoryTargetConfig(DMA2_Stream1,DMA_Memory1BaseAddr,DMA_Memory_1);//配置目标地址1
DMA_ITConfig(DMA2_Stream1,DMA_IT_TC,ENABLE);//开启传输完成中断
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0; //子优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、
}
}
//DCMI,启动传输
void DCMI_Start(void)
{
LCD_SetCursor(0,0);
LCD_WriteRAM_Prepare(); //开始写入GRAM
DMA_Cmd(DMA2_Stream1, ENABLE);//开启DMA2,Stream1
DCMI_CaptureCmd(ENABLE);//DCMI捕获使能
}
//DCMI,关闭传输
void DCMI_Stop(void)
{
DCMI_CaptureCmd(DISABLE);//DCMI捕获使关闭
while(DCMI->CR&0X01); //等待传输结束
DMA_Cmd(DMA2_Stream1,DISABLE);//关闭DMA2,Stream1
}
//DCMI中断服务函数
void DCMI_IRQHandler(void)
{
uint16_t * p;
uint32_t i;
p= PICTURE_data_buf;
if(DCMI_GetITStatus(DCMI_IT_FRAME)==SET)//捕获到一帧图像
{
DCMI_Stop();
PICTURE_data_process(); //jpeg数据处理
DCMI_ClearITPendingBit(DCMI_IT_FRAME);//清除帧中断
// LED1=!LED1;
p=(uint16_t)((uint32_t)0x68000000);
for(i=0;i<320*240;i++)
{
LCD_WriteRAM(*p++);
}
ov_frame++;
DCMI_Start();
}
}
void (*dcmi_rx_callback)(void);//DCMI DMA接收回调函数
//DMA2_Stream1中断服务函数(仅双缓冲模式会用到)
void DMA2_Stream1_IRQHandler(void)
{
if(DMA_GetFlagStatus(DMA2_Stream1,DMA_FLAG_TCIF1)==SET)//DMA2_Steam1,传输完成标志
{
DMA_ClearFlag(DMA2_Stream1,DMA_FLAG_TCIF1);//清除传输完成中断
dcmi_rx_callback(); //执行摄像头接收回调函数,读取数据等操作在这里面处理
}
}
#define BUFFER_SIZE 0x400 /*定义读写BUFFER大小*/
#define WRITE_READ_ADDR 0x0000 /*定义SRAM读写的地址*/
#define Bank1_SRAM3_ADDR ((uint32_t)0x68000000)
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
ErrorStatus HSEStartUpStatus;
u16 TxBuffer[BUFFER_SIZE];
u16 RxBuffer[BUFFER_SIZE];
u32 WriteReadStatus = 0, Index = 0;
u8 count=0;
extern Camera_TypeDef Camera;
extern ImageFormat_TypeDef ImageFormat;
extern __IO uint8_t ValueMax;
extern const uint8_t *ImageForematArray[];
#define PICTURE_dma_bufsize (uint32_t)0xF00 //定义JPEG DMA接收时数据缓存PICTURE_buf0/1的大小(*4字节),320X24X2/4=3840,每帧10次DMA中断
volatile u32 PICTURE_data_len=0; //buf中的PICTURE有效数据长度(*4字节)
volatile u8 PICTURE_data_ok=0; //PICTURE数据采集完成标志
//0,数据没有采集完;
//1,数据采集完了,但是还没处理;
//2,数据已经处理完成了,可以开始下一帧接收
#define SRAM3_BASE ((uint32_t)0x20020000) /*!< SRAM3(64 KB) base address in the alias region */
u16 *PICTURE_buf0= (u16 *)((uint32_t)SRAM3_BASE); //PICTURE数据缓存buf0,内部SRAM1
u16 *PICTURE_buf1= (u16 *)(SRAM3_BASE+PICTURE_dma_bufsize*4); //PICTURE数据缓存buf1,内部SRAM1
u16 *PICTURE_data_buf= (uint16_t *) Bank1_SRAM3_ADDR ; //(SRAM1_BASE+PICTURE_dma_bufsize*4*2); //PICTURE数据缓存buf,外部SRAM
/* Private function prototypes -----------------------------------------------*/
void ADC_Config(void);
//当采集完一帧JPEG数据后,调用此函数,切换JPEG BUF.开始下一帧采集.
void PICTURE_data_process(void)
{
u16 i;
u16 rlen;//剩余数据长度
u16 *pbuf;
if(PICTURE_data_ok==0) //jpeg数据还未采集完?
{
DMA_Cmd(DMA2_Stream1,DISABLE); //停止当前传输
while(DMA_GetCmdStatus(DMA2_Stream1) != DISABLE); //等待DMA2_Stream1可配置
rlen=PICTURE_dma_bufsize-DMA_GetCurrDataCounter(DMA2_Stream1);//得到剩余数据长度
pbuf=(uint16_t*)(PICTURE_data_buf+PICTURE_data_len*4);//偏移到有效数据末尾,继续添加
if(DMA2_Stream1->CR&(1<<19))for(i=0;i<rlen*2;i++)pbuf[i]=PICTURE_buf1[i];//读取buf1里面的剩余数据
else for(i=0;i<rlen*2;i++)pbuf[i]=PICTURE_buf0[i];//读取buf0里面的剩余数据
PICTURE_data_len+=rlen; //加上剩余长度
PICTURE_data_ok=2; //标记JPEG数据采集完按成,等待其他函数处理
}
if(PICTURE_data_ok==2) //上一次的jpeg数据已经被处理了
{ DMA_SetCurrDataCounter(DMA2_Stream1,PICTURE_dma_bufsize);//传输长度为jpeg_buf_size*4字节
DMA_Cmd(DMA2_Stream1,ENABLE); //重新传输
PICTURE_data_ok=0; //标记数据未采集
PICTURE_data_len=0; //数据重新开始
}
}
//jpeg数据接收回调函数
void PICTURE_dcmi_rx_callback(void)
{
u16 i;
u16 *pbuf;
pbuf=(uint16_t*)(PICTURE_data_buf+PICTURE_data_len*4);//偏移到有效数据末尾
if(DMA2_Stream1->CR&(1<<19))//buf0已满,DMA正在处理buf1
{
for(i=0;i<ICTURE_dma_bufsize*2;i++)pbuf[i]=PICTURE_buf0[i];//读取buf0里面的数据
PICTURE_data_len+=PICTURE_dma_bufsize;//偏移
}else //buf1已满,DMA正在处理buf0
{
for(i=0;i<ICTURE_dma_bufsize*2;i++)pbuf[i]=PICTURE_buf1[i];//读取buf1里面的数据
PICTURE_data_len+=PICTURE_dma_bufsize;//偏移
}
}
int main(void)
{
u8 keynum;
u32 i;
u16 p=0;
uint32_t WriteAddr=0;
/* SysTick end of count event each 10ms */
RCC_GetClocksFreq(&RCC_Clocks);
SysTick_Config(RCC_Clocks.HCLK_Frequency / 100);
GPIO_KEY_Config(); //按键使用的GPIO初始化
/* Initialize the LCD */
STM324xG_LCD_Init();
LCD_Clear(Red);
LCD_SetTextColor(White);
LCD_LOG_SetHeader("STM32F407 Camera Demo");
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
SRAM_Init();
/* Initializes the DCMI interface (I2C and GPIO) used to configure the camera */
OV9655_HW_Init();
OV9655_ReadID(&OV9655_Camera_ID);
if(OV9655_Camera_ID.PID == 0x96)
{
Camera = OV9655_CAMERA;
sprintf((char*)buffer, "OV9655 Camera ID 0x%x", OV9655_Camera_ID.PID);
}
LCD_SetTextColor(LCD_COLOR_YELLOW);
LCD_DisplayStringLine(LINE(4), (uint8_t*)buffer);
LCD_SetTextColor(LCD_COLOR_WHITE);
Delay(200);
/* Configure the Camera module mounted on STM324xG-EVAL board */
OV9655_QVGAConfig();
OV9655_Init(BMP_QVGA);
// /* Enable DMA2 stream 1 and DCMI interface then start image capture */
DMA_Cmd(DMA2_Stream1, ENABLE);
DCMI_Cmd(ENABLE);
// /* Insert 100ms delay: wait 100ms */
Delay(200);
dcmi_rx_callback=PICTURE_dcmi_rx_callback;//回调函数
DCMI_CaptureCmd(ENABLE);
/* LCD Display window */
LCD_SetDisplayWindow(239, 319, 240, 320);
LCD_WriteReg(LCD_REG_3, 0x1038);
LCD_WriteRAM_Prepare();
ImageFormat = BMP_QVGA;
DCMI_DMA_Init((u32)FSMC_LCD_ADDRESS,0,1,DMA_MemoryDataSize_HalfWord,DMA_MemoryInc_Disable);//DCMI DMA配置
DCMI_Start();
while(1)
{
/* 按键按下时为低电平,如果按键按下则改变指示灯状态 */
keynum =ReadKeyDown();
if(keynum != 0)
{
switch(keynum)
{
case 1:
LCD_WriteReg(LCD_REG_3, 0x1030);
DCMI_DMA_Init((u32)PICTURE_buf0,(u32)PICTURE_buf1,PICTURE_dma_bufsize,DMA_MemoryDataSize_Word,DMA_MemoryInc_Enable);//DCMI DMA配置(双缓冲模式)
DMA_ITConfig(DMA2_Stream1,DMA_IT_TC,ENABLE); //开启传输完成中断
DCMI_ITConfig(DCMI_IT_FRAME,ENABLE); //开启帧中断
DCMI_Start(); //启动传输
break;
case 2:
OV9655_Init(BMP_QVGA);
LCD_WriteReg(LCD_REG_3, 0x1038);
DCMI_ITConfig(DCMI_IT_FRAME,DISABLE);//开启帧中断
DMA_ITConfig(DMA2_Stream1,DMA_IT_TC,DISABLE);//开启传输完成中断
DCMI_DMA_Init((u32)FSMC_LCD_ADDRESS,0,1,DMA_MemoryDataSize_HalfWord,DMA_MemoryInc_Disable);//DCMI DMA配置
DCMI_Start();
break;
case 3:
// Led_Turn_on(2); /* 改变指示灯3状态 */
break;
case 4:
// Led_Turn_on(3); /* 改变指示灯4状态 */
break;
default:
;
}
/* 等待按键释放 */
while(keynum == ReadKeyDown());
p=0x1234;
/* Insert 100ms delay */
Delay(10);
ADCVal = 130;
OV9655_BrightnessConfig(ADCVal);
}
}
}
E:BaiduYunDownloadSTM32F4STM32F439摄像头IMG_20160325_233438
一周热门 更多>