本文引用地址:https://www.eepw.com.cn/article/201611/321674.htm// 摄像接口初始化
// 输入参数分别为预览目标宽和高(即 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 <<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;
}
}
}
评论