⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eeprom.c

📁 arm9处理器
💻 C
字号:
/*
 create by hzh, to support wr/rd parameters to/from eeprom
*/
#include "def.h"
#include "2440addr.h"
#include "2440lib.h"

#define	SLV_ADDR_24C02	0xa0//定义EEPROM的地址
//#define	SLV_ADDR_CAMERA	0x5a//定义CAMERA的地址,OV9650的写地址应该是0x60,读地址应该是0x61,有问题,feipeng
#define	SLV_ADDR_CAMERA_WRITE 0x60//feipeng
#define	SLV_ADDR_CAMERA_READ 0x61//feipeng
void mdelay(int ms);

static volatile int iic_ints;

static void __irq IicInt(void)//中断服务子函数,feipeng
{
	ClearPending(BIT_IIC);//清中断未决位,feipeng
	iic_ints++;//?
}

static int iic_wr(U8 data, U8 cnt)//写IIC总线,feipeng
{
	int i, c;

	for(i=0; i<20; i++);
	
	if(cnt)
		rIICDS = data;//写数据
		
	rIICCON &= ~0x10;		//Resume IIC operation to send

	i = 3;	//3ms
	//while(!(rIICCON&0x10)&&i--) mdelay(1);
	c = iic_ints;//只有发生中断时,iic_ints才改变,feipeng
	
	while(iic_ints==c&&i--)//延时3ms 
		mdelay(1);
	//rIICCON &= ~0x10;
	
	if(!i)
		return -1;

	return (rIICSTAT&1)?-1:0;//收到ACK返回-1.未收到ACK返回0,feipeng
}

static int iic_rd(U8 *pBuf)
{
	int i, c;
	
	for(i=0; i<20; i++);
	
	rIICCON &= ~0x10;		//Resumes IIC operation to receive
	i = 3;	//3ms
	//while(!(rIICCON&0x10)&&i--) mdelay(1);
	c = iic_ints;
	while(iic_ints==c&i--) mdelay(1);
	
	if(i) {
		*pBuf = rIICDS;
		return 0;
	}
	
	return -1;
}

static int seek_iic_device(U8 slvAddr)
{
	int i;
	U8 d;
	
	i = 200;				//200ms
	while(i--) 
	{
		rIICDS   = slvAddr;
		
		//IICSTAT	Mode select		Busy stat/Start_Stop Condition		Serial output		Arbitration stat flag		Addr_as_slave stat flag		Addr zero stat flag		Last_receive bit stat flag
		//				10					1									1					0						0							0						0						
		//STAT		Master Rx			Start 							Enable Rx/Tx
		rIICSTAT = 0xb0;	//read mode
		
		if(!iic_wr(0, 0)) 
		{
			iic_rd(&d);
			break;
		}
		mdelay(1);
	}
	
	//IICSTAT	Mode select		Busy stat/Start_Stop Condition		Serial output		Arbitration stat flag		Addr_as_slave stat flag		Addr zero stat flag		Last_receive bit stat flag
	//				10					0									1					0						0							0						0						
	//STAT		Master Rx				Stop 						Enable Rx/Tx
	rIICSTAT = 0x90;
	
	rIICCON &= ~0x10;		//Resume IIC operation to send stop
	mdelay(1);

	return (i>=0)?0:-1;
}

//8 bits register address only
static int write_eeprom(U8 slvAddr, U8 addr, U8 data)//IIC 写从属设备,feipeng
{
	int i;
	U8 ch[3];
	
	ch[1] = addr;
	ch[2] = data;
	
	rIICDS   = slvAddr;//写从属地址,feipeng
	
	
	
	//IICSTAT	Mode select		Busy stat/Start_Stop Condition		Serial output		Arbitration stat flag		Addr_as_slave stat flag		Addr zero stat flag		Last_receive bit stat flag
	//				11					1									1					0						0							0						0						
	//STAT		Master Tx			Start 							Enable Rx/Tx
	rIICSTAT = 0xf0;		//MasTx,Start//发送开始,feipeng
	
	for(i=0; i<3; i++)
		if(iic_wr(ch[i], i))
			break;
	
	//IICSTAT	Mode select		Busy stat/Start_Stop Condition		Serial output		Arbitration stat flag		Addr_as_slave stat flag		Addr zero stat flag		Last_receive bit stat flag
	//				11					0									1					0						0							0						0						
	//STAT		Master Tx				Stop 						Enable Rx/Tx		
	rIICSTAT = 0xd0;		//Stop MasTx condition//发送停止,feipeng
	
	
	
	
	
	rIICCON &= ~0x10;		//Resume IIC operation to send stop
	mdelay(1);
	
	if(i<3)
		return -1;
		
	return seek_iic_device(slvAddr);
}

//8 bits register address only
static int read_eeprom(U8 slvAddr, U8 addr, U8 *pBuf)
{
	int i;
	U8 ch[2];
	
	ch[1] = addr;
	
	rIICDS   = slvAddr;
	rIICSTAT = 0xf0;		//MasTx,Start
	for(i=0; i<2; i++)
		if(iic_wr(ch[i], i))
			break;
	if(i<2) {
		rIICSTAT = 0xd0;	//Stop MasTx condition
		rIICCON &= ~0x10;	//Resume IIC operation to send stop
		mdelay(1);
		return -1;
	}

	rIICDS   = slvAddr;
	rIICSTAT = 0xb0;		//Master Rx,Start
	if(!iic_wr(0, 0))		//wait ack
		i = iic_rd(pBuf);
	rIICSTAT = 0x90;		//Stop MaxRx condition
	rIICCON &= ~0x10;		//Resume IIC operation to send stop
	mdelay(1);
	
	return i;
}

static void init_iic_op(void)//初始化IIC操作,feipeng   
{
	rCLKCON |= 1<<16;//control PCLK into IIC block,feipeng
	
	rGPEUP  |= 0xc000;                  //Pull-up disable?有意义吗?feipeng
	rGPECON &= ~0xf0000000;				//GPE14\GPE15作为输入,feipeng
	rGPECON |= 0xa0000000;              //GPE15:IICSDA , GPE14:IICSCL 
	
	//Enable ACK, Prescaler IICCLK=PCLK/16, Enable interrupt, Transmit clock value Tx clock=IICCLK/16
	// If PCLK 50.7MHz, IICCLK = 3.17MHz, Tx Clock = 0.198MHz
	//rIICCON = (1<<7) | (1<<6) | (1<<5) | (0);	//IICCLK=PCLK/512=97K
	
	//just read one byte, don't enable ack!
	rIICCON = (0<<7) | (1<<6) | (1<<5) | (0);	//IICCLK=PCLK/512=97K
	//  disable ack  iicclk=1/512pclk Tx/Rx interrupt enable
	rIICSTAT = 0x10;                    //IIC bus data output enable(Rx/Tx),serial output enable,feipeng//从属接收模式
	rIICADD  = 0x10;                    //2410 slave address = [7:1]serial output enable时,按datasheet,rIICADD不能写?,feipeng//2440作为从属设备的地址
	
	pISR_IIC = (unsigned)IicInt;//中断向量关联中断子函数,feipeng,注意,只用函数名,不带()
	EnableIrq(BIT_IIC);//中断使能,feipeng
}

static void end_iic_op(void)
{
//	rCLKCON &= ~(1<<16);
	DisableIrq(BIT_IIC);
}

int write_24c02(U8 *pBuf)
{
	int i;
	
	init_iic_op();
	
	for(i=0; i<256; i++) {
		//if(seek_iic_device(SLV_ADDR_24C02))
		//	break;
		if(write_eeprom(SLV_ADDR_24C02, i, pBuf[i]))
			break;
	}
	
	end_iic_op();
	
	Uart_Printf("Write EEPROM %s!\n", (i<256)?"Fail":"Success");
	
	return i<256;
}

int read_24c02(U8 *pBuf)
{
	int i;
	
	init_iic_op();
	
	for(i=0; i<256; i++) {
		if(read_eeprom(SLV_ADDR_24C02, i, pBuf+i))
			break;
	}
	
	end_iic_op();
	
	Uart_Printf("Read EEPROM %s!\n", (i<256)?"Fail":"Success");

	return i<256;
}

int find_camera(void)
{
	int ret = -2;
	U8 d[256];
	
	rGPGCON &= ~(3<<24);//GPG12作为输入,feipeng
	rGPGCON |= 1<<24;//GPG12作为输出,feipeng
	rGPGUP  &= ~(1<<12);//GPG12内部上拉禁用,feipeng
	rGPGDAT |= 1<<12;//GPG12输出1,feipeng
	
	rGPJCON = 0x1aaaaaa;//GPJ口为作为Cam口,但GPJ12作为输出,连接CAMRESET,用于复位, 不是0x2aaaaaa?feipeng
	rGPJUP  = 0;//内部上拉禁用,feipeng
	
	//以下四句复位camera,上升沿,feipeng
	rGPJDAT = 0;//GPJ12输出0,feipeng
	mdelay(10);//延时10ms,函数没看,feipeng
	rGPJDAT = 1<<12;//GPJ12输出1,feipeng
	mdelay(10);//延时10ms,函数没看,feipeng
	
	init_iic_op();//IIC总线初始化操作,IIC中断使能,关联中断向量
	
	if(!write_eeprom(SLV_ADDR_CAMERA_WRITE, 0xec, 0)) //三个参数依次为从属设备参数,内部地址,数据,改了
	{
		int i, a;
		
		ret = -1;
		a = 0xb0;
		for(i=0; i<4; i++)
			if(read_eeprom(SLV_ADDR_CAMERA_READ, a+i, d+i))//feipeng,SLV_ADDR_CAMERA到SLV_ADDR_CAMERA_READ
				break;
		if(i>=4)
			ret = 0;
		
	//	Uart_Printf("i = %d\n", i);
	//	for(i=0; i<256; i++)
	//		Uart_Printf("%c%02x", (i%16)?' ':'\n', d[i]);
	}
	
	end_iic_op();

	switch(ret)	{
	case -2:
		Uart_Printf("Fail to write camera IIC!\n");
		break;
	case -1:
		Uart_Printf("Fail to read camera IIC!\n");
		break;
	case 0:
		Uart_Printf("Read camera ID is 0x%04x, ", (d[0]<<8)|d[1]);
		Uart_Printf("chip version is 0x%04x\n", (d[2]<<8)|d[3]);
		break;
	default:
		break;
	}
		
	return ret;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -