?? 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 + -