STM32F4读取OV7620

 

个人之前接触过智能车比赛,手里留下了一个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

1、TIM1外部触发配置

  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);

}

2、DMA配置


    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);            
}

3、IO口配置


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);//配置

}

4、主逻辑

#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上的中断标志位
}

源码下载:

链接:https://pan.baidu.com/s/17qYwMNoDK4mJjSFqUsr7zg 
提取码:6k8s 
复制这段内容后打开百度网盘手机App,操作更方便哦

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值