立即注册 登录
返回首页

fan52的个人空间

日志

STM32之OV7620调试记录

已有 390 次阅读2019-10-23 16:25 |个人分类:OV7620

最近学习STM32做了OV7620的相关调试工作,刚开始是很困难的,慢慢的搞清楚原理和配置之后就开始熟悉了,目前主要可以采用三种采集模式进行摄像头数据采集,基本过程差不多,分别是配置IO口,配置SCCB,配置采集控制方式(场、行、像素时钟),送显(可以采用两种送显方式,一是图像数据采集完送显,二是边采集边送显)。
1.GPIO直接采集,就是使用GPIO口直接采集摄像头的数据,这种方式需要高速的IO翻转速度,如果单片机速度不够很难实现(采用STM32F103c8t6完成实现)。具体过程:(1)将A0-A7接摄像头Y0-Y7,VSYNC、HREF、PCLK分别接B0-B2,SCL和SDA接B10和B11,RST接地,采用5V供电;(2)配置A0-A7为悬浮输入,摄像头数据就在GPIOA_ODR寄存器读取,配置SCCB,配置OV7620的寄存器(可以输出不同的分辨率和窗口,可以只输出亮度信息或彩色YUV输出),配置B0-B2为外部中断触发,分别控制场中断和行中断比较好实现,注意中断HREF是上升沿采集数据,场中断VSYNC是下降沿采集,配置中断优先级,场优先级要高于行,一场采集结束后给一个标志位,送显,或者每采集完一行就直接送显。
2.采用定时器捕获像素信号PCLK,用DMA传输,与GPIO采集不同的是,多了一个PCLK像素采集,这里可以将PCLK连接TIM_x设置成捕获模式,捕获到数据时触发DMA传输,依然需要控制场中断和行中断,以及送显。
3.采用DCMI接口进行采集,将Y0-Y7接STM32F4的DCMI接口D0-D7,VSYNC、HREF、PCLK接对应的DCMI_x,SCL和SDA使用GPIO模式,这里重点是DCMI的配置和DMA的配置,DMA的设备地址是DCMI,首地址是图像buffer的首地址或者是LCD_RAM(直接送显),采用硬件同步模式,VSYNC高电平有效(下降沿),HREF低电平有效(上升沿),PCLK上升沿触发,必须配置好采集的时钟控制才能出图像。
可以多参考原子和野火的例程,原子是OV2640,重点弄清楚摄像头的采集原理和时序,其他的代码都差不多。
部分代码如下,有用的可以参考:
//输入中断配置
void EXTI_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  EXTI_InitTypeDef EXTI_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1|GPIO_Pin_2; 
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);
EXTI_InitStruct.EXTI_Line = EXTI_Line1;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;     
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStruct);
EXTI_GenerateSWInterrupt(EXTI_Line1);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
  EXTI_InitStruct.EXTI_Line = EXTI_Line0;
  EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
  EXTI_InitStruct.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStruct);
EXTI_GenerateSWInterrupt(EXTI_Line0);  
}
void NVIC_Config(void)
{
  NVIC_InitTypeDef NVIC_InitStruct;
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
//  NVIC_InitStruct.NVIC_IRQChannel = EXTI2_IRQn;      
//    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
//    NVIC_InitStruct.NVIC_IRQChannelSubPriority =
//    NVIC_InitStruct.NVIC_IRQChannelCmd = DISABL
//    NVIC_Init(&NVIC_InitStruct

NVIC_InitStruct.NVIC_IRQChannel = EXTI1_IRQn;        
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);

NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;         
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
//DCMI
void DCMI_DMA_Init(u32 DMA_Memory0BaseAddr,u16 DMA_BufferSize,u32 DMA_MemoryDataSize,u32 DMA_MemoryInc)
{
DMA_InitTypeDef  DMA_InitStructure;
//    NVIC_InitTypeDef NVIC_InitStructur
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);
DMA_DeInit(DMA2_Stream1);
while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE){}
 
  DMA_InitStructure.DMA_Channel = DMA_Channel_1; 
  DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)&DCMI->DR;
  DMA_InitStructure.DMA_Memory0BaseAddr = DMA_Memory0BaseAddr;
  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;
  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;    
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA2_Stream1, &DMA_InitStructure);
}
//DCMI3?ê?
void My_DCMI_Init(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOE, ENABLE);
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI,ENABLE);
 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin =GPIO_Pin_5|GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_Init(GPIOE, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOA,GPIO_PinSource4,GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_DCMI);
     GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_DCMI);
     GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_DCMI);
     GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource8,GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource9,GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource5,GPIO_AF_DCMI);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource6,GPIO_AF_DCMI);

DCMI_DeInit();
 
  DCMI_InitStructure.DCMI_CaptureMode=DCMI_CaptureMode_Continuous;
DCMI_InitStructure.DCMI_CaptureRate=DCMI_CaptureRate_All_Frame;
DCMI_InitStructure.DCMI_ExtendedDataMode= DCMI_ExtendedDataMode_8b;
DCMI_InitStructure.DCMI_PCKPolarity= DCMI_PCKPolarity_Rising;
DCMI_InitStructure.DCMI_VSPolarity=DCMI_VSPolarity_High;
DCMI_InitStructure.DCMI_HSPolarity= DCMI_HSPolarity_Low;
DCMI_InitStructure.DCMI_SynchroMode= DCMI_SynchroMode_Hardware;
DCMI_Init(&DCMI_InitStructure);

//   DCMI_ITConfig(DCMI_IT_FRAME,ENABLE
   DCMI_ITConfig(DCMI_IT_VSYNC,ENABLE);   
   DCMI_ITConfig(DCMI_IT_LINE,DISABLE);       
//  DCMI_ITConfig(DCMI_IT_ERR, DISABLE
//  DCMI_ITConfig(DCMI_IT_OVF, DISABLE

DCMI_Cmd(ENABLE);   
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  NVIC_InitStructure.NVIC_IRQChannel = DCMI_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;   
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   
NVIC_Init(&NVIC_InitStructure);   
 
}
//DCMI,???ˉ′?
void DCMI_Start(void)

  LCD_SetCursor(0,0); 
     LCD_WriteRAM_Prepare();   
DMA_Cmd(DMA2_Stream1, ENABLE);
DCMI_CaptureCmd(ENABLE);
}
//DCMI,1?±?′?
void DCMI_Stop(void)
{
  DCMI_CaptureCmd(DISABLE);
while(DCMI->CR&0X01);   
DMA_Cmd(DMA2_Stream1,DISABLE);
LCD_SetCursor(0,0);
LCD_WriteRAM_Prepare();
}
   void DCMI_IRQHandler(void)
{
    if (DCMI->MISR & DCMI_IT_VSYNC)
    {
      DCMI_ClearITPendingBit(DCMI_IT_VSYNC);   
//        LED1=!LED
Flag=1;    
//    DCMI_Stop()
//    DMA2_Stream1->M0AR = (uint32_t)&(Image[0])
DCMI_ITConfig(DCMI_IT_LINE,ENABLE);  
ImgControl.lines = 0;
      ImgControl.ImgOk = false;
ov_frame++;   
  
    }
    if (DCMI->MISR & DCMI_IT_LINE)
    {     
        DCMI->ICR = DCMI_IT_LINE; 
        if(ImgControl.ImgOk == false)  
        {   
          
if(ImgControl.lines<camera_H)
            {   
  ImgControl.lines++;
        DMA2_Stream1->CR  &= (uint32_t)~DMA_SxCR_EN;
                DMA2_Stream1->M0AR = (uint32_t)&(Image[ImgControl.lines]);   
                DMA2_Stream1->CR  |=  DMA_SxCR_EN;     
                DCMI->CR |=  DCMI_CR_CAPTURE;   
            }   
if(ImgControl.lines ==camera_H)       
{   
  DCMI_ITConfig(DCMI_IT_LINE,DISABLE);   
                ImgControl.ImgOk = true;           
          DMA2_Stream1->CR  &= (uint32_t)~DMA_SxCR_EN;
               }
          }
}

    if (DCMI->MISR & DCMI_IT_FRAME)
    {
        DCMI->ICR = DCMI_IT_FRAME;
    }
    if (DCMI->MISR &DCMI_IT_ERR)
    {
        DCMI->ICR = DCMI_IT_ERR;
    }
}   
//8位亮度转RGB565
uint16_t ChangeYtoRGB(uint8_t Y)   
{
uint16_t RGB = 0;
uint8_t R = 0,G = 0,B = 0;
 
R = Y >> 3;
G = Y >> 2;
B = Y >> 3;
RGB = (R<<6) | G;
RGB = (RGB << 5) | B;
return RGB;
}
//图像拉伸处理(双线性插值
int is_in_array(short x,short y, int height, int width)
{
    if (x >= 0 && x < width && y >= 0 && y <height)
        return 1;
    else
        return 0;
}

//void bilinera_interpolation(u8 in_array[240][320],u8 out_array[240][240])     
//{
//    u32 height=240;     
//    u32 width=32
//    u32 out_height=240
//    u32 out_width=24
//   float h_times = out_height / height
//   float w_times = out_width / widt
//    int x, y
//    int  x1, y1, x2, y2, f11, f12, f21, f2
//    int i,
//    for ( i = 0; i < out_height; i++
//        for (j = 0; j < out_width; j++
//            x = j / w_times*10
//            y = i / h_times*10
//            x1 = (int)(x - 100
//            x2 = (int)(x + 100
//            y1 = (int)(y + 100
//            y2 = (int)(y- 100
//            f11 = is_in_array(x1, y1, height, width) ? in_array[y1][x1] :
//            f12 = is_in_array(x1, y2, height, width) ? in_array[y2][x1] :
//            f21 = is_in_array(x2, y1, height, width) ? in_array[y1][x2] :
//            f22 = is_in_array(x2, y2, height, width) ? in_array[y2][x2] :
//            out_array[i][j] = (u8)(((f11 * (x2 - x) * (y2 - y))
//                                       (f21 * (x - x1) * (y2 - y))
//                                       (f12 * (x2 - x) * (y - y1))
//                                       (f22 * (x - x1) * (y - y1))) / ((x2 - x1) * (y2 - y1))
//      
//  
/

//sccb
/    SCCB_Write_Reg(0x14,0x04);
//    SCCB_Write_Reg(0x14,0x04)
//    SCCB_Write_Reg(0x11,0x02);
//    SCCB_Write_Reg(0x17,0x57)
//    SCCB_Write_Reg(0x18,0xA7);
//  SCCB_Write_Reg(0x19,0x06)
//    SCCB_Write_Reg(0x1A,0xF6
//    SCCB_Write_Reg(0x6A,0x42);
//    SCCB_Write_Reg(0x12,0x34)
//    SCCB_Write_Reg(0x15,0x01);
//    SCCB_Write_Reg(0x05,0x60);
//    SCCB_Write_Reg(0x06,0x80);
//    SCCB_Write_Reg(0x6A,0x42);
//    SCCB_Write_Reg(0x28,0x20)
//YUV转rgb888再转RGB5
  
//          R0=(u16)((1164*(Image[i][j+1]-16)+1596*(Image[i][j]-128))/1000); 
//    B0=(u16)((1164*(Image[i][j+1]-16)+2018*(Image[i][j+2]-128))/1000
//    G0=(u16)((1164*(Image[i][j+1]-16)-813*(Image[i][j]-128)-391*(Image[i][j+2]-128))/1000);
//    R0=R0>255?255:(R0<1?1:R0);
//          G0=G0>255?255:(G0<1?1:G0);
//          B0=B0>255?255:(B0<1?1:B0);
//    RGB0=((B0<<8)&0xF800)|((G0<<3)&0x7E0)|(R0>>3
//    LCD->LCD_RAM=RGB0
//    R1=(u16)((1164*(Image[i][j+3]-16)+1596*(Image[i][j]-128))/1000); 
//    B1=(u16)((1164*(Image[i][j+3]-16)+2018*(Image[i][j+2]-128))/1000
//    G1=(u16)((1164*(Image[i][j+3]-16)-813*(Image[i][j]-128)-391*(Image[i][j+2]-128))/1000);
//    R1=R1>255?255:(R1<1?1:R1);
//          G1=G1>255?255:(G1<1?1:G1);
//          B1=B1>255?255:(B1<1?1:B1)
//            RGB1=((B1<<8)&0xF800)|((G1<<3)&0x7E0)|(R1>>3);      
//    LCD->LCD_RAM=RGB1;

//中值滤波
gray=ChangeYtoRGB(Image[i][j]); 
//      LCD->LCD_RAM=gra


//    LCD->LCD_RAM=0XFFE0;

//         if(Image[i][j]>=12
//
//    LCD->LCD_RAM=65535;   
//
//    el
//
//    LCD->LCD_RAM=


//            if(i==
//    {                
//    img=Image[0][j
//    gray=ChangeYtoRGB(img
//        LCD->LCD_RAM=gra
//     
//    if(i==23
//
//      img=Image[239][j
//    gray=ChangeYtoRGB(img
//        LCD->LCD_RAM=gra
//
//    if(j==
//
//    img=Image[i][0
//    gray=ChangeYtoRGB(img
//        LCD->LCD_RAM=gray
//     
//      if(j==319
//      img=Image[i][319
//    gray=ChangeYtoRGB(img
//        LCD->LCD_RAM=gray;
//    el
//
//            img=(u8)((Image[i-1][j-1]+Image[i-1][j]+Image[i-1][j+1]+Image[i][j-1]+Image[i][j]+Image[i][j+1]+Image[i+1][j-1]+Image[i+1][j]+Image[i+1][j+1])/9);
//      gray=ChangeYtoRGB(img
//        LCD->LCD_RAM=gray
//

//边缘检测
for(i=0;i<240;i++)
//    {
//      left_flag1=
//      right_flag1=
//      left=
//      right=
//      LCD_SetCursor(0,i
//        LCD_WriteRAM_Prepare()
//          for(j=0;j<320;j+
//     
//    img1[j]=Image[i][j]
////    img[i][j]=Image[i]
////    if(Image[i][j]>=
////    Image[i][j]=0xff; 
////   
////    Image[i][j]=0; 
//     
//
//      for(j=3;j<320;j++)      
//      {
//    if(Image[i][j-1]-Image[i][j]>Threshold)
//     
////    left
//    Image[i][j-1]=COLO
//    Image[i][j-2]=COLOR;
////    if(Image[i-1][j]-Image[i][j]>Threshold1
////    Image[i][j]=CO
////    if(Image[i+1][j]-Image[i][j]>Threshold1
////    Image[i][j]=CO
//     
//    else
//
//    Image[i][j-1]=
//    Image[i][j-2]=
//
//    if(Image[i][j+1]-Image[i][j]>Threshold)
//     
////    righ
//       Image[i][j+1]=COLO
//    Image[i][j+2]=COLOR;
////    if(Image[i-1][j]-Image[i][j]>Threshold1
////    Image[i][j]=CO
////    if(Image[i+1][j]-Image[i][j]>Threshold1
////    Image[i][j]=CO
//     
//             else
//
//    Image[i][j+1]=
//    Image[i][j+2]=
//   
//
////    if((left_flag1==1) && (right_flag1==1)) 
//
////    if((right-left>=BLACK_LINE_MIN0)&&(right-left<=BLACK_LINE_MAX0))
////       {Line_Center[i]=(right+left)/2
///
//
////      Image[i][(right+left)/2]=0x
////      Image[i][(right+left)/2+1]=0x
////      Image[i][(right+left)/2-1]=0x
/
//         for(j=0;j<320;j+
//     
/
//    gray=ChangeYtoRGB(img1[j]
////    LCD->LCD_RAM=gr
//    LCD->LCD_RAM=(u16)(Image[i][j]<<8)+Image[i][j]+gray;
////    if(Image[i][j]>=
////    LCD->LCD_RAM=65535; 
////   
////    LCD->LCD_RA
////      gray=ChangeYtoRGB(Image[i][j]
////      LCD->LCD_RAM=gr
//     
//   
//    
//    DCMI_Start(
//    ImgControl.ImgDealOk= true;
/
//

//径向畸变矫正
//  float normalizedX
//    float normalizedY
//    float distance
//    float radialDistor

/
/
//    int CAM_U0=269;      
//    int CAM_V0=24
//    float CAM_FX=1674.5
//    float CAM_FY=1675.3
//    float CAM_K1=-0.2
//    float CAM_K2=-0.7
/
/
//    uchar sourceV
//    int distorPixelPositionX
//    int distorPixelPositionY;
/
/
//    for(int h = 0; h < 240; h+
//
//    for(int w = 0; w < 320; w+
//
//    normalizedX = ((float)w - CAM_U0) / CAM_F
//    normalizedY = ((float)h - CAM_V0) / CAM_F
//    distance = normalizedX * normalizedX + normalizedY * normalized
//    radialDistor = CAM_K1 * distance + CAM_K2 * pow(distance , 2)
//    distorPixelPositionX = w+((float)w-CAM_U0)*radialDisto
//    distorPixelPositionY = h+((float)h-CAM_V0)*radialDisto
//    if(distorPixelPositionX < 0 || distorPixelPositionX >=24
//
//    distorPixelPositionX =
//
//    if(distorPixelPositionY < 0 || distorPixelPositionY >=32
//
//    distorPixelPositionY =
//
//    sourceV = Image(distorPixelPositionY,distorPixelPositionX)
//    compensatedImg.at<uchar>(h,w)=source
/
//
//


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 立即注册

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

返回顶部