📄 iic.c
字号:
/*
* I2C D-òé
* ′|àí?÷ààDí£oC51
* °?±?£o1 è??ú£o2006-12-13
*
* °?±?£o2 è??ú£o2006-12-28
* ê1ó?°?±?2Dè?¨ò?I2C_V2
* ?ü??£o?°I2CWriteBunch?±·?·¨·??a?°dat?±2?êy?aêy?Yμ??·?°datAdd?±oí?°dat?±£?è¥3yá?2?êyautoStop
*
* ×÷??£o??μ?í?<yangdewang@gmail.com>
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. Or, point your browser to
* http://www.gnu.org/copyleft/gpl.html
*/
#include <intrins.h>
#include <global.h>
#include "iic.h"
#include "delay.h"
//#define DEBUG_IIC
#define clSCL() (SCL_I2C = false)
#define setSCL() (SCL_I2C = true)
#define clSDA() (SDA_I2C = false)
#define setSDA() (SDA_I2C = true)
/*
void clSCL() {SCL_I2C = false;}
void setSCL() {SCL_I2C = true;}
void clSDA() {SDA_I2C = false;}
void setSDA() {SDA_I2C = true;}*/
#if (IIC_WAITCYCLE>0)
bool waitSCL(uint8 c)//μè′y?y?ùéè±?,c?a0μè′yê±??×?3¤
{
do
{
if(SCL_I2C == 1)return true;
}
while(--c);
return false;//μè′y3?ê±
}
#else
#define waitSCL(x) SCL_I2C
#endif
bool waitAnswer()//μè′y?ìó|//·μ??oóSCL_I2C=1,SDA_I2C=1
{
clSCL();//T.hd,dat?ó3ù5us//êy?Y±£3?ê±??//±ê×?IIC?a0us
//Delay(0);
setSDA();
setSCL();
if(waitSCL(IIC_WAITCYCLE))
{
if(SDA_I2C == 0)
return true;
}
return false;
}
bool sendAnswer()
{
clSDA();
setSCL();
if(!waitSCL(IIC_WAITCYCLE))
return false;//μè′y3?ê±
clSCL();
setSDA();
return true;
}
static bool write(uint8 add)//D′ò???×??úμ?×ü??//ê§°üoóSCL_I2C=1,SDA_I2C=1//3é1|SCL_I2C=1,SDA_I2C?′?¨
{ //è?1?ê§°ü??·¢?íí£?1?ò??D??aê?D?o?£?μ?ò2??????ê§è¥?ù2?μ??é??
bool sdav;
uint8 i=8;
do
{
clSCL();//T.hd,dat?ó3ù5us//êy?Y±£3?ê±??//±ê×?IIC?a0us
#if 0
ACC = add;
#pragma asm
//_RLC_();
RLC A
#pragma endasm
add = ACC;
#else
add=(add<<1);//×¢òa£oê1ó?á?Cì???é???μ?′ú????è·±£?éò?ì???
#endif
SDA_I2C = CY;//T.su,dat?ó3ù250ns//êy?Y?¨á¢ê±??
sdav= CY;
setSCL();//T.hgih?ó3ù4us SCL_I2Cê±?óμ???μ????ü?ú
if(!waitSCL(IIC_WAITCYCLE))
goto er;//μè′y3?ê±
#ifdef IIC_MULTI_MATER
if(SDA_I2C != sdav)
{
goto er;//ê§è¥?ù2?
}
#endif
}while(--i);
//SCL_I2C is 1
return true;
er:
//setSDA();
return false;
}
bool read(uint8* dat)//?áò???×??ú′ó×ü??//ê§°üoóSCL_I2C=1,SDA_I2C=1//3é1|SCL_I2C=0,SDA_I2C=1
{
uint8 datm = 0;
uint8 i=8;
clSCL();//T.hd,dat?ó3ù5us//êy?Y±£3?ê±??//±ê×?IIC?a0us
do
{
setSCL();
if(!waitSCL(IIC_WAITCYCLE))
goto er;//μè′y3?ê±
#if 0
CY = SDA_I2C;//T.hgih?ó3ù4us SCL_I2Cê±?óμ???μ????ü?ú
ACC = datm;
#pragma asm
//_RLC_();
RLC A
#pragma endasm
datm= ACC;
#else
datm=datm<<1;
if(SDA_I2C)datm++;
#endif
clSCL();//T.hd,dat?ó3ù5us//êy?Y±£3?ê±??//±ê×?IIC?a0us
}while(--i);
*dat = datm;
return true;
er:
return false;
}
void IICStop() //·¢?íí£?1D?o?
{
clSCL();
clSDA();
setSCL();
waitSCL(IIC_WAITCYCLE);//í£?1ì??tμ??¨á¢ê±???ó3ù 4.7us
#if (_CPU_INSTRUCTION_CLOCK_)>(1000000/5)
_delay_us(5);
#endif
setSDA();
}
//?°?·′ó?ú add μ??·/r_w?á/D′:true=read//·μ??oóSCL_I2C=1,SDA_I2C=1
bool I2CStart(uint8 add,bool r_w)
{
#ifdef IIC_MULTI_MATER
//todo:2é?ˉ×ü?????D
#endif
setSDA();
setSCL();//Start Setup Time 4.7us
#if (_CPU_INSTRUCTION_CLOCK_)>(1000000/5)
_delay_us(5);
#endif
clSDA();
#if 0
CY = r_w;
ACC = add;
#pragma asm
//_RLC_();
RLC A
#pragma endasm
add = ACC;
#else
add=add<<1;
if(r_w)add++;
#endif
// Delay(0);//?ó3ù
/*if(!write(add))
{
setSDA();
setSCL();
return false;
}*/
return write(add)&&waitAnswer();
}
#ifdef I2C_V2
/***************************************************
D′ò???×??ú′?μ????¨éè±?
add: éè±?μ??·
datAdd: êy?Yμ??·
dat: êy?Yê××??ú????
count: ′?3¤?è
autoStop:=true???ú3é1|?áê?oó2úéúí£?1D?o?
return: 3é1|D′è?×??úêy
*****************************************************/
uint8 I2CWriteBunch(uint8 add,uint8 datAdd,uint8* dat,uint8 count)
{
uint8 i=0;
if(I2CStart(add,0))
{
write(datAdd);
if(!waitAnswer())goto end;
for(;i<count;i++)
if(!write(dat[i])||!waitAnswer())
goto end;
}
end:
IICStop();
return i;
}
/***************************************************
?áò???×??ú′?′óéè±?
devAdd: éè±?μ??·
datAdd: êy?Yμ??·
dat: êy?Yê××??ú????
count: ′?3¤?è
return: 3é1|?áè?×??úêy
*****************************************************/
uint8 I2CReadBunch(uint8 devAdd,uint8 datAdd,uint8* dat,uint8 count)
{
if(I2CStart(devAdd,0))
{
write(datAdd);
if(!waitAnswer())return 0;
clSCL();//?áê?′ó?úμ??ìó|D?o?
return I2CReadStream(devAdd,dat,count);
}
return 0;
#if 0
uint8 i = 0;
if(I2CStart(devAdd,0))
{
write(datAdd);
if(!waitAnswer())goto re;
clSCL();//?áê?′ó?úμ??ìó|D?o?
if(I2CStart(devAdd,1))
{
while(i<count-1)
{
if(!read(dat)||!sendAnswer())
{
goto re;
}
dat++;
i++;
}
if(read(dat))i++;
}
}
re: setSCL();//2??ìó|D?o?
waitSCL(IIC_WAITCYCLE);
//Delay(0);
IICStop(); //·¢?íí£?1D?o?
return i;
#endif
}
/***************************************************
?áò???×??ú′?′óéè±?
′?·?·¨????2?ó?ìá1?êy?Yμ??·μ?éè±??òá?D??áè?
devAdd: éè±?μ??·
dat: êy?Yê××??ú????
count: ′?3¤?è
return: 3é1|?áè?×??úêy
*****************************************************/
uint8 I2CReadStream(uint8 devAdd,uint8* dat,uint8 count)
{
uint8 i;
if(count==0)
return 0;
i= count-1;
if(I2CStart(devAdd,1))
{
while(i)
{
if(!read(dat)||!sendAnswer())
{
goto re;
}
dat++;
i--;
}
if(!read(dat))i++;
}
re: setSCL();//2??ìó|D?o?
waitSCL(IIC_WAITCYCLE);
//Delay(0);
IICStop(); //·¢?íí£?1D?o?
return count-i;
}
#else//I2C_V2
uint8 I2CWriteBunch(uint8 add,uint8* dat,uint8 count,bool autoStop)//D′ò???×??ú′?μ????¨éè±? 1:éè±?μ??· 2:êy?Yê××??ú???? 3£o′?3¤?è autoStop=true:???ú3é1|?áê?oó2úéúí£?1D?o? re£o3é1|D′è?×??úêy
{
uint8 i=0;
if(I2CStart(add,0))
{
for(;i<count;i++)
{
if(!write(dat[i]))
goto end;
if(!waitAnswer())
goto end;
}
}
else
{
goto rt;
}
end:
if(autoStop)
IICStop();
rt:
return i;
}
#ifdef I2C_WRITEBYTE_U
bool I2CWriteByte(uint8 add,uint8 dat)//D′ò???×??úμ????¨éè±?
{
return I2CWriteBunch(add,&dat,1,true); //todo
}
#endif//I2C_WRITEBYTE_U
uint8 I2CReadBunch(uint8 devAdd,uint8 datAdd,uint8* dat,uint8 count)//?áò???×??ú′?′óéè±?divAdd:éè±?μ??· datAdd:êy?Yê××??úμ??· dat:êy?Yê××??ú???? count£o′?3¤?è re£o3é1|?áè?×??úêy
{
uint8 i = 0;
if(I2CWriteBunch(devAdd,&datAdd,1,false))
{
clSCL();//?áê?′ó?úμ??ìó|D?o?
if(I2CStart(devAdd,1))
{
while(i<count-1)
{
if(!read(dat)||!sendAnswer())
{
goto re;
}
dat++;
i++;
}
if(read(dat))i++;
}
}
re: setSCL();//2??ìó|D?o?
waitSCL(IIC_WAITCYCLE);
//Delay(0);
IICStop(); //·¢?íí£?1D?o?
return i;
}
#endif//I2C_V2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -