1. 程式人生 > >stm32驅動ov7670 資料轉BMP格式再轉JPEG儲存

stm32驅動ov7670 資料轉BMP格式再轉JPEG儲存

一.搞了幾天攝像頭終於搞出來了一點成果,本打算用BMP格式儲存讀出的資料但是資料太大達到225k,後來又將BMP資料轉成JPEG格式就小了很多,jpeg是有失真壓縮圖片會變得不那麼清晰。

搞出來的成果:

二.攝像頭小知識:XCLK是輸入攝像頭的時鐘,看別的原理圖接的是一個12M的晶振,初始化的時候4倍頻達到48M,這裡沒有接,用PA8輸出8M內部6倍頻達到48M,PCLK是攝像頭輸出的時鐘達到12M,影象輸出的是QVGA,RGB565格式,用的是VGA時序,一個畫素需要2個pclk.

行輸出時序圖:

HREF是一個行訊號,這個訊號和mcu的一個引腳連線在SN74LVC1G00D(與非門)上,和mcu一塊控制fifo,當準備寫fifo時,mcu傳送高電平,這時fifo並沒有被使能,只有當HREF產生高電平訊號時,在PCLK的配合下將資料寫到fifo中。

幀輸出時序圖:

VSYNC是幀同步訊號,當攝像頭採集到一幀資料,會發出幀同步訊號,用外部中斷捕獲這個幀中斷訊號。

void EXTI4_IRQHandler(void)
{         
    if(EXTI_GetITStatus(EXTI_Line4)==SET)    //是4線的中斷
    {   if(OV7670_CS == 0) 
        {       
                if(ov_sta == 0)
                {            
                    OV7670_WRST=0;    //復位寫指標                   
                    OV7670_WRST=1;    
                    OV7670_WREN=1;    //允許寫入FIFO      
                    ov_sta=1;
                }
                else
                {
                    OV7670_WRST=0;    //復位寫指標                   
                    OV7670_WRST=0;    
                    OV7670_WREN=1;    //允許寫入FIFO 
                }
            }
    }
    EXTI_ClearITPendingBit(EXTI_Line4);  //清除EXTI4線路掛起位                          
}

三.讀取資料並轉換,也是仿照的別人的用的開源庫。

void camera_refresh(void)
{   
    int width, height;
    int j,i;
     u16 color=0;
    int col;
    int t;
   jpeg_compress_info *cinfo;
    pt_buf = 0;
    if(ov_sta)//有幀中斷更新?
    {
          width = 320;//影象的寬度 
          height = 240;//影象的高度 
          cinfo = jpeg_create_compress();
          if (!cinfo) 
          {
            //printf("error in create cinfo, malloc faild!\n");
          }
          cinfo->image_width = width;
          cinfo->image_height= height;
          cinfo->output =(char *)JPG_enc_buf;//fopen("test.jpg", "wb");
          jpeg_set_default(cinfo);  
          
          jpeg_start_compress(cinfo);
  
        FLASH_SIZE1 = 8192;
        OV7670_RRST=0;                //開始復位讀指標         
        OV7670_RCK_L;
        OV7670_RCK_H;
        OV7670_RCK_L;
        OV7670_RRST=1;                //復位讀指標結束 
        OV7670_RCK_H;                
        for(j=0;j<240;j++)
        {    //printf("第%u行",j);
            for(i=319;i>=0;i--)
            {

      //高位元組  資料位接的比較亂 根據實際情況修改
                OV7670_RCK_L;
                color = ((GPIOD->IDR&0xC000)>>14);   //D14 D15
                color |= ((GPIOD->IDR&0x0003)<<2);  //D0 D1
                color |= ((GPIOE->IDR&0x0780)>>3);  //E7 8 9 10
                OV7670_RCK_H;                 
                color<<=8;  
                OV7670_RCK_L;
                //低位元組
                color |= ((GPIOD->IDR&0xC000)>>14);   //D14 D15
                color |= ((GPIOD->IDR&0x0003)<<2);  //D0 D1
                color |= ((GPIOE->IDR&0x0780)>>3);  //E7 8 9 10                
                OV7670_RCK_H;                                 
                R = (color>>8)&0xF8;
                G = (color>>3)&0xFC;
                B = (color<<3)&0xF8;
                
                buffer[i*3+0] = R;//jpeg格式順序RGB 如果是bmp格式寫成BGR
                buffer[i*3+1] = G;
                buffer[i*3+2] = B;
            }            
            jpeg_write_scanline(cinfo, buffer);//一行一行的壓縮
        } 
        jpeg_finish_compress(cinfo);  
        jpeg_destory_compress(cinfo);
        //OV7670_CS=1;
         ov_sta=0;        //清零幀中斷標記
        //需要多少擦多少
        for(i = 0;i<=(pt_buf/4096);i++)
        {
            W25QXX_Erase_Sector( 8192/4096+i );
        }      
        for(t = 0;t<pt_buf;t++)
        {
         send_data(JPG_enc_buf[t]);//傳送資料給上位機          
        }      
        W25QXX_Write_NoCheck((u8*)JPG_enc_buf,FLASH_SIZE1,pt_buf);//寫到flash

    } 
}