好记心不如烂笔头,为方便以后查看代码及代码重复利用,这里贴出S3C2440 Camera驱动代码。使用友善MINI2440开发板,开发环境为RealView MDK 4.22。
原始工程下载地址:点击打开链接
*初,本人在网上下载了许多mini2440 camera驱动的代码,但结果都不尽人意,因为这些代码看起来都比较晦涩难懂,都是直接对寄存器进行位与位或操作,且有的代码排版布局很乱,对初学者来说难度较大。由于本人接触了STM32开发后,觉得STM32的库函数给初学者提供了很大帮助,仅仅通过函数名及变量名就能知道当前操作的是哪个寄存器,这样在阅读代码时就能很容易明白代码的含义了,增强了程序的可读性。由此启发,本人也仿照STM32库函数的风格,写了一个基于S3C2440 CAMIF的库函数,这样当以后自己回过头来再看自己写的代码时就能很快理解代码的含义,也能帮助其他学习2440 camera的初学者,让他们能更容易理解代码的思路。
结构体定义:
typedefstruct
{
//SOURCEFORMATREGISTER
u32ITU601_656n;
u32UVOffset;
u32SourceHsize;
u32Order422;
u32SourceVsize;
//WINDOWOPTIONREGISTER
u32WinOfsEn;
u32WinHorOfst;
u32WinVerOfst;
//GLOBALCONTROLREGISTER
u32TestPattern;
u32InvPolCAMPCLK;
u32InvPolCAMVSYNC;
u32InvPolCAMHREF;
}CAMIF_InitTypeDef;
typedefstruct
{
//YSTARTADDRESSREGISTER
u32YStartAddr1;
u32YStartAddr2;
u32YStartAddr3;
u32YStartAddr4;
//CbSTARTADDRESSREGISTER
u32CbStartAddr1;
u32CbStartAddr2;
u32CbStartAddr3;
u32CbStartAddr4;
//CrSTARTADDRESSREGISTER
u32CrStartAddr1;
u32CrStartAddr2;
u32CrStartAddr3;
u32CrStartAddr4;
//CODECTARGETFORMATREGISTER
u32In422_Co;
u32Out422_Co;
u32TargetHsize_Co;
u32FlipMd_Co;
u32TargetVsize_Co;
//CODECDMACONTROLREGISTER
u32Yburst1_Co;
u32Yburst2_Co;
u32Cburst1_Co;
u32Cburst2_Co;
//CODECPRE-SCALERCONTROLREGISTER
u32SHfactor_Co;
u32PreHorRatio_Co;
u32PreVerRatio_Co;
u32PreDstWidth_Co;
u32PreDstHeight_Co;
//CODECMAIN-SCALERCONTROLREGISTER
u32ScalerBypass_Co;
u32ScaleUpDown_Co;
u32MainHorRatio_Co;
u32MainVerRatio_Co;
//CODECDMATARGETAREAREGISTER
u32TargetArea_Co;
}CAMIF_CodecInitTypeDef;
typedefstruct
{
//RGBSTARTADDRESSREGISTER
u32RGBStartAddr1;
u32RGBStartAddr2;
u32RGBStartAddr3;
u32RGBStartAddr4;
//PREVIEWTARGETFORMATREGISTER
u32TargetHsize_Pr;
u32FlipMd_Pr;
u32TargetVsize_Pr;
//PREVIEWDMACONTROLREGISTER
u32RGBburst1_Pr;
u32RGBburst2_Pr;
//PREVIEWPRE-SCALERCONTROLREGISTER
u32SHfactor_Pr;
u32PreHorRatio_Pr;
u32PreVerRatio_Pr;
u32PreDstWidth_Pr;
u32PreDstHeight_Pr;
//PREVIEWMAIN-SCALERCONTROLREGISTER
u32RGBformat_Pr;
u32ScaleUpDown_Pr;
u32MainHorRatio_Pr;
u32MainVerRatio_Pr;
//PREVIEWDMATARGETAREAREGISTER
u32TargetArea_Pr;
}CAMIF_PreviewInitTypeDef;
CAMIF接口的配置(主要寄存器的配置):
voidCAMIF_Config(unsignedintHorOfst,unsignedintVerOfst)
{
CAMIF_InitTypeDefCAMIF_InitStruct;
CAMIF_CodecInitTypeDefCAMIF_CoInitStruct;
CAMIF_PreviewInitTypeDefCAMIF_PrInitStruct;
unsignedintmainburst,remainburst;
unsignedintH_Shift,V_Shift;
unsignedintPreHorRatio,PreVerRatio;
unsignedintMainHorRatio,MainVerRatio;
unsignedintSRC_Width,SRC_Height;
unsignedintDST_Width,DST_Height;
/***********************globalparameters****************************/
CAMIF_InitStruct.ITU601_656n=ITU_601;
CAMIF_InitStruct.UVOffset=UVOffest_0;
CAMIF_InitStruct.Order422=Order_YCbYCr;
CAMIF_InitStruct.SourceHsize=CAM_XSIZE;
CAMIF_InitStruct.SourceVsize=CAM_YSIZE;
CAMIF_InitStruct.WinOfsEn=(HorOfst||VerOfst)?1:0;
CAMIF_InitStruct.WinHorOfst=HorOfst;
CAMIF_InitStruct.WinVerOfst=VerOfst;
CAMIF_InitStruct.TestPattern=Pattern_Normal;
CAMIF_InitStruct.InvPolCAMPCLK=ENABLE;
CAMIF_InitStruct.InvPolCAMHREF=DISABLE;
CAMIF_InitStruct.InvPolCAMVSYNC=DISABLE;
CAMIF_Init(&CAMIF_InitStruct);
/***********************previewscalerparameters********************/
CAMIF_PrInitStruct.RGBStartAddr1=(u32)LCD_BUFFER;
CAMIF_PrInitStruct.RGBStartAddr2=(u32)LCD_BUFFER;
CAMIF_PrInitStruct.RGBStartAddr3=(u32)LCD_BUFFER;
CAMIF_PrInitStruct.RGBStartAddr4=(u32)LCD_BUFFER;
CAMIF_PrInitStruct.RGBformat_Pr=RGBformat_16;
CAMIF_PrInitStruct.FlipMd_Pr=FlipMode_Xmirror;
CAMIF_PrInitStruct.TargetHsize_Pr=LCD_XSIZE;
CAMIF_PrInitStruct.TargetVsize_Pr=LCD_YSIZE;
CAMIF_PrInitStruct.TargetArea_Pr=LCD_XSIZE*LCD_YSIZE;
CalcBurstSize(LCD_XSIZE*2,&mainburst,&remainburst);
CAMIF_PrInitStruct.RGBburst1_Pr=mainburst;
CAMIF_PrInitStruct.RGBburst2_Pr=remainburst;
SRC_Width=CAM_XSIZE-(2*HorOfst);
SRC_Height=CAM_YSIZE-(2*VerOfst);
DST_Width=LCD_XSIZE;
DST_Height=LCD_YSIZE;
CalcPrescaleParam(SRC_Width,DST_Width,&PreHorRatio,&H_Shift);
CalcPrescaleParam(SRC_Height,DST_Height,&PreVerRatio,&V_Shift);
CAMIF_PrInitStruct.SHfactor_Pr=10-H_Shift-V_Shift;
CAMIF_PrInitStruct.PreHorRatio_Pr=PreHorRatio;
CAMIF_PrInitStruct.PreVerRatio_Pr=PreVerRatio;
CAMIF_PrInitStruct.PreDstWidth_Pr=SRC_Width/PreHorRatio;
CAMIF_PrInitStruct.PreDstHeight_Pr=SRC_Height/PreVerRatio;
MainHorRatio=(SRC_Width<<8)/(DST_Width< MainVerRatio=(SRC_Height<<8)/(DST_Height< CAMIF_PrInitStruct.MainHorRatio_Pr=MainHorRatio; CAMIF_PrInitStruct.MainVerRatio_Pr=MainVerRatio; CAMIF_PrInitStruct.ScaleUpDown_Pr=(SRC_Width<=DST_Width)?ScaleUp:ScaleDown; CAMIF_PreviewInit(&CAMIF_PrInitStruct); /*******************codecscalerparameters**************************/ CAMIF_CoInitStruct.YStartAddr1=(u32)CaptureY_Buf; CAMIF_CoInitStruct.YStartAddr2=(u32)CaptureY_Buf; CAMIF_CoInitStruct.YStartAddr3=(u32)CaptureY_Buf; CAMIF_CoInitStruct.YStartAddr4=(u32)CaptureY_Buf; CAMIF_CoInitStruct.CbStartAddr1=(u32)CaptureCb_Buf; CAMIF_CoInitStruct.CbStartAddr2=(u32)CaptureCb_Buf; CAMIF_CoInitStruct.CbStartAddr3=(u32)CaptureCb_Buf; CAMIF_CoInitStruct.CbStartAddr4=(u32)CaptureCb_Buf; CAMIF_CoInitStruct.CrStartAddr1=(u32)CaptureCr_Buf; CAMIF_CoInitStruct.CrStartAddr2=(u32)CaptureCr_Buf; CAMIF_CoInitStruct.CrStartAddr3=(u32)CaptureCr_Buf; CAMIF_CoInitStruct.CrStartAddr4=(u32)CaptureCr_Buf; CAMIF_CoInitStruct.In422_Co=YCbCr_422; CAMIF_CoInitStruct.Out422_Co=YCbCr_422; CAMIF_CoInitStruct.FlipMd_Co=FlipMode_Xmirror; CAMIF_CoInitStruct.TargetHsize_Co=LCD_XSIZE; CAMIF_CoInitStruct.TargetVsize_Co=LCD_YSIZE; CAMIF_CoInitStruct.TargetArea_Co=LCD_XSIZE*LCD_YSIZE; CalcBurstSize(LCD_XSIZE,&mainburst,&remainburst); CAMIF_CoInitStruct.Yburst1_Co=mainburst; CAMIF_CoInitStruct.Yburst2_Co=remainburst; CalcBurstSize(LCD_YSIZE/2,&mainburst,&remainburst); CAMIF_CoInitStruct.Cburst1_Co=mainburst; CAMIF_CoInitStruct.Cburst2_Co=remainburst; SRC_Width=CAM_XSIZE-(2*HorOfst); SRC_Height=CAM_YSIZE-(2*VerOfst); DST_Width=LCD_XSIZE; DST_Height=LCD_YSIZE; CalcPrescaleParam(SRC_Width,DST_Width,&PreHorRatio,&H_Shift); CalcPrescaleParam(SRC_Height,DST_Height,&PreVerRatio,&V_Shift); CAMIF_CoInitStruct.SHfactor_Co=10-H_Shift-V_Shift; CAMIF_CoInitStruct.PreHorRatio_Co=PreHorRatio; CAMIF_CoInitStruct.PreVerRatio_Co=PreVerRatio; CAMIF_CoInitStruct.PreDstWidth_Co=SRC_Width/PreHorRatio; CAMIF_CoInitStruct.PreDstHeight_Co=SRC_Height/PreVerRatio; MainHorRatio=(SRC_Width<<8)/(DST_Width< MainVerRatio=(SRC_Height<<8)/(DST_Height< CAMIF_CoInitStruct.MainHorRatio_Co=MainHorRatio; CAMIF_CoInitStruct.MainVerRatio_Co=MainVerRatio; CAMIF_CoInitStruct.ScaleUpDown_Co=(SRC_Width<=DST_Width)?ScaleUp:ScaleDown; CAMIF_CoInitStruct.ScalerBypass_Co=DISABLE; CAMIF_CodecInit(&CAMIF_CoInitStruct); } CAMIF_Init函数,实现对全局参数寄存器的配置: voidCAMIF_Init(CAMIF_InitTypeDef*pInitStruct) { //SOURCEFORMATREGISTER rCISRCFMT&=~(0x1FFF<<0); rCISRCFMT|=(pInitStruct->SourceVsize<<0); rCISRCFMT&=~(3<<14); rCISRCFMT|=(pInitStruct->Order422<<14); rCISRCFMT&=~(0x1FFF<<16); rCISRCFMT|=(pInitStruct->SourceHsize<<16); rCISRCFMT&=~(1<<30); rCISRCFMT|=(pInitStruct->UVOffset<<30); rCISRCFMT&=~(1<<31); rCISRCFMT|=(pInitStruct->ITU601_656n<<31); //WINDOWOPTIONREGISTER rCIWDOFST&=~(0x7FF<<0); rCIWDOFST|=(pInitStruct->WinVerOfst<<0); rCIWDOFST&=~(0x7FF<<16); rCIWDOFST|=(pInitStruct->WinHorOfst<<16); rCIWDOFST&=~(1<<31); rCIWDOFST|=(pInitStruct->WinOfsEn<<31); //GLOBALCONTROLREGISTER rCIGCTRL&=~(1<<24); rCIGCTRL|=(pInitStruct->InvPolCAMVSYNC<<24); rCIGCTRL&=~(1<<25); rCIGCTRL|=(pInitStruct->InvPolCAMHREF<<25); rCIGCTRL&=~(1<<26); rCIGCTRL|=(pInitStruct->InvPolCAMPCLK<<26); rCIGCTRL&=~(3<<27); rCIGCTRL|=(pInitStruct->TestPattern<<27); rCIGCTRL|=(1<<29); } CAMIF_PreviewInit函数,实现对Preview参数寄存器的配置: voidCAMIF_PreviewInit(CAMIF_PreviewInitTypeDef*pPreInitStruct) { //RGBSTARTADDRESSREGISTER rCIPRCLRSA1=pPreInitStruct->RGBStartAddr1; rCIPRCLRSA2=pPreInitStruct->RGBStartAddr2; rCIPRCLRSA3=pPreInitStruct->RGBStartAddr3; rCIPRCLRSA4=pPreInitStruct->RGBStartAddr4; //PREVIEWTARGETFORMATREGISTER rCIPRTRGFMT&=~(0x1FFF<<0); rCIPRTRGFMT|=(pPreInitStruct->TargetVsize_Pr<<0); rCIPRTRGFMT&=~(3<<14); rCIPRTRGFMT|=(pPreInitStruct->FlipMd_Pr<<14); rCIPRTRGFMT&=~(0x1FFF<<16); rCIPRTRGFMT|=(pPreInitStruct->TargetHsize_Pr<<16); //PREVIEWDMACONTROLREGISTER rCIPRCTRL&=~(1<<2); rCIPRCTRL&=~(0x1F<<14); rCIPRCTRL|=(pPreInitStruct->RGBburst2_Pr<<14); rCIPRCTRL&=~(0x1F<<19); rCIPRCTRL|=(pPreInitStruct->RGBburst1_Pr<<19); //PREVIEWPRE-SCALERCONTROLREGISTER rCIPRSCPRERATIO&=~(0x7F<<0); rCIPRSCPRERATIO|=(pPreInitStruct->PreVerRatio_Pr<<0); rCIPRSCPRERATIO&=~(0x7F<<16); rCIPRSCPRERATIO|=(pPreInitStruct->PreHorRatio_Pr<<16); rCIPRSCPRERATIO&=~(0xF<<28); rCIPRSCPRERATIO|=(pPreInitStruct->SHfactor_Pr<<28); rCIPRSCPREDST&=~(0xFFF<<0); rCIPRSCPREDST|=(pPreInitStruct->PreDstHeight_Pr<<0); rCIPRSCPREDST&=~(0xFFF<<16); rCIPRSCPREDST|=(pPreInitStruct->PreDstWidth_Pr<<16); //PREVIEWMAIN-SCALERCONTROLREGISTER rCIPRSCCTRL&=~(0x1FF<<0); rCIPRSCCTRL|=(pPreInitStruct->MainVerRatio_Pr<<0); rCIPRSCCTRL&=~(1<<15); rCIPRSCCTRL&=~(0x1FF<<16); rCIPRSCCTRL|=(pPreInitStruct->MainHorRatio_Pr<<16); rCIPRSCCTRL&=~(3<<28); rCIPRSCCTRL|=(pPreInitStruct->ScaleUpDown_Pr<<28); rCIPRSCCTRL&=~(1<<30); rCIPRSCCTRL|=(pPreInitStruct->RGBformat_Pr<<30); rCIPRSCCTRL|=(1<<31); //PREVIEWDMATARGETAREAREGISTER rCIPRTAREA=pPreInitStruct->TargetArea_Pr; } CAMIF_CodecInit函数,实现对Codec参数寄存器的配置: voidCAMIF_CodecInit(CAMIF_CodecInitTypeDef*pCoInitStruct) { //YSTARTADDRESSREGISTER rCICOYSA1=(u32)pCoInitStruct->YStartAddr1; rCICOYSA2=(u32)pCoInitStruct->YStartAddr2; rCICOYSA3=(u32)pCoInitStruct->YStartAddr3; rCICOYSA4=(u32)pCoInitStruct->YStartAddr4; //CBSTARTADDRESSREGISTER rCICOCBSA1=(u32)pCoInitStruct->CbStartAddr1; rCICOCBSA2=(u32)pCoInitStruct->CbStartAddr2; rCICOCBSA3=(u32)pCoInitStruct->CbStartAddr3; rCICOCBSA4=(u32)pCoInitStruct->CbStartAddr4; //CRSTARTADDRESSREGISTER rCICOCRSA1=(u32)pCoInitStruct->CrStartAddr1; rCICOCRSA2=(u32)pCoInitStruct->CrStartAddr2; rCICOCRSA3=(u32)pCoInitStruct->CrStartAddr3; rCICOCRSA4=(u32)pCoInitStruct->CrStartAddr4; //CODECTARGETFORMATREGISTER rCICOTRGFMT&=~(0x1FFF<<0); rCICOTRGFMT|=(pCoInitStruct->TargetVsize_Co<<0); rCICOTRGFMT&=~(3<<14); rCICOTRGFMT|=(pCoInitStruct->FlipMd_Co<<14); rCICOTRGFMT&=~(0x1FFF<<16); rCICOTRGFMT|=(pCoInitStruct->TargetHsize_Co<<16); rCICOTRGFMT&=~(1<<30); rCICOTRGFMT|=(pCoInitStruct->Out422_Co<<30); rCICOTRGFMT&=~(1<<31); rCICOTRGFMT|=(pCoInitStruct->In422_Co<<31); //CODECDMACONTROLREGISTER rCICOCTRL&=~(1<<2); rCICOCTRL&=~(0x1F<<4); rCICOCTRL|=(pCoInitStruct->Cburst2_Co<<4); rCICOCTRL&=~(0x1F<<9); rCICOCTRL|=(pCoInitStruct->Cburst1_Co<<9); rCICOCTRL&=~(0x1F<<14); rCICOCTRL|=(pCoInitStruct->Yburst2_Co<<14); rCICOCTRL&=~(0x1F<<19); rCICOCTRL|=(pCoInitStruct->Yburst1_Co<<19); //CODECPRE-SCALERCONTROLREGISTER rCICOSCPRERATIO&=~(0x7F<<0); rCICOSCPRERATIO|=(pCoInitStruct->PreVerRatio_Co<<0); rCICOSCPRERATIO&=~(0x7F<<16); rCICOSCPRERATIO|=(pCoInitStruct->PreHorRatio_Co<<16); rCICOSCPRERATIO&=~(0xF<<28); rCICOSCPRERATIO|=(pCoInitStruct->SHfactor_Co<<28); rCICOSCPREDST&=~(0xFFF<<0); rCICOSCPREDST|=(pCoInitStruct->PreDstHeight_Co<<0); rCICOSCPREDST&=~(0xFFF<<16); rCICOSCPREDST|=(pCoInitStruct->PreDstWidth_Co<<16); //CODECMAIN-SCALERCONTROLREGISTER rCICOSCCTRL&=~(0x1FF<<0); rCICOSCCTRL|=(pCoInitStruct->MainVerRatio_Co<<0); rCICOSCCTRL&=~(1<<15); rCICOSCCTRL&=~(0x1FF<<16); rCICOSCCTRL|=(pCoInitStruct->MainHorRatio_Co<<16); rCICOSCCTRL&=~(3<<29); rCICOSCCTRL|=(pCoInitStruct->ScaleUpDown_Co<<29); rCICOSCCTRL&=~(1<<31); rCICOSCCTRL|=(pCoInitStruct->ScalerBypass_Co<<31); //CODECDMATARGETAREAREGISTER rCICOTAREA=pCoInitStruct->TargetArea_Co; } 开启Preview: voidCAMIF_StartPreview(void) { rCIPRSCCTRL|=(1<<15); rCIIMGCPT|=(1<<29); rCIIMGCPT|=(1<<31); } 开启Codec: voidCAMIF_StartCapture(void) { rCICOSCCTRL|=(1<<15); rCIIMGCPT|=(1<<30); rCIIMGCPT|=(1<<31); } Camera sensor模块初始化时调用顺序: voidOV9650_Init(void) { CAMIF_Clock_Init(); CAMIF_GPIO_Config(); CAMIF_ResetIF(); CAMIF_ResetMoudle(); CAMIF_Config(0,0); SCCB_Init(); OV9650_CheckPID(); OV9650_Config(); CAMIF_StartPreview(); CAMIF_StartCapture(); } 执行到这里,你的LCD上就能显示预览的图像了。关于更详细的代码,请下载源码工程自行研究。 百检网秉承“客户至上,服务为先,精诚合作,以人为本”的经营理念,始终站在用户的角度解决问题,为客户提供“一站购物式”的新奇检测体验,打开网站,像挑选商品一样简单,方便。打破行业信息壁垒,建构消费和检测机构之间高效的沟通平台