📄 i2c.c
字号:
{
uchar retc;
uchar BitCnt;
retc=0;
SDA=1; /*置数据线为输入方式*/
for(BitCnt=0;BitCnt<8;BitCnt++)
{
SCL=0; /*置时钟线为低,准备接收数据位*/
_nop_();
_nop_();
_nop_(); /*时钟低电平周期大于4.7μs*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL=1; /*置时钟线为高使数据线上数据有效*/
while(SCL!=1); /*07-22-03*/
_nop_();
_nop_();
retc=retc<<1;
if(SDA==1)retc=retc+1; /*读数据位,接收的数据位放入retc中 */
_nop_();
_nop_();
}
SCL=0;
_nop_();
_nop_();
return(retc);
}
/**********************下面为从机MCU使用子函数***********************
从机单字节接收函数
函数原型: uchar SRcvByte(uchar no);
功能:从器件接收传来的数据,no代表位数,接收寻址字节no=9,接收数据字节no=8位。
返回:返回接收到的字节
********************************************************************/
uchar SRcvByte(uchar no)
{
uchar retc;
uchar Bitcnt;
retc=0;
SDA=1; /*置数据线为输入方式*/
for(Bitcnt=0;Bitcnt<no;Bitcnt++)
{
while(SCL!=0); /*等待时钟线为低*/
while(SCL!=1); /*等待时钟线为高时接收数据信号*/
retc=retc<<1;
if(SDA==1) retc=retc+1;
}
return(retc);
}
/*******************************************************************
从机单字节发送函数
函数原型: void SSendByte(uchar c);
功能:从器件发送单字节数据,c代表要发送的数据。
********************************************************************/
void SSendByte(uchar c)
{
uchar Bitcnt;
for(Bitcnt=0;Bitcnt<8;Bitcnt++)
{
while(SCL!=0); /*等待直到SCL为0*/
if((c<<Bitcnt)&0x80) SDA=1;
else SDA=0;
while(SCL!=1); /*等待SCL为1*/
}
while(SCL!=0);
SDA=1; /*释放数据线*/
while(SCL!=1); /*等待SCL为1*/
if(SDA==1) ack=0; /*非应答*/
else ack=1; /*应答*/
}
/********************************************************************
从机发应答信号
函数原型: void SSendAck(bit a);
功能:从器件发应答信号,a=0发应答,a=1发非应答。
********************************************************************/
void SSendAck(bit a)
{
while(SCL!=0); /*SCL不为零则循环等待*/
if(a==0) SDA=0; /*应答*/
else SDA=1;
while(SCL!=1); /*等待SCL为1*/
while(SCL!=0);
SDA=1; /*释放数据线*/
}
/*********************下面是向用户提供的接口函数**********************
向有字地址器件发送多字节数据函数(主发送)
函数原型:bit ISendStr(uchar sla,uchar subah,uchar subal,uchar *s,uchar num) ;
功能:从竞争仲裁到启动总线,发送地址,字地址,数据,结束总线的全过程。从器件
地址sla,字地址高字节subah,字地址低字节subal,发送内容是s指向的内容,发送num个字节。
返回:如果返回OK表示操作成功,否则操作有误。
********************************************************************/
bit ISendStr(uchar sla,uchar subah,uchar subal,uchar *s,uchar num)
{
uchar i;
if(Get_I2C()!=OK) goto out;/*没竞争到总线,返回失败标志*/
Start_I2C(); /*竞争到总线,发动起始信号*/
if(SendByte(sla)!=OK) goto out; /*发送器件地址,正确继续发送,错误跳出*/
if(SendByte(subah)!=OK) goto out; /*发送器件高字地址*/
if(SendByte(subal)!=OK) goto out; /*发送器件低字地址*/
for(i=0;i<num;i++) /*发送num个字节数据*/
{
if(SendByte(*s)!=OK) goto out;/*发送数据,正确继续发送,错误跳出*/
s++;
}
Stop_I2C(); /*结束总线*/
BUSY=1;
IE1=0; /*清中断标志,清除自己拉低总线时产生的中断标志*/
EX1=1; /*使用完总线开中断*/
return(OK);
out:Stop_I2C(); /*结束总线*/
BUSY=1;
IE1=0; /*清中断标志*/
EX1=1; /*使用完总线开中断*/
return(NOK); /*返回失败标志*/
}
/*******************************************************************
向有子地址器件读取多字节数据函数(主接收)
函数原型:bit IRcvStr(uchar sla,uchar subah,uchar subal,uchar *s,uchar num);
功能:从竞争仲裁到启动总线,发送地址,子地址,读数据,结束总线的全过程,从器件
地址sla,字地址高字节subah,字地址低字节subal,读出的内容放入s指向的存储区,读num个字节。
返回:如果返回OK表示操作成功,否则操作有误。
********************************************************************/
bit IRcvStr(uchar sla,uchar subah,uchar subal,uchar *s,uchar num)
{
uchar i;
if(Get_I2C()!=OK) goto out1; /*没竞争到总线,返回失败标志跳出*/
Start_I2C(); /*竞争到总线,发动起始信号*/
if(SendByte(sla)!=OK) goto out1; /*发送器件地址*/
if(SendByte(subah)!=OK) goto out1; /*发送器件高字地址*/
if(SendByte(subal)!=OK) goto out1; /*发送器件低字地址*/
Start_I2C();
if(SendByte(sla+1)!=OK) goto out1; /*发送器件地址读操作*/
for(i=0;i<num-1;i++) /*接收num个字节数据,放入s指针所指的地方*/
{
*s=RcvByte();
Ack_I2C(0); /*发应答位*/
s++;
}
*s=RcvByte();
Ack_I2C(1); /*发非应答位*/
Stop_I2C(); /*结束总线*/
BUSY=1;
IE1=0; /*清中断标志*/
EX1=1; /*使用完总线开中断*/
return(OK); /*返回成功*/
out1:Stop_I2C(); /*结束总线*/
BUSY=1;
IE1=0; /*清中断标志*/
EX1=1; /*使用完总线开中断*/
return(NOK); /*返回失败*/
}
/*******************************************************************
向无子地址器件包括MCU发送多字节数据函数(主发送)
函数原型:bit M_SendStr(uchar sla,uchar *s,uchar num)
功能:从竞争仲裁到启动总线,发送地址,数据,结束总线的全过程。从器件地址sla.
返回:如果返回OK表示操作成功,否则操作有误。
********************************************************************/
bit M_SendStr(uchar sla,uchar *s,uchar num)
{
uchar i;
if(Get_I2C()!=OK) goto out2;/*没竞争到总线,返回失败标志*/
Start_I2C(); /*竞争到总线,发动起始信号*/
if(SendByte(sla)!=OK) goto out2; /*发送器件地址,正确继续发送,错误跳出*/
for(i=0;i<num;i++) /*发送num个字节数据*/
{
if(SendByte(*s)!=OK) goto out2;/*发送数据,正确继续发送,错误跳出*/
s++;
}
Stop_I2C(); /*结束总线*/
BUSY=1;
IE1=0; /*清中断标志*/
EX1=1; /*使用完总线开中断*/
return(OK);
out2:Stop_I2C(); /*结束总线*/
BUSY=1;
IE1=0; /*清中断标志*/
EX1=1; /*使用完总线开中断*/
return(NOK); /*返回失败标志*/
}
/*******************************************************************
MCU作从器件接收多字节数据函数(从接收)
函数原型:bit S_RcvStr(uchar *s,uchar num)
功能:接收寻址,数据,发应答。该函数在中断程序中调用。
返回:如果返回OK表示操作成功,否则操作有误。
********************************************************************/
bit S_RcvStr(uchar *s,uchar num)
{
uchar i;
uchar address;
address=SRcvByte(8);
if(MYADR==address) /*判断第一个寻址字节,以决定是中断退出,还是进行从接受*/
{
SSendAck(0); /*从机MCU发应答*/
for(i=0;i<num;i++)
{
*s=SRcvByte(8);
s++;
SSendAck(0); /*从机MCU发应答*/
}
return(OK); /*成功返回OK*/
}
return(NOK);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -