S3C2440之Camera驱动代码模板(RealView MDK)

好记心不如烂笔头,为方便以后查看代码及代码重复利用,这里贴出S3C2440 Camera驱动代码。使用友善MINI2440开发板,开发环境为RealView MDK 4.22。

原始工程下载地址:点击打开链接

最初,本人在网上下载了许多mini2440 camera驱动的代码,但结果都不尽人意,因为这些代码看起来都比较晦涩难懂,都是直接对寄存器进行位与位或操作,且有的代码排版布局很乱,对初学者来说难度较大。由于本人接触了STM32开发后,觉得STM32的库函数给初学者提供了很大帮助,仅仅通过函数名及变量名就能知道当前操作的是哪个寄存器,这样在阅读代码时就能很容易明白代码的含义了,增强了程序的可读性。由此启发,本人也仿照STM32库函数的风格,写了一个基于S3C2440 CAMIF的库函数,这样当以后自己回过头来再看自己写的代码时就能很快理解代码的含义,也能帮助其他学习2440 camera的初学者,让他们能更容易理解代码的思路。


结构体定义:

typedef struct 
{
	//SOURCE FORMAT REGISTER
	u32 ITU601_656n;
	u32 UVOffset;
	u32 SourceHsize;
	u32 Order422;
	u32 SourceVsize;

	//WINDOW OPTION REGISTER
	u32 WinOfsEn;
	u32 WinHorOfst;
	u32 WinVerOfst;

	//GLOBAL CONTROL REGISTER
	u32 TestPattern;
	u32 InvPolCAMPCLK;
	u32 InvPolCAMVSYNC;
	u32 InvPolCAMHREF;
	
}CAMIF_InitTypeDef;


typedef struct
{
	//Y START ADDRESS REGISTER
	u32 YStartAddr1;
	u32 YStartAddr2;
	u32 YStartAddr3;
	u32 YStartAddr4;

	//Cb START ADDRESS REGISTER
	u32 CbStartAddr1;
	u32 CbStartAddr2;
	u32 CbStartAddr3;
	u32 CbStartAddr4;

	//Cr START ADDRESS REGISTER
	u32 CrStartAddr1;
	u32 CrStartAddr2;
	u32 CrStartAddr3;
	u32 CrStartAddr4;

	//CODEC TARGET FORMAT REGISTER
	u32 In422_Co;
	u32 Out422_Co;
	u32 TargetHsize_Co;
	u32 FlipMd_Co;
	u32 TargetVsize_Co;

	//CODEC DMA CONTROL REGISTER
	u32 Yburst1_Co;
	u32 Yburst2_Co;
	u32 Cburst1_Co;
	u32 Cburst2_Co;

	//CODEC PRE-SCALER CONTROL REGISTER
	u32 SHfactor_Co;
	u32 PreHorRatio_Co;
	u32 PreVerRatio_Co;
	u32 PreDstWidth_Co;
	u32 PreDstHeight_Co;

	//CODEC MAIN-SCALER CONTROL REGISTER
	u32 ScalerBypass_Co;
	u32 ScaleUpDown_Co;
	u32 MainHorRatio_Co;
	u32 MainVerRatio_Co;

	//CODEC DMA TARGET AREA REGISTER
	u32 TargetArea_Co;

}CAMIF_CodecInitTypeDef;


typedef struct
{
	//RGB START ADDRESS REGISTER
	u32 RGBStartAddr1;
	u32 RGBStartAddr2;
	u32 RGBStartAddr3;
	u32 RGBStartAddr4;

	//PREVIEW TARGET FORMAT REGISTER
	u32 TargetHsize_Pr;
	u32 FlipMd_Pr;
	u32 TargetVsize_Pr;

	//PREVIEW DMA CONTROL REGISTER
	u32 RGBburst1_Pr;
	u32 RGBburst2_Pr;

	//PREVIEW PRE-SCALER CONTROL REGISTER 
	u32 SHfactor_Pr;
	u32 PreHorRatio_Pr;
	u32 PreVerRatio_Pr;
	u32 PreDstWidth_Pr;
	u32 PreDstHeight_Pr;

	//PREVIEW MAIN-SCALER CONTROL REGISTER
	u32 RGBformat_Pr;
	u32 ScaleUpDown_Pr;
	u32 MainHorRatio_Pr;
	u32 MainVerRatio_Pr;
	
	//PREVIEW DMA TARGET AREA REGISTER
	u32 TargetArea_Pr;
	
}CAMIF_PreviewInitTypeDef;

CAMIF接口的配置(主要寄存器的配置):

void CAMIF_Config(unsigned int HorOfst, unsigned int VerOfst)
{
	CAMIF_InitTypeDef CAMIF_InitStruct;
	CAMIF_CodecInitTypeDef CAMIF_CoInitStruct;
	CAMIF_PreviewInitTypeDef CAMIF_PrInitStruct;
	
	unsigned int mainburst, remainburst;
	unsigned int H_Shift, V_Shift;
	unsigned int PreHorRatio, PreVerRatio;
	unsigned int MainHorRatio, MainVerRatio;
	unsigned int SRC_Width, SRC_Height;
	unsigned int DST_Width, DST_Height;

/*********************** global parameters ****************************/
	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);

/*********************** preview scaler parameters ********************/
	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 << H_Shift);
	MainVerRatio=(SRC_Height << 8) / (DST_Height << V_Shift);
	CAMIF_PrInitStruct.MainHorRatio_Pr = MainHorRatio;
	CAMIF_PrInitStruct.MainVerRatio_Pr = MainVerRatio;
	CAMIF_PrInitStruct.ScaleUpDown_Pr = (SRC_Width <= DST_Width) ? ScaleUp : ScaleDown;

	CAMIF_PreviewInit(&CAMIF_PrInitStruct);

/******************* codec scaler parameters **************************/
	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 << H_Shift);
	MainVerRatio=(SRC_Height << 8) / (DST_Height << V_Shift);
	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函数,实现对全局参数寄存器的配置:

void CAMIF_Init(CAMIF_InitTypeDef *pInitStruct)
{
	//SOURCE FORMAT REGISTER
	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);

	//WINDOW OPTION REGISTER
	rCIWDOFST &= ~(0x7FF << 0);
	rCIWDOFST |= (pInitStruct->WinVerOfst << 0);

	rCIWDOFST &= ~(0x7FF << 16);
	rCIWDOFST |= (pInitStruct->WinHorOfst << 16);

	rCIWDOFST &= ~(1 << 31);
	rCIWDOFST |= (pInitStruct->WinOfsEn << 31);

	//GLOBAL CONTROL REGISTER
	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参数寄存器的配置:

void CAMIF_PreviewInit(CAMIF_PreviewInitTypeDef *pPreInitStruct)
{
	//RGB START ADDRESS REGISTER
	rCIPRCLRSA1 = pPreInitStruct->RGBStartAddr1;
	rCIPRCLRSA2 = pPreInitStruct->RGBStartAddr2;
	rCIPRCLRSA3 = pPreInitStruct->RGBStartAddr3;
	rCIPRCLRSA4 = pPreInitStruct->RGBStartAddr4;

	//PREVIEW TARGET FORMAT REGISTER
	rCIPRTRGFMT &= ~(0x1FFF << 0);
	rCIPRTRGFMT |= (pPreInitStruct->TargetVsize_Pr << 0);

	rCIPRTRGFMT &= ~(3 << 14);
	rCIPRTRGFMT |= (pPreInitStruct->FlipMd_Pr << 14);

	rCIPRTRGFMT &= ~(0x1FFF << 16); 
	rCIPRTRGFMT |= (pPreInitStruct->TargetHsize_Pr << 16);

	//PREVIEW DMA CONTROL REGISTER
	rCIPRCTRL &= ~(1 << 2);

	rCIPRCTRL &= ~(0x1F << 14); 
	rCIPRCTRL |= (pPreInitStruct->RGBburst2_Pr << 14);

	rCIPRCTRL &= ~(0x1F << 19); 
	rCIPRCTRL |= (pPreInitStruct->RGBburst1_Pr << 19);

	//PREVIEW PRE-SCALER CONTROL REGISTER
	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);

	//PREVIEW MAIN-SCALER CONTROL REGISTER
	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);

	//PREVIEW DMA TARGET AREA REGISTER
	rCIPRTAREA = pPreInitStruct->TargetArea_Pr;
}

CAMIF_CodecInit函数,实现对Codec参数寄存器的配置:

void CAMIF_CodecInit(CAMIF_CodecInitTypeDef *pCoInitStruct)
{
	//Y START ADDRESS REGISTER
	rCICOYSA1 = (u32)pCoInitStruct->YStartAddr1;
	rCICOYSA2 = (u32)pCoInitStruct->YStartAddr2;
	rCICOYSA3 = (u32)pCoInitStruct->YStartAddr3;
	rCICOYSA4 = (u32)pCoInitStruct->YStartAddr4;

	//CB START ADDRESS REGISTER
	rCICOCBSA1 = (u32)pCoInitStruct->CbStartAddr1;
	rCICOCBSA2 = (u32)pCoInitStruct->CbStartAddr2;
	rCICOCBSA3 = (u32)pCoInitStruct->CbStartAddr3;
	rCICOCBSA4 = (u32)pCoInitStruct->CbStartAddr4;

	//CR START ADDRESS REGISTER
	rCICOCRSA1 = (u32)pCoInitStruct->CrStartAddr1;
	rCICOCRSA2 = (u32)pCoInitStruct->CrStartAddr2;
	rCICOCRSA3 = (u32)pCoInitStruct->CrStartAddr3;
	rCICOCRSA4 = (u32)pCoInitStruct->CrStartAddr4;

	//CODEC TARGET FORMAT REGISTER
	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);

	//CODEC DMA CONTROL REGISTER
	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);

	//CODEC PRE-SCALER CONTROL REGISTER
	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);

	//CODEC MAIN-SCALER CONTROL REGISTER
	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);

	//CODEC DMA TARGET AREA REGISTER
	rCICOTAREA = pCoInitStruct->TargetArea_Co;
}

开启Preview:

void CAMIF_StartPreview(void)
{
	rCIPRSCCTRL |= (1 << 15);
	rCIIMGCPT |= (1 << 29);
	rCIIMGCPT |= (1 << 31);
}

开启Codec:

void CAMIF_StartCapture(void)
{
	rCICOSCCTRL |= (1 << 15);
	rCIIMGCPT |= (1 << 30);
	rCIIMGCPT |= (1 << 31);
}

Camera sensor模块初始化时调用顺序:

void OV9650_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上就能显示预览的图像了。关于更详细的代码,请下载源码工程自行研究。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

何小龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值