<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > s3c2440的攝像接口應(yīng)用

          s3c2440的攝像接口應(yīng)用

          作者: 時(shí)間:2016-11-19 來(lái)源:網(wǎng)絡(luò) 收藏
          s3c2440提供了一個(gè)攝像接口,使開發(fā)人員很容易地實(shí)現(xiàn)攝像、照相等功能。攝像接口包括8位來(lái)自攝像頭的輸入數(shù)據(jù)信號(hào),一個(gè)輸出主時(shí)鐘信號(hào),三個(gè)來(lái)自攝像頭的輸入同步時(shí)鐘信號(hào)和一個(gè)輸出復(fù)位信號(hào)。攝像接口的主時(shí)鐘信號(hào)由USB PLL產(chǎn)生,它的頻率為96MHz,再經(jīng)過(guò)分頻處理后輸出給攝像頭,攝像頭再根據(jù)該時(shí)鐘信號(hào)產(chǎn)生三個(gè)同步時(shí)鐘信號(hào)(像素時(shí)鐘、幀同步時(shí)鐘和行同步時(shí)鐘),反過(guò)來(lái)再輸入回s3c2440。

          s3c2440僅僅提供了一個(gè)攝像接口,因此要實(shí)現(xiàn)其功能,還需要攝像頭。在這里,我們使用OV9650。OV9650內(nèi)部有大量的寄存器需要配置,這就需要另外的數(shù)據(jù)接口。OV9650的數(shù)據(jù)接口稱為SCCB(串行攝像控制總線),它由兩條數(shù)據(jù)線組成:一個(gè)是用于傳輸時(shí)鐘信號(hào)的SIO_C,另一個(gè)是用于傳輸數(shù)據(jù)信號(hào)的SIO_D。SCCB的傳輸協(xié)議與IIC的極其相似,只不過(guò)IIC在每傳輸完一個(gè)字節(jié)后,接收數(shù)據(jù)的一方要發(fā)送一位的確認(rèn)數(shù)據(jù),而SCCB一次要傳輸9位數(shù)據(jù),前8位為有用數(shù)據(jù),而第9位數(shù)據(jù)在寫周期中是Don’t-Care位(即不必關(guān)心位),在讀周期中是NA位。SCCB定義數(shù)據(jù)傳輸?shù)幕締卧獮橄啵╬hase),即一個(gè)相傳輸一個(gè)字節(jié)數(shù)據(jù)。SCCB只包括三種傳輸周期,即3相寫傳輸周期(三個(gè)相依次為設(shè)備從地址,內(nèi)存地址,所寫數(shù)據(jù)),2相寫傳輸周期(兩個(gè)相依次為設(shè)備從地址,內(nèi)存地址)和2相讀傳輸周期(兩個(gè)相依次為設(shè)備從地址,所讀數(shù)據(jù))。當(dāng)需要寫操作時(shí),應(yīng)用3相寫傳輸周期,當(dāng)需要讀操作時(shí),依次應(yīng)用2相寫傳輸周期和2相讀傳輸周期。因此SCCB一次只能讀或?qū)懸粋€(gè)字節(jié)。下面我們就用s3c2440的IIC總線接口分別與OV9650的SIO_C和SIO_D相連接來(lái)實(shí)現(xiàn)SCCB的功能。具體的讀、寫函數(shù)為:

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

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

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

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

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

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

          rIICSTAT = 0xd0;//停止位
          rIICCON = 0xe3;//為下一次數(shù)據(jù)傳輸做準(zhǔn)備

          delay(100);
          }

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

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

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

          rIICSTAT = 0xd0;//停止位
          rIICCON = 0xe3;//為下一次數(shù)據(jù)傳輸做準(zhǔn)備

          delay(100);

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

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

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

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

          delay(100);
          }

          當(dāng)然我們也可以用兩個(gè)通用IO口來(lái)模擬SCCB總線,下面我們給出具體的程序,其中GPE15為SIO_D,GPE14為SIO_C。

          #define CLOCK_LOW()(rGPEDAT&=(~(1<<14)))//時(shí)鐘信號(hào)低
          #define CLOCK_HIGH()(rGPEDAT|=(1<<14))//時(shí)鐘信號(hào)高
          #define DATA_LOW()(rGPEDAT&=(~(1<<15)))//數(shù)據(jù)信號(hào)低
          #define DATA_HIGH()(rGPEDAT|=(1<<15))//數(shù)據(jù)信號(hào)高

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

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

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

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

          //SCCB發(fā)送一個(gè)字節(jié)
          void __inline SCCB_sendbyte(unsigned char data)
          {
          int i=0;
          //并行數(shù)據(jù)轉(zhuǎn)串行輸出,串行數(shù)據(jù)輸出的順序?yàn)橄雀呶辉俚臀?br />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接收一個(gè)字節(jié)
          void __inline SCCB_receivebyte(unsigned char *data)
          {
          int i=0;
          int svalue=0;
          int pvalue = 0;

          rGPECON = 1<<28;//把GPE15輸出改變?yōu)檩斎?br />
          //串行數(shù)據(jù)轉(zhuǎn)并行輸入,高位在前
          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();//啟動(dòng)SCCB
          SCCB_sendbyte(0x60);//OV9650設(shè)備從地址,寫操作
          SCCB_sendbyte(subaddr);//設(shè)備內(nèi)存地址
          SCCB_sendbyte(data);//寫數(shù)據(jù)字節(jié)
          SCCB_end();//結(jié)束SCCB

          delay(20);
          }

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

          //2相寫傳輸周期
          SCCB_start();//啟動(dòng)SCCB
          SCCB_sendbyte(0x60);//OV9650設(shè)備從地址,寫操作
          SCCB_sendbyte(subaddr);//設(shè)備內(nèi)存地址
          SCCB_end();//結(jié)束SCCB

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

          return temp;
          }

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

          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有兩個(gè)只讀寄存器——0x1C和0x1D,用于存放廠家ID,數(shù)據(jù)分別為0x7F和0xA2,我們可以通過(guò)讀取它們來(lái)判斷s3c2440是否連接了OV9650。當(dāng)確認(rèn)連接了OV9650后,我們就可以把上面的那個(gè)數(shù)組寫入OV9650內(nèi),如下所示。在這里我們總是認(rèn)為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;
          }

          //復(fù)位所有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]);
          }
          }

          上面程序中,我們是用循環(huán)語(yǔ)句讀取OV9650的寄存器0x1C和0x1D的,之所以這樣,是為了防止只讀取一次時(shí),會(huì)有讀取不正確的現(xiàn)象發(fā)生。而一旦正確讀取了廠商ID信息,再讀寫OV9650寄存器,一般就不會(huì)發(fā)生讀寫的錯(cuò)誤。

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

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

          前面已經(jīng)介紹過(guò),攝像接口都是通過(guò)DMA實(shí)現(xiàn)數(shù)據(jù)交換的。s3c2440能夠在內(nèi)存中各開辟四塊乒乓存儲(chǔ)區(qū)域,用于實(shí)現(xiàn)P通道和C通道的快速數(shù)據(jù)傳遞。在P通道中,寄存器CIPRCLRSA1、CIPRCLRSA2、CIPRCLRSA3和CIPRCLRSA4分別用于表示這四塊內(nèi)存的首地址。另外在DMA數(shù)據(jù)傳遞中,還要讓DMA知道如何進(jìn)行傳遞,即一次傳輸多少個(gè)字節(jié),這需要設(shè)置預(yù)覽DMA控制相關(guān)寄存器CIPRCTRL的主突發(fā)長(zhǎng)度和剩余突發(fā)長(zhǎng)度,這兩個(gè)值也可以通過(guò)調(diào)用標(biāo)準(zhǔn)函數(shù)來(lái)求得。另外在完成每一幀視頻采集后,會(huì)觸發(fā)一個(gè)視頻中斷。

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


          …………

          int com;

          …………

          //計(jì)算主突發(fā)長(zhǎng)度和剩余突發(fā)長(zhǎng)度,用于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;
          }
          }

          //計(jì)算預(yù)縮放比率及移位量,用于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;
          }
          }

          //攝像接口初始化
          //輸入?yún)?shù)分別為預(yù)覽目標(biāo)寬和高(即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;

          //判斷是否需要設(shè)置偏移量
          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極性反轉(zhuǎn),外部攝像處理器輸入
          rCIWDOFST = (1<<30)|(0xf<<12);//清FIFO溢出
          rCIWDOFST = 0;//恢復(fù)正常模式
          rCIWDOFST=(WinOfsEn<<31)|(WinHorOffset<<16)|(WinVerOffset);//設(shè)置偏移量
          rCISRCFMT=(1<<31)|(0<<30)|(0<<29)|(640/*源水平尺寸*/<<16)|(0<<14)|(480/*源垂直尺寸*/);

          //設(shè)置內(nèi)存首地址,因?yàn)槭侵苯语@示,所以設(shè)置為L(zhǎng)CD緩存數(shù)組首地址
          rCIPRCLRSA1 = (U32)LCD_BUFFER;
          rCIPRCLRSA2 = (U32)LCD_BUFFER;
          rCIPRCLRSA3 = (U32)LCD_BUFFER;
          rCIPRCLRSA4 = (U32)LCD_BUFFER;

          //設(shè)置目標(biāo)尺寸,并且不進(jìn)行鏡像和旋轉(zhuǎn)處理
          rCIPRTRGFMT=(PrDstWidth<<16)|(0<<14)|(PrDstHeight);

          //計(jì)算并設(shè)置突發(fā)長(zhǎng)度
          CalculateBurstSize(PrDstWidth*2, &MainBurstSizeRGB, &RemainedBurstSizeRGB);
          rCIPRCTRL=(MainBurstSizeRGB<<19)|(RemainedBurstSizeRGB<<14);

          //計(jì)算水平和垂直縮放比率和位移量,以及主水平、垂直比率
          CalculatePrescalerRatioShift(SrcWidth, PrDstWidth, &PreHorRatio, &H_Shift);
          CalculatePrescalerRatioShift(SrcHeight, PrDstHeight, &PreVerRatio, &V_Shift);
          MainHorRatio=(SrcWidth<<8)/(PrDstWidth<MainVerRatio=(SrcHeight<<8)/(PrDstHeight<
          //設(shè)置縮放所需的各類參數(shù)
          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);

          //設(shè)置面積
          rCIPRTAREA= PrDstWidth*PrDstHeight;
          }

          //攝像中斷,在這里,除了清中斷標(biāo)志,沒(méi)有其他操作
          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; //接收字節(jié)數(shù)據(jù)
          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的系統(tǒng)時(shí)鐘
          rUPLLCON = (56<<12) | (2<<4) | 1;//UPLL為96MHz
          rCLKDIVN |= (1<<3);//UCLK = UPLL/2=48MHz
          rCAMDIVN = (rCAMDIVN & ~(0xf))|(1<<4)|(2);//設(shè)置攝像接口時(shí)鐘分頻

          …………

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

          rLCDCON1|=1;//開啟LCD


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

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

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

          //軟件復(fù)位攝像頭
          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);//預(yù)覽縮放開啟
          rCIIMGCPT =(1<<31)|(1<<29);//預(yù)覽縮放捕捉使能

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


          關(guān)鍵詞: s3c2440攝像接

          評(píng)論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();