/************************************************************************ *** Copyright(c) 2009,by XH Du *** *** All right reserved. 引用请注明出处***
*** 文件名:NEC_78K0_i2c.c *** 当前版本:1.2 *** 完成日期:2009-12-08 *** 作 者:XH Du
*** 功能描述:NEC的硬件I2C 操作 ************************************************************************/ #include "macrodriver.h" #include "NEC_78K0_system_clk.h" #include "NEC_78K0_i2c.h"
static UCHAR I2CWaitDelay;
// **头文件中的部分内容**************************************
typedef unsigned char bool;
#define IICCL0_INITIALVALUE 0x00 #define IIC0_CLOCK2 0x02 #define IIC0_EXPENSION0 0x00
#define I2C_ERR 0 #define I2C_CRR 1
#define I2CStart() {STT0 = 1;} #define I2CStop() {SPT0 = 1;} #define I2CSendByte(x) {IIC0 = x;} #define I2CEightIsr() {WTIM0 = 0;} #define I2CNinthIsr() {WTIM0 = 1;} #define I2CRcvNoAck() {ACKE0 = 0;} #define I2CRcvAck() {ACKE0 = 1;} #define I2CWait() {WREL0 = 0;} #define I2CCanWait() {WREL0 = 1;} //********************************************************
/******************************************************************************* ** Abstract: ** This function initializes IIC0. ** ** Parameters: ** None ** ** Returns: ** None ** *******************************************************************************/ void IIC0_Init(void) { IICE0 = 0; /* IIC0 disable */ IICMK0 = 1; /* INTIIC0 disable */ IICIF0 = 0; /* clear INTIIC0 interrupt flag */ /* Set INTIIC0 low priority */ IICPR0 = 1; /* Set clock pin for IIC0 */ PM6 &= ~0x1; P6 &= ~0x1; /* Set data transfer I/O pin for IIC0 */ PM6 &= ~0x2; P6 &= ~0x2; /*Set IIC0 clock*/ IICCL0 = IICCL0_INITIALVALUE | IIC0_CLOCK2; IICX0 = IIC0_EXPENSION0;
STCEN = 1; //After operation is enabled (IICE0 = 1), enable generation of a start condition without detecting a stop condition. IICRSV = 1; //Disable communication reservation SPIE0 = 0; //Disable generation of interrupt request when stop condition is detected WTIM0 = 1; //Interrupt request is generated at the ninth clock's falling edge. ACKE0 = 1; //No auto acknowledge WREL0 = 1; IICE0 = 1; /* IIC0 ensable */ LREL0 = 1; /*normal operation*/ STT0 = 0; //Generate no start condition SPT0 = 1; //IICMK0 = 0; }
/********************************************************************* ******************* I2C 等待时间处理 ********************************* *******************(定时器中调用时间比较准确)************************* *********************************************************************/ void I2CWaitDelayProcess(void) { if((I2CWaitDelay>0) && (I2CWaitDelay<=250)) { I2CWaitDelay--; } }
/************************************************************ *******************检测I2C总线是否忙状态 **********************
************************************************************/ bool SysI2CCheckBusy(void) { I2CWaitDelay = 100; //Wait 1S while((IICBSY==1) && (I2CWaitDelay>0)) { NOP(); }
if(I2CWaitDelay<=0) //overtime { SPT0 = 1; return I2C_ERR; } else { I2CWaitDelay = 100; //Wait 1S while((SPT0==1 || STT0==1) && (I2CWaitDelay>0)) { NOP(); } if(I2CWaitDelay<=0) { SPT0 = 1; return I2C_ERR; } else { return I2C_CRR; } } }
/******************************************************* ********************Start I2C***************************** *******************************************************/ bool SysI2C_Start(void) { I2CStart(); /*Generate a start condition */ I2CWaitDelay = 100; //Wait 1S
while((!STD0) && (I2CWaitDelay>0)) { NOP(); } if(I2CWaitDelay<=0) //overtime { SPT0 = 1; return I2C_ERR; } else { return I2C_CRR; } }
/******************************************************* ********************Stop I2C***************************** *******************************************************/ bool SysI2C_Stop(void) { I2CStop(); I2CWaitDelay = 100; //Wait 1S
while((!SPD0) && (I2CWaitDelay>0)) { NOP(); } if(I2CWaitDelay<=0) //overtime { return I2C_ERR; } else { return I2C_CRR; } }
/******************************************************* **************** Wait ack and judge overtime *************** *******************************************************/ bool SysI2CWaitAck(void) { I2CWaitDelay = 100; //Wait 1S while((!IICIF0) && (I2CWaitDelay>0)) // { NOP(); }
if(I2CWaitDelay<=0) //overtime { SPT0 = 1; return I2C_ERR; } else { if(!ACKD0) //not ACK { SPT0 = 1; return I2C_ERR; } else { IICIF0 = 0; return I2C_CRR; } } }
/******************************************************* ********************Send data**************************** *******************************************************/ bool SysI2C_SendDat(UCHAR configDat) { bool I2CSTATE; I2CSendByte(configDat); /*Send data*/ I2CSTATE = SysI2CWaitAck(); return I2CSTATE; }
/******************************************************* **************I2C(TWI)I2C(TWI)receive data **************** *******************************************************/ bool SysI2C_RcvDat(UCHAR *pRdDat) { I2CWaitDelay = 100; //Wait 1S while((!IICIF0) && (I2CWaitDelay>0)) { NOP(); }
if(I2CWaitDelay<=0) { SPT0 = 1; return I2C_ERR; } else { IICIF0 = 0; *pRdDat = IIC0; return I2C_CRR; } }
/******************************************************* **********************读N个数据************************** **** wrDAdr: write device-address 器件地址?? **** wordAdr: word address 读数据的寄存器地址?? **** pRdDat: p->read data 存放数据的指针 **** num: number 读数据的个数
*******************************************************/ bool SysI2C_Read(UCHAR wrDAdr,UCHAR wordAdr,UCHAR *pRdDat,USHORT num) { UCHAR rdDAdr; USHORT i=0; rdDAdr = wrDAdr+1; //读器器件地址为写地址加1
if(SysI2CCheckBusy()==I2C_ERR) {return I2C_ERR;} if(SysI2C_Start()==I2C_ERR) /*启动I2C*/ {return I2C_ERR;} if(SysI2C_SendDat(wrDAdr)==I2C_ERR)/*发写器件地址*/ {return I2C_ERR;} if(SysI2C_SendDat(wordAdr)==I2C_ERR)/*发要读的寄存器地址*/ {return I2C_ERR;} if(SysI2C_Start()==I2C_ERR)/*重启I2C*/ {return I2C_ERR;} if(SysI2C_SendDat(rdDAdr)==I2C_ERR)/*发读器器件地址*/ {return I2C_ERR;}
if(TRC0 == 0) //读 { I2CRcvAck(); while(i<num-1) { I2CCanWait(); if(SysI2C_RcvDat(pRdDat+i)) {i++;} else {return I2C_ERR;} } I2CRcvNoAck(); I2CCanWait(); i=num-1; if(SysI2C_RcvDat(pRdDat+i)) { I2CRcvAck(); if(SysI2C_Stop()) { _delay_us(10); return I2C_CRR; } else {return I2C_ERR;} } else {return I2C_ERR;} } else {return I2C_ERR;} }
/******************************************************* **********************写N个数据************************** **** wrDAdr: write device-address 器件地址?? **** wordAdr: word address 写数据的寄存器地址?? **** pRdDat: p->read data 写数据的指针 **** num: number 写数据的个数 *******************************************************/ bool SysI2C_Write(UCHAR wrDAdr,UCHAR wordAdr,UCHAR *pWrDat,UCHAR num) { unsigned char i=0;
if(SysI2CCheckBusy()==I2C_ERR) {return I2C_ERR;} if(SysI2C_Start()==I2C_ERR) /*启动I2C*/ {return I2C_ERR;} if(SysI2C_SendDat(wrDAdr)==I2C_ERR)/*发写器件地址*/ {return I2C_ERR;} if(SysI2C_SendDat(wordAdr)==I2C_ERR)/*发要写的寄存器地址*/ {return I2C_ERR;} if(TRC0 == 1) //写 { while(i<num) { if(SysI2C_SendDat(*(pWrDat+i))) {i++;} else {return I2C_ERR;} } if(SysI2C_Stop()) { _delay_us(10); return I2C_CRR; } else { return I2C_ERR; } } else {return I2C_ERR;} } |