新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > s3c2440的攝像接口應用

        s3c2440的攝像接口應用

        作者: 時間:2016-11-19 來源:網絡 收藏
        s3c2440提供了一個攝像接口,使開發人員很容易地實現攝像、照相等功能。攝像接口包括8位來自攝像頭的輸入數據信號,一個輸出主時鐘信號,三個來自攝像頭的輸入同步時鐘信號和一個輸出復位信號。攝像接口的主時鐘信號由USB PLL產生,它的頻率為96MHz,再經過分頻處理后輸出給攝像頭,攝像頭再根據該時鐘信號產生三個同步時鐘信號(像素時鐘、幀同步時鐘和行同步時鐘),反過來再輸入回s3c2440。

        s3c2440僅僅提供了一個攝像接口,因此要實現其功能,還需要攝像頭。在這里,我們使用OV9650。OV9650內部有大量的寄存器需要配置,這就需要另外的數據接口。OV9650的數據接口稱為SCCB(串行攝像控制總線),它由兩條數據線組成:一個是用于傳輸時鐘信號的SIO_C,另一個是用于傳輸數據信號的SIO_D。SCCB的傳輸協議與IIC的極其相似,只不過IIC在每傳輸完一個字節后,接收數據的一方要發送一位的確認數據,而SCCB一次要傳輸9位數據,前8位為有用數據,而第9位數據在寫周期中是Don’t-Care位(即不必關心位),在讀周期中是NA位。SCCB定義數據傳輸的基本單元為相(phase),即一個相傳輸一個字節數據。SCCB只包括三種傳輸周期,即3相寫傳輸周期(三個相依次為設備從地址,內存地址,所寫數據),2相寫傳輸周期(兩個相依次為設備從地址,內存地址)和2相讀傳輸周期(兩個相依次為設備從地址,所讀數據)。當需要寫操作時,應用3相寫傳輸周期,當需要讀操作時,依次應用2相寫傳輸周期和2相讀傳輸周期。因此SCCB一次只能讀或寫一個字節。下面我們就用s3c2440的IIC總線接口分別與OV9650的SIO_C和SIO_D相連接來實現SCCB的功能。具體的讀、寫函數為:

        //配置IIC接口
        rGPEUP = 0xc000;//上拉無效
        rGPECON = 0xa0000000;//GPE15:IICSDA,GPE14:IICSCL

        //IIC中斷
        void __irq IicISR(void)
        {
        rSRCPND |= 0x1<<27;
        rINTPND |= 0x1<<27;
        flag = 0;
        }

        //寫操作
        //輸入參數分別為要寫入的內存地址和數據
        void Wr_SCCB(unsigned char wordAddr, unsigned char data)
        {
        //3相寫傳輸周期
        //寫OV9650設備從地址字節
        flag =1;
        rIICDS =0x60;//OV9650設備從地址為0x60
        rIICSTAT = 0xf0;
        rIICCON &= ~0x10;

        while(flag == 1)
        delay(100);

        //寫OV9650內存地址字節
        flag = 1;
        rIICDS = wordAddr;
        rIICCON &= ~0x10;
        while(flag)
        delay(100);

        //寫具體的數據字節
        flag = 1;
        rIICDS = data;
        rIICCON &= ~0x10;
        while(flag)
        delay(100);

        rIICSTAT = 0xd0;//停止位
        rIICCON = 0xe3;//為下一次數據傳輸做準備

        delay(100);
        }

        //讀操作
        //參數分別為要讀取的內存地址和數據
        void Rd_SCCB (unsigned char wordAddr,unsigned char *data)
        {
        unsigned char temp;

        //2相寫傳輸周期
        //寫入OV9650設備從地址字節
        flag =1;
        rIICDS = 0x60;
        rIICSTAT = 0xf0;
        rIICCON &= ~0x10;
        while(flag)
        delay(100);

        //寫入內存地址字節
        flag = 1;
        rIICDS = wordAddr;
        rIICCON &= ~0x10;
        while(flag)
        delay(100);

        rIICSTAT = 0xd0;//停止位
        rIICCON = 0xe3;//為下一次數據傳輸做準備

        delay(100);

        //2相讀傳輸周期
        //寫入OV9650設備從地址字節
        flag = 1;
        rIICDS = 0x60;
        rIICSTAT = 0xb0;
        rIICCON &= ~0x10;
        while (flag)
        delay(100);

        //讀取一個無用字節
        flag = 1;
        temp = rIICDS;
        rIICCON &= ~((1<<7)|(1<<4));
        while(flag)
        delay(100);

        //讀取數據
        flag = 1;
        *data= rIICDS;
        rIICCON &= ~((1<<7)|(1<<4));
        while(flag)
        delay(100);

        rIICSTAT = 0x90;//停止位
        rIICCON = 0xe3;//為下一次傳輸做準備

        delay(100);
        }

        當然我們也可以用兩個通用IO口來模擬SCCB總線,下面我們給出具體的程序,其中GPE15為SIO_D,GPE14為SIO_C。

        #define CLOCK_LOW()(rGPEDAT&=(~(1<<14)))//時鐘信號低
        #define CLOCK_HIGH()(rGPEDAT|=(1<<14))//時鐘信號高
        #define DATA_LOW()(rGPEDAT&=(~(1<<15)))//數據信號低
        #define DATA_HIGH()(rGPEDAT|=(1<<15))//數據信號高

        //配置IO
        rGPEUP = 0xc000;//上拉無效
        rGPECON = 5<<28;//GPE15為SIO_D,GPE14為SIO_C,都為輸出

        void delay(int a)
        {
        int k;
        for(k=0;k;
        }

        //啟動SCCB
        void __inline SCCB_start(void)
        {
        CLOCK_HIGH();
        DATA_HIGH();
        delay(10);
        DATA_LOW();
        delay(10);
        CLOCK_LOW();
        delay(10);
        }

        //結束SCCB
        void __inline SCCB_end(void)
        {
        DATA_LOW();
        delay(10);
        CLOCK_HIGH();
        delay(10);
        DATA_HIGH();
        delay(10);
        }

        //SCCB發送一個字節
        void __inline SCCB_sendbyte(unsigned char data)
        {
        int i=0;
        //并行數據轉串行輸出,串行數據輸出的順序為先高位再低位
        for(i=0;i<8;i++)
        {
        if(data & 0x80)
        DATA_HIGH();
        else
        DATA_LOW();

        delay(10);
        CLOCK_HIGH();
        delay(10);
        CLOCK_LOW();
        delay(10);
        DATA_LOW();
        delay(10);

        data <<= 1;
        }

        //第9位,Don’t Care
        DATA_HIGH();
        delay(10);
        CLOCK_HIGH();
        delay(10);
        CLOCK_LOW();
        delay(10);
        }

        // SCCB接收一個字節
        void __inline SCCB_receivebyte(unsigned char *data)
        {
        int i=0;
        int svalue=0;
        int pvalue = 0;

        rGPECON = 1<<28;//把GPE15輸出改變為輸入

        //串行數據轉并行輸入,高位在前
        for(i=7;i>=0;i--)
        {
        CLOCK_HIGH();
        delay(10);
        svalue = rGPEDAT>>15;
        CLOCK_LOW();
        delay(10);
        pvalue |= svalue <}

        rGPECON =5<<28;//再把GPE15改回為輸出

        //第9位,N.A.
        DATA_HIGH();
        delay(10);
        CLOCK_HIGH();
        delay(10);
        CLOCK_LOW();
        delay(10);

        *data = pvalue &0xff;
        }

        //寫操作
        void SCCB_senddata(unsigned char subaddr, unsigned char data)
        {
        //3相寫傳輸周期
        SCCB_start();//啟動SCCB
        SCCB_sendbyte(0x60);//OV9650設備從地址,寫操作
        SCCB_sendbyte(subaddr);//設備內存地址
        SCCB_sendbyte(data);//寫數據字節
        SCCB_end();//結束SCCB

        delay(20);
        }

        //讀操作
        unsigned char SCCB_receivedata(unsigned char subaddr)
        {
        unsigned char temp;

        //2相寫傳輸周期
        SCCB_start();//啟動SCCB
        SCCB_sendbyte(0x60);//OV9650設備從地址,寫操作
        SCCB_sendbyte(subaddr);//設備內存地址
        SCCB_end();//結束SCCB

        //2相讀傳輸周期
        SCCB_start();//啟動SCCB
        SCCB_sendbyte(0x61);//OV9650設備從地址,讀操作
        SCCB_receivebyte(&temp);//讀字節
        SCCB_end();//結束SCCB

        return temp;
        }

        OV9650的寄存器較多,要想配置好這些寄存器是需要花費一些精力的。下面數組給出了一個VGA(640×480)模式下YUV彩色空間的配置例子,括號內第一個元素表示寄存器地址,第二個元素表示要寫入的數據。

        const unsigned char ov9650_register[ ][2] = {
        {0x11,0x80},{0x6a,0x3e},{0x3b,0x09},{0x13,0xe0},{0x01,0x80},{0x02,0x80},{0x00,0x00},{0x10,0x00},
        {0x13,0xe5},{0x39,0x43},{0x38,0x12},{0x37,0x00},{0x35,0x91},{0x0e,0xa0},{0x1e,0x04},{0xA8,0x80},
        {0x12,0x40},{0x04,0x00},{0x0c,0x04},{0x0d,0x80},{0x18,0xc6},{0x17,0x26},{0x32,0xad},{0x03,0x00},
        {0x1a,0x3d},{0x19,0x01},{0x3f,0xa6},{0x14,0x2e},{0x15,0x10},{0x41,0x02},{0x42,0x08},{0x1b,0x00},
        {0x16,0x06},{0x33,0xe2},{0x34,0xbf},{0x96,0x04},{0x3a,0x00},{0x8e,0x00},{0x3c,0x77},{0x8B,0x06},
        {0x94,0x88},{0x95,0x88},{0x40,0xc1},{0x29,0x3f},{0x0f,0x42},{0x3d,0x92},{0x69,0x40},{0x5C,0xb9},
        {0x5D,0x96},{0x5E,0x10},{0x59,0xc0},{0x5A,0xaf},{0x5B,0x55},{0x43,0xf0},{0x44,0x10},{0x45,0x68},
        {0x46,0x96},{0x47,0x60},{0x48,0x80},{0x5F,0xe0},{0x60,0x8c},{0x61,0x20},{0xa5,0xd9},{0xa4,0x74},
        {0x8d,0x02},{0x13,0xe7},{0x4f,0x3a},{0x50,0x3d},{0x51,0x03},{0x52,0x12},{0x53,0x26},{0x54,0x38},
        {0x55,0x40},{0x56,0x40},{0x57,0x40},{0x58,0x0d},{0x8C,0x23},{0x3E,0x02},{0xa9,0xb8},{0xaa,0x92},
        {0xab,0x0a},{0x8f,0xdf},{0x90,0x00},{0x91,0x00},{0x9f,0x00},{0xa0,0x00},{0x3A,0x01},{0x24,0x70},
        {0x25,0x64},{0x26,0xc3},{0x2a,0x00},{0x2b,0x00},{0x6c,0x40},{0x6d,0x30},{0x6e,0x4b},{0x6f,0x60},
        {0x70,0x70},{0x71,0x70},{0x72,0x70},{0x73,0x70},{0x74,0x60},{0x75,0x60},{0x76,0x50},{0x77,0x48},
        {0x78,0x3a},{0x79,0x2e},{0x7a,0x28},{0x7b,0x22},{0x7c,0x04},{0x7d,0x07},{0x7e,0x10},{0x7f,0x28},
        {0x80,0x36},{0x81,0x44},{0x82,0x52},{0x83,0x60},{0x84,0x6c},{0x85,0x78},{0x86,0x8c},{0x87,0x9e},
        {0x88,0xbb},{0x89,0xd2},{0x8a,0xe6},
        };

        另外OV9650有兩個只讀寄存器——0x1C和0x1D,用于存放廠家ID,數據分別為0x7F和0xA2,我們可以通過讀取它們來判斷s3c2440是否連接了OV9650。當確認連接了OV9650后,我們就可以把上面的那個數組寫入OV9650內,如下所示。在這里我們總是認為s3c2440連接了OV9650。

        void config_ov9650(void)
        {
        unsigned char temp;
        int i;

        //讀取OV9650廠商ID
        i=1;
        while(i)
        {
        temp = SCCB_receivedata(0x1C);//或Rd_SCCB (0x1C,&temp);
        if(temp==0x7F)
        i=0;
        }
        i=1;
        while(i)
        {
        temp = SCCB_receivedata(0x1D);//或Rd_SCCB (0x1D,&temp);
        if(temp==0xA2)
        i=0;
        }

        //復位所有OV9650寄存器
        SCCB_senddata(0x12,0x80);//或Wr_SCCB (0x12,0x80);
        delay(10000);

        //配置OV9650寄存器
        for(i=0;i<((sizeof(ov9650_register))/2);i++)
        {
        SCCB_senddata(ov9650_register[i][0],ov9650_register[i][1]);
        //或Wr_SCCB (ov9650_register[i][0],ov9650_register[i][1]);
        }
        }

        上面程序中,我們是用循環語句讀取OV9650的寄存器0x1C和0x1D的,之所以這樣,是為了防止只讀取一次時,會有讀取不正確的現象發生。而一旦正確讀取了廠商ID信息,再讀寫OV9650寄存器,一般就不會發生讀寫的錯誤。

        下面就介紹口的相關配置。攝像接口有兩個相互獨立的DMA通道——P通道(預覽通道)和C通道(編解碼通道)。P通道主要是存儲用于視頻顯示的RGB圖像數據,C通道主要是存儲用于編解碼的YCbCr圖像數據。在這里我們主要是把OV9650采集到的視頻信息實時顯示在LCD上,因此只介紹P通道的用法。

        設置口一個很重要的步驟就是設置視頻尺寸大小。我們把由OV9650采集到的視頻尺寸稱為源,即源水平尺寸和源垂直尺寸,其中源水平尺寸必須是8的整數倍。這個尺寸是通過配置OV9650的相關寄存器實現的。我們把這兩個值分別放入輸入源格式寄存器CISRCFMT的第16位至第28位,和第0位至第12位內,例如通過OV9650,采集的到的視頻尺寸為640×480,則把640和480分別放入寄存器CISRCFMT中的相應位置即可。我們把實際顯示的視頻尺寸稱為目標,即目標水平尺寸和目標垂直尺寸,這里這個尺寸就是LCD的尺寸。我們把這兩個值分別放入預覽DMA目標圖像格式寄存器CIPRTRGFMT的第16位至第28位,和第0位至第12位內,例如LCD的尺寸為320×240,則把320和240分別放入寄存器CIPRTRGFMT中的相應位置即可。另外還需要把這兩個值的乘積放入預覽縮放目標面積寄存器CIPRTAREA內。源尺寸和目標尺寸往往是不一樣大小的,那么可能還需要設置偏移量,即水平偏移量和垂直偏移量,應該把這兩個值分別放入窗口偏移寄存器CIWDOFST的第16位至第26位,和第0位至第10位內,其中這個寄存器的第31位用于控制是否需要設置偏移量,當偏移量為0或不需要設置偏移量時,這一位應為0,否則為1。顯然,通過源尺寸、目標尺寸和偏移量的設置,可以實現被攝像物體的縮放效果。當然,要實現這種縮放效果,還需要配置預覽預縮放比例控制寄存器CIPRSCPRERATIO、預覽預縮放距離格式寄存器CIPRSCPREDST和預覽主縮放控制寄存器CIPRSCCTRL,這些寄存器的相關參數是通過計算得到的,數據手冊上有詳細的說明,而且還有標準的函數可以調用,因此在這里就不過多介紹。

        前面已經介紹過,攝像接口都是通過DMA實現數據交換的。s3c2440能夠在內存中各開辟四塊乒乓存儲區域,用于實現P通道和C通道的快速數據傳遞。在P通道中,寄存器CIPRCLRSA1、CIPRCLRSA2、CIPRCLRSA3和CIPRCLRSA4分別用于表示這四塊內存的首地址。另外在DMA數據傳遞中,還要讓DMA知道如何進行傳遞,即一次傳輸多少個字節,這需要設置預覽DMA控制相關寄存器CIPRCTRL的主突發長度和剩余突發長度,這兩個值也可以通過調用標準函數來求得。另外在完成每一幀視頻采集后,會觸發一個視頻中斷。

        下面就給出一段具體的程序,利用OV9650實時地在LCD上顯示視頻,并通過UART來控制視頻,讓視頻圖像放大,縮小,以及實現照相的功能(讓圖像定格在LCD上)。


        …………

        int com;

        …………

        //計算主突發長度和剩余突發長度,用于CIPRCTRL寄存器
        void CalculateBurstSize(U32 hSize,U32 *mainBurstSize,U32 *remainedBurstSize)
        {
        U32 tmp;
        tmp=(hSize/4)%16;
        switch(tmp) {
        case 0:
        *mainBurstSize=16;
        *remainedBurstSize=16;
        break;
        case 4:
        *mainBurstSize=16;
        *remainedBurstSize=4;
        break;
        case 8:
        *mainBurstSize=16;
        *remainedBurstSize=8;
        break;
        default:
        tmp=(hSize/4)%8;
        switch(tmp) {
        case 0:
        *mainBurstSize=8;
        *remainedBurstSize=8;
        break;
        case 4:
        *mainBurstSize=8;
        *remainedBurstSize=4;
        default:
        *mainBurstSize=4;
        tmp=(hSize/4)%4;
        *remainedBurstSize= (tmp) ? tmp: 4;
        break;
        }
        break;
        }
        }

        //計算預縮放比率及移位量,用于CICOSCPRERATIO寄存器
        void CalculatePrescalerRatioShift(U32 SrcSize, U32 DstSize, U32 *ratio,U32 *shift)
        {
        if(SrcSize>=64*DstSize) {
        //Uart_Printf("ERROR: out of the prescaler range: SrcSize/DstSize = %d(< 64)/n",SrcSize/DstSize);
        while(1);
        }
        else if(SrcSize>=32*DstSize) {
        *ratio=32;
        *shift=5;
        }
        else if(SrcSize>=16*DstSize) {
        *ratio=16;
        *shift=4;
        }
        else if(SrcSize>=8*DstSize) {
        *ratio=8;
        *shift=3;
        }
        else if(SrcSize>=4*DstSize) {
        *ratio=4;
        *shift=2;
        }
        else if(SrcSize>=2*DstSize) {
        *ratio=2;
        *shift=1;
        }
        else {
        *ratio=1;
        *shift=0;
        }
        }

        //攝像接口初始化
        //輸入參數分別為預覽目標寬和高(即LCD尺寸),以及水平和垂直偏移量
        void CamInit(U32 PrDstWidth, U32 PrDstHeight, U32 WinHorOffset, U32 WinVerOffset)
        {
        U32 WinOfsEn;
        U32 MainBurstSizeRGB, RemainedBurstSizeRGB;
        U32 H_Shift, V_Shift, PreHorRatio, PreVerRatio, MainHorRatio, MainVerRatio;
        U32 SrcWidth, SrcHeight;
        U32 ScaleUp_H_Pr, ScaleUp_V_Pr;

        //判斷是否需要設置偏移量
        if(WinHorOffset==0 && WinVerOffset==0)
        WinOfsEn=0;
        else
        WinOfsEn=1;

        SrcWidth=640/*源水平尺寸*/-WinHorOffset*2;
        SrcHeight=480/*源垂直尺寸*/-WinVerOffset*2;

        //判斷尺寸是放大還是縮小
        if(SrcWidth>=PrDstWidth)
        ScaleUp_H_Pr=0;//down
        else
        ScaleUp_H_Pr=1;//up

        if(SrcHeight>=PrDstHeight)
        ScaleUp_V_Pr=0;
        else
        ScaleUp_V_Pr=1;

        rCIGCTRL |= (1<<26)|(0<<27);//PCLK極性反轉,外部攝像處理器輸入
        rCIWDOFST = (1<<30)|(0xf<<12);//清FIFO溢出
        rCIWDOFST = 0;//恢復正常模式
        rCIWDOFST=(WinOfsEn<<31)|(WinHorOffset<<16)|(WinVerOffset);//設置偏移量
        rCISRCFMT=(1<<31)|(0<<30)|(0<<29)|(640/*源水平尺寸*/<<16)|(0<<14)|(480/*源垂直尺寸*/);

        //設置內存首地址,因為是直接顯示,所以設置為LCD緩存數組首地址
        rCIPRCLRSA1 = (U32)LCD_BUFFER;
        rCIPRCLRSA2 = (U32)LCD_BUFFER;
        rCIPRCLRSA3 = (U32)LCD_BUFFER;
        rCIPRCLRSA4 = (U32)LCD_BUFFER;

        //設置目標尺寸,并且不進行鏡像和旋轉處理
        rCIPRTRGFMT=(PrDstWidth<<16)|(0<<14)|(PrDstHeight);

        //計算并設置突發長度
        CalculateBurstSize(PrDstWidth*2, &MainBurstSizeRGB, &RemainedBurstSizeRGB);
        rCIPRCTRL=(MainBurstSizeRGB<<19)|(RemainedBurstSizeRGB<<14);

        //計算水平和垂直縮放比率和位移量,以及主水平、垂直比率
        CalculatePrescalerRatioShift(SrcWidth, PrDstWidth, &PreHorRatio, &H_Shift);
        CalculatePrescalerRatioShift(SrcHeight, PrDstHeight, &PreVerRatio, &V_Shift);
        MainHorRatio=(SrcWidth<<8)/(PrDstWidth<MainVerRatio=(SrcHeight<<8)/(PrDstHeight<
        //設置縮放所需的各類參數
        rCIPRSCPRERATIO=((10-H_Shift-V_Shift)<<28)|(PreHorRatio<<16)|(PreVerRatio);
        rCIPRSCPREDST=((SrcWidth/PreHorRatio)<<16)|(SrcHeight/PreVerRatio);
        rCIPRSCCTRL=(1<<31)|(1 /*24位RGB格式*/ <<30)|(ScaleUp_H_Pr<<29)|(ScaleUp_V_Pr<<28)|(MainHorRatio<<16)|(MainVerRatio);

        //設置面積
        rCIPRTAREA= PrDstWidth*PrDstHeight;
        }

        //攝像中斷,在這里,除了清中斷標志,沒有其他操作
        void __irq CamIsr(void)
        {
        rSUBSRCPND |= 1<<12;
        rSRCPND |= 1<<6;
        rINTPND |= 1<<6;
        }

        //UART中斷
        void __irq uartISR(void)
        {
        unsigned char ch;

        rSUBSRCPND |= 0x3;
        rSRCPND = 0x1<<28;
        rINTPND = 0x1<<28;

        ch = rURXH0; //接收字節數據
        switch(ch)
        {
        case 0x11://正常顯示視頻
        com=1;
        break;
        case 0x22://定格圖像
        com=2;
        break;
        case 0x33://放大尺寸
        com=3;
        break;
        case 0x44://縮小尺寸
        com =4;
        break;
        }
        rUTXH0 = ch;
        }

        void Main(void)
        {
        int HOffset,VOffset;

        //初始化UPLL,以得到OV9650的系統時鐘
        rUPLLCON = (56<<12) | (2<<4) | 1;//UPLL為96MHz
        rCLKDIVN |= (1<<3);//UCLK = UPLL/2=48MHz
        rCAMDIVN = (rCAMDIVN & ~(0xf))|(1<<4)|(2);//設置攝像接口時鐘分頻

        …………

        LCD_Init();//初始化LCD,其中LCD的顯示格式為24位RGB格式

        rLCDCON1|=1;//開啟LCD


        //配置攝像接口引腳
        rGPJCON = 0x2aaaaaa;
        rGPJDAT = 0;
        rGPJUP = 0;//上拉使能

        //硬件復位攝像頭
        rGPJDAT |= 1<<12;
        delay(100);
        rGPJDAT &= ~(1<<12);

        //軟件復位攝像接口
        rCIGCTRL |= (1<<31);
        delay(100);
        rCIGCTRL &= ~(1<<31);
        delay(100);

        //軟件復位攝像頭
        rCIGCTRL |= (1<<30);
        delay(300);
        rCIGCTRL &= ~(1<<30);
        delay(20000);

        config_ov9650();//配置OV9650寄存器

        HOffset=0;
        VOffset=0;

        //初始化攝像接口
        CamInit(320,240,HOffset,VOffset);

        //開啟攝像接口中斷,
        rSUBSRCPND |= 1<<12;
        rSRCPND |= 1<<6;
        rINTPND |= 1<<6;
        rINTSUBMSK &= ~(1<<12);
        rINTMSK &= ~(1<<6);
        pISR_CAM = (U32)CamIsr;

        rCIPRSCCTRL|=(1<<15);//預覽縮放開啟
        rCIIMGCPT =(1<<31)|(1<<29);//預覽縮放捕捉使能

        com=0;

        while(1)
        {
        switch(com)
        {
        case 1://正常顯示
        com=0;
        rCIPRSCCTRL|=(1<<15);
        rCIIMGCPT =(1<<31)|(1<<29);
        break;
        case 2://定格圖像
        com=0;
        rCIPRSCCTRL&=~(1<<15);
        rCIIMGCPT &=~((1<<31)|(1<<29));
        break;
        case 3://放大視頻
        com=0;
        if(HOffset==160)
        break;
        HOffset += 8;
        VOffset += 8;
        rCIPRSCCTRL&=~(1<<15);
        rCIIMGCPT &=~((1<<31)|(1<<29));
        CamInit(320,240,HOffset,VOffset);
        rCIPRSCCTRL|=(1<<15);
        rCIIMGCPT =(1<<31)|(1<<29);
        break;
        case 4://縮小視頻
        com=0;
        if(HOffset==0)
        break;
        HOffset -= 8;
        VOffset -= 8;
        rCIPRSCCTRL&=~(1<<15);
        rCIIMGCPT &=~((1<<31)|(1<<29));
        CamInit(320,240,HOffset,VOffset);
        rCIPRSCCTRL|=(1<<15);
        rCIIMGCPT =(1<<31)|(1<<29);
        break;
        }
        }
        }


        關鍵詞: s3c2440攝像接

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 墨江| 托克托县| 疏勒县| 卢氏县| 绿春县| 永德县| 平武县| 甘孜| 临西县| 宁安市| 孟津县| 黄石市| 苍山县| 繁昌县| 商河县| 青冈县| 乐亭县| 会泽县| 兴业县| 南康市| 文化| 犍为县| 铁岭县| 高雄市| 夏津县| 白沙| 罗山县| 晋城| 吴堡县| 高密市| 贵定县| 繁峙县| 望城县| 桓仁| 始兴县| 庆城县| 贵德县| 正定县| 林甸县| 白城市| 宜黄县|