📄 eeprom.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 + -