📄 i2c.c
字号:
/*
//*************************************************************************
//
// P H I L I P S P R O P R I E T A R Y
//
// COPYRIGHT (c) 1999 BY PHILIPS SINGAPORE.
// -- ALL RIGHTS RESERVED --
//
// File Name: I2C.C
// Author: Xia Huiyuan
// Created: 25 Jan.2002
// Modified:
// Revision: 0.0.
//
//*************************************************************************
//
//*************************************************************************
*/
#include <intrins.h>
#include "standard.h"
#include "Kernel.h"
#include "I2C.h"
//***********************************************************************
//* *
//* Global Variable Definition *
//* *
//***********************************************************************
UC idata I2CDev_UniqueAddr;
UC idata I2C_SubAddr;
I2C_FLAG I2C_Flag;
//***********************************************************************
//* *
//* External Variable Definition *
//* *
//***********************************************************************
extern UC idata Endpt_FIFO[64];
/*
//*************************************************************************
// Main Funcs
//*************************************************************************
*/
// Since we try to use C++ programming style for this part,
// a set of bit flags were defined to instead of the function's parameters.
// This will hepls to reduce the code size.
bit Hal4I2C_Write(UC Length)
{
UC i;
UC Data;
if(I2C_Flag.BITS.WRITESTARTING)
{
I2C_SCL =1;
I2C_SDA =1;
Hal4Sys_Wait4US();
//Setup time for a prepeated START condition. 4.7us for standard-mode/600ns for Fast-mode.
//Since 24Mhz cystal is selected, the cycle for one single word instraction is 500ns.
//At frist stage, we set the the delay as 4us, late it will be modified to mee the FS spec.
Hal4I2Csup_StartCond(); //Start
if(Hal4I2Csup_Send(I2CDev_UniqueAddr)) //Send Sub-adress 7bit+1bit(r/w)
return(I2C_ERROR);
if(Hal4I2Csup_Send(I2C_SubAddr)) //Send Sub-adress 7bit+1bit(r/w)
return(I2C_ERROR);
}
if(I2C_Flag.BITS.DATAPHASE)
{
for(i=0; i<Length; i++)
{
Data=Endpt_FIFO[i];
if ( Hal4I2Csup_Send(Data) )
return(I2C_ERROR);
}
}
if(I2C_Flag.BITS.WRITEENDING)
{
Hal4I2Csup_StopCond(); //Stop condition
return(I2C_OK);
}
return(I2C_OK);
}
bit Hal4I2C_Read(UC Length)
{
UC OrderOfArray;
if(I2C_Flag.BITS.READSTARTING)
{
I2C_SCL =1;
I2C_SDA =1;
Hal4Sys_Wait4US();
//Setup time for a prepeated START condition. 4.7us for standard-mode/600ns for Fast-mode.
//Since 24Mhz cystal is selected, the cycle for one single word instraction is 500ns.
//At frist stage, we set the the delay as 4us, late it will be modified to mee the FS spec.
Hal4I2Csup_StartCond(); //Start
if(Hal4I2Csup_Send(I2CDev_UniqueAddr)) //Send Sub-adress 7bit+1bit(r/w)
return(I2C_ERROR);
if(Hal4I2Csup_Send(I2C_SubAddr)) //Send Sub-adress 7bit+1bit(r/w)
return(I2C_ERROR);
//Repeat start (Sr)
if(Hal4I2Csup_SCLHigh()) //Set I2C_SCL = 1 and wait HIGH period of the SCL.
return(I2C_ERROR) ;
Hal4Sys_Wait4US();
Hal4I2Csup_StartCond();
Hal4I2Csup_Send(I2CDev_UniqueAddr+1); // Read address
}
if(I2C_Flag.BITS.DATAPHASE)
{
//Bytes transfer from first byte to length-1 byte.
for (OrderOfArray=0; OrderOfArray < (Length-1); OrderOfArray++)
{
if(Hal4I2Csup_Receive(OrderOfArray,0)) return(I2C_ERROR);
}
//These are two cases to receive Last byte.
//Case 1: If ACKASSERT=1; transfer will be terminated by Master(non ack).
//Case 2: If ACKASSERT=0; last byte will be transfered with ACK.
if(I2C_Flag.BITS.ACKASSERT)
{
//Since the ACK should be asserted by Master
//after receiving a last byte data.
if(Hal4I2Csup_Receive(OrderOfArray,1)) return(I2C_ERROR);
}
else
{
//Since the ACK should be asserted by SLAVE
//after receiving a byte data except last byte.
if(Hal4I2Csup_Receive(OrderOfArray,0)) return(I2C_ERROR);
}
}
if(I2C_Flag.BITS.READENDING)
{
Hal4I2Csup_StopCond();
return(I2C_OK);
}
return(I2C_OK);
}
/* ------------------------------------------------------------------------- */
/* Supporting functions */
/* ------------------------------------------------------------------------- */
bit Hal4I2Csup_SCLHigh(void)//Set SCL to high and keep at lease 4us or 0.6 us.
{
int c0;
I2C_SCL = 1;
for (c0=8*3500; c0!=0; c0--)
{
if (I2C_SCL)
{
Hal4Sys_Wait4US(); //High period of the SCL clock, 4.0/0.6us
return(I2C_OK);
}
};
return(I2C_ERROR);
}
void Hal4I2Csup_StartCond(void)
{
I2C_SDA = 0 ;//fall time must be less than 300ns.
Hal4Sys_Wait4US();
//Hold time, START condition. 4.0us for ST-mode/0.6 for FS-mode.
I2C_SCL = 0 ;
Hal4Sys_Wait4US();//LOW period of the SCL clock.
}
void Hal4I2Csup_StopCond(void)
{
I2C_SDA = 0;
Hal4Sys_Wait1US();//Setup-time.
I2C_SCL = 1;
Hal4Sys_Wait4US(); //Setup-time before I2C_SDA rasing. 4.0us st-mode/0.6us fs-mode
I2C_SDA = 1 ;
Hal4Sys_Wait4US();//Bus-free time between a STOP and START condition. 4.7us st-mode/1.3 fs-mode.
}
bit Hal4I2Csup_Send(UC SendData)
{
UC c0;
UC Data;
c0 = 0x80;
Data = SendData;
do
{
if (Data & c0) //SendData & 0x80
I2C_SDA = 1 ;
else
I2C_SDA = 0 ;
Hal4Sys_Wait1US(); //data set-up time, 250ns for ST-mode, 100ns for FS-mode.
c0 >>= 1 ;
if(Hal4I2Csup_SCLHigh()) //Set I2C_SCL = 1 and wait HIGH period of the SCL.
return(I2C_ERROR) ;
I2C_SCL = 0 ;
Hal4Sys_Wait4US();//hold-time 5.0us st/0 fs
}while (c0);
// Check Ack
I2C_SDA = 1 ; // Gave up SDA and I2C slave device will drives the bit to low.
Hal4Sys_Wait4US();//Hold time, START condition. 4.0us for ST-mode/0.6 for FS-mode.
if(Hal4I2Csup_SCLHigh()) //Set I2C_SCL = 1 and wait HIGH period of the SCL.
return(I2C_ERROR);
if ( I2C_SDA==0 ) //I2C_SDA = 0. Slave device issued an acknowledge.
{
I2C_SCL=0;
Hal4Sys_Wait4US();//hold-time 5.0us st/0 fs
return(I2C_OK);
};
return(I2C_ERROR);
}
//Master's receiver is requested to issue an ACK=1 to terminated the transfer,
//This is a signals to slave's transmitter to terminated the transfer.
bit Hal4I2Csup_Receive(UC count, UC Terminator)
{
UC c0;
UC c1;
I2C_SDA = 1; // Give up SDA
Hal4Sys_Wait1US();
c0 = 0x80;
c1 = 0;
do
{
if(Hal4I2Csup_SCLHigh())
return(I2C_ERROR);
if (I2C_SDA==1)
c1 = c1|c0 ;
I2C_SCL = 0 ;
Hal4Sys_Wait4US();
c0 >>= 1;
}while(c0);
if (Terminator)
I2C_SDA =1;
else
I2C_SDA =0;
if(Hal4I2Csup_SCLHigh())
return(I2C_ERROR);
Endpt_FIFO[count] = c1;
I2C_SCL = 0;
return(I2C_OK);
}
void Hal4Sys_Wait4US(void)
{
// @24MHz
#ifdef WORK_AT_FS_MODE
_nop_();
#endif
#ifdef WORK_AT_ST_MODE
_nop_();
_nop_();
_nop_(); //time = MACHINECYCLE_AT24MHZ*NumberOfInstruction;
_nop_();
_nop_();
_nop_();
_nop_(); //time = MACHINECYCLE_AT24MHZ*NumberOfInstruction;
_nop_();
#endif
}
void Hal4Sys_Wait1US(void)
{
// @24MHz
_nop_(); //time = MACHINECYCLE_AT24MHZ*NumberOfInstruction;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -