个人之前接触过智能车比赛,手里留下了一个OV7620摄像头,由于项目需求需要测试一下摄像头探物性能,便捣鼓一番。
OV7620默认像素320*240=76800。存储需要75k内存空间。STM32F1保存不了,便上了STM32F4VGTx。
[STM32F4] STM32F407 捕获中断 进不去DMA 中断
OV7620的使用
采用 TIM输入捕捉触发DMA保存像素数据。帧信号启动后,行中断逐行启动DAM传输。
简单二值化后的效果图:
像素PCLK PA8 TIM1_CH1 上升沿触发 DMA传输
行中断HREF PA3 上升沿触发
场中断VSYNC PA2 下降沿触发
像素DATA PC0-7
arr和psc可以随意配置,对外部触发无影响。
void TIM1_CH1_Cap_Init(uint32_t arr,uint16_t psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBseInitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
NVIC_InitTypeDef NVIC_InitSructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_DOWN;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_TIM1);
TIM_TimeBseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBseInitStructure.TIM_Period=arr;
TIM_TimeBseInitStructure.TIM_Prescaler=psc;
TIM_TimeBaseInit(TIM1,&TIM_TimeBseInitStructure);
TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;
TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter=0x00;
TIM_ICInit(TIM1,&TIM_ICInitStructure);
TIM_Cmd(TIM1,ENABLE);
TIM_SelectCCDMA(TIM1,DISABLE);
TIM_DMACmd(TIM1,TIM_DMA_CC1,ENABLE);
}
DMA_InitTypeDef DMA_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能
DMA_DeInit(DMA2_Stream1);
while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE) {} //等待DMA2_Stream1可配置
/* 配置 DMA Stream */
DMA_InitStructure.DMA_Channel = DMA_Channel_6;
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&GPIOC->IDR;//外设地址为
DMA_InitStructure.DMA_Memory0BaseAddr = (u32)&picture;//DMA 存储器0地址 uint8_t picture[240][320];
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//外设到存储器模式
DMA_InitStructure.DMA_BufferSize = 0;//数据传输量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//高优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; //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
void DMA_Enable(DMA_Stream_TypeDef *DMA_Streamx,u32 memadd,u16 ndtr)
{
DMA_Cmd(DMA_Streamx, DISABLE);
while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE) {}
DMA_Streamx->NDTR = ndtr;
DMA_Streamx->M0AR = memadd;
DMA_Cmd(DMA_Streamx, ENABLE);
}
void exit_config()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOC, ENABLE);//使能GPIOA,GPIOE时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; //KEY0 KEY1 KEY2对应引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOE2,3,4
GPIO_InitStructure.GPIO_Pin = 0xFF; //KEY0 KEY1 KEY2对应引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOE2,3,4
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource2);//PE2 连接到中断线2
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource3);//PE3 连接到中断线3
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource4);//PE4 连接到中断线4
/* 配置EXTI_Line2,3,4 */
EXTI_InitStructure.EXTI_Line = EXTI_Line2 ;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//中断线使能
EXTI_Init(&EXTI_InitStructure);//配置
/* 配置EXTI_Line2,3,4 */
EXTI_InitStructure.EXTI_Line = EXTI_Line3;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//中断线使能
EXTI_Init(&EXTI_InitStructure);//配置
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;//外部中断2
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
NVIC_Init(&NVIC_InitStructure);//配置
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;//外部中断3
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
NVIC_Init(&NVIC_InitStructure);//配置
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;//外部中断4
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;//抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
NVIC_Init(&NVIC_InitStructure);//配置
}
#define PIC_SIZE (320*240)
uint8_t picture[240][320];
int row=0;
int flag =0;
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168); //初始化延时函数
uart_init(115200); //初始化串口波特率为115200
exit_config();
DMA_Config();//DMA2,STEAM7,CH4,外设为串口1,存储器为SendBuff,长度为:SEND_BUF_SIZE.
// TIM5_CH1_Cap_Init(-1,0);
TIM1_CH1_Cap_Init(0XFFFFFFFF,84-1);
while(1)
{
// delay_ms(100);
flag=1;
while(flag!=3);
//printf("采集结束 %X\r\n",GPIOC->IDR);
uint8_t data=0;
uint8_t index=0;
fputc(0x01,0);
fputc(0xfe,0);
for(int j=0; j<240; j++)
for(int i=0; i<320; i++)
{
#if 0
fputc(picture[j][i],0);
#else //二值化
data<<=1;
if(picture[j][i]>128)
{
data|=1;
}
index++;
if(index==8)
{
fputc(data,0);
data =0;
index=0;
}
#endif
}
fputc(0xfe,0);
fputc(0x01,0);
delay_ms(500);
}
}
//外部中断2服务程序
void EXTI2_IRQHandler(void)//帧
{
// printf("*2");
EXTI_ClearITPendingBit(EXTI_Line2);//清除LINE2上的中断标志位
if(flag==1)
{
//开始启动
flag=2;//启动采集
row=0;
}
else if(flag==2)
{
flag=3;//采集结束
}
}
//外部中断3服务程序
void EXTI3_IRQHandler(void)//行
{
// printf("*3");
EXTI_ClearITPendingBit(EXTI_Line3); //清除LINE3上的中断标志位
if(flag==2)
{
if(row<240)
MYDMA_Enable(DMA2_Stream1,(u32)&picture[row][0],320);
row++;
}
}
//外部中断4服务程序
void EXTI4_IRQHandler(void)
{
printf("*4");
EXTI_ClearITPendingBit(EXTI_Line4);//清除LINE4上的中断标志位
}
需要工程源码的请留言