您的位置 首页 汽车

MCS-51单片机模仿I2C软件包

注意:普通M51单片机机器周期=12个时钟周期,f020机器周期=时钟周期对于nop指令,F020是一个时钟周期,例如f020晶振为22.1184M,约为45ns/…

留意:一般M51单片机机器周期=12个时钟周期,f020机器周期=时钟周期

关于nop指令,F020是一个时钟周期,例如f020晶振为22.1184M, 约为45ns

/*函数是选用软件延时的办法发生SCL脉冲,固对高晶振频率要作 必定的修正….(本软件包是1us机器周期,即晶振频率要小于12MHZ)总线时序契合I2C规范形式,100Kbit/S。*/

#include
#include

#define uchar unsigned char /*宏界说*/
#define uint unsigned int

#define _Nop() _nop_() /*界说空指令1us*/

sbit SDA=P3^4; /*模仿I2C数据传送位*/
sbit SCL=P3^5; /*模仿I2C时钟操控位*/

bit ack; /*应对标志位*/

/*******************************************************************
起动总线函数
函数原型: void Start_I2c();
功用: 发动I2C总线,即发送I2C开端条件.
********************************************************************/
void Start_I2c()
{
SDA=1; /*发送开端条件的数据信号*/
_Nop();
SCL=1;
_Nop(); /*开端条件树立时刻大于4.7us,延时*/
_Nop();
_Nop();
_Nop();
_Nop();
SDA=0; /*发送开端信号*/
_Nop(); /* 开端条件确定时刻大于4μs*/
_Nop();
_Nop();
_Nop();
_Nop();
SCL=0; /*钳住I2C总线,预备发送或接纳数据 */
_Nop();
_Nop();
}

/*******************************************************************
完毕总线函数
函数原型: void Stop_I2c();
功用: 完毕I2C总线,即发送I2C完毕条件.
********************************************************************/
void Stop_I2c()
{
SDA=0; /*发送完毕条件的数据信号*/
_Nop(); /*发送完毕条件的时钟信号*/
SCL=1; /*完毕条件树立时刻大于4μs*/
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
SDA=1; /*发送I2C总线完毕信号*/
_Nop();
_Nop();
_Nop();
_Nop();
}

/*******************************************************************
字节数据发送函数
函数原型: void SendByte(uchar c);
功用: 将数据c发送出去,可所以地址,也可所以数据,发完后等候应对,并对
此状况位进行操作.(不应对或非应对都使ack=0)
发送数据正常,ack=1; ack=0表明被控器无应对或损坏。
********************************************************************/
void SendByte(uchar c)
{
uchar BitCnt;

for(BitCnt=0;BitCnt<8;BitCnt++) /*要传送的数据长度为8位*/
{
if((c< else SDA=0;
_Nop();
SCL=1; /*置时钟线为高,告诉被控器开端接纳数据位*/
_Nop();
_Nop(); /*确保时钟高电平周期大于4μs*/
_Nop();
_Nop();
_Nop();
SCL=0;
}

_Nop();
_Nop();
SDA=1; /*8位发送完后开释数据线,预备接纳应对位*/
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop();
_Nop();
if(SDA==1)ack=0;
else ack=1; /*判别是否接纳到应对信号*/
SCL=0;
_Nop();
_Nop();
}

/*******************************************************************
字节数据接纳函数
函数原型: uchar RcvByte();
功用: 用来接纳从器材传来的数据,并判别总线过错(不发应对信号),
发完后请用应对函数应对从机。
********************************************************************/
uchar RcvByte()
{
uchar retc;
uchar BitCnt;

retc=0;
SDA=1; /*置数据线为输入方法*/
for(BitCnt=0;BitCnt<8;BitCnt++)
{
_Nop();
SCL=0; /*置时钟线为低,预备接纳数据位*/
_Nop();
_Nop(); /*时钟低电平周期大于4.7μs*/
_Nop();
_Nop();
_Nop();
SCL=1; /*置时钟线为高使数据线上数据有用*/
_Nop();
_Nop();
retc=retc<<1;
if(SDA==1)retc=retc+1; /*读数据位,接纳的数据位放入retc中 */
_Nop();
_Nop();
}
SCL=0;
_Nop();
_Nop();
return(retc);
}

/********************************************************************
应对子函数
函数原型: void Ack_I2c(bit a);
功用: 主控器进行应对信号(可所以应对或非应对信号,由位参数a决议)
********************************************************************/
void Ack_I2c(bit a)
{

if(a==0)SDA=0; /*在此宣布应对或非应对信号 */
else SDA=1;
_Nop();
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop(); /*时钟低电平周期大于4μs*/
_Nop();
_Nop();
_Nop();
SCL=0; /*清时钟线,钳住I2C总线以便持续接纳*/
_Nop();
_Nop();
}

/*******************************************************************
用户接口函数
*******************************************************************/

/*******************************************************************
向无子地址器材发送字节数据函数
函数原型: bit ISendByte(uchar sla,ucahr c);
功用: 从发动总线到发送地址,数据,完毕总线的全过程,从器材地址sla.
假如回来1表明操作成功,不然操作有误。
留意: 运用前有必要已完毕总线。
********************************************************************/
bit ISendByte(uchar sla,uchar c)
{
Start_I2c(); /*发动总线*/
SendByte(sla); /*发送器材地址*/
if(ack==0)return(0);
SendByte(c); /*发送数据*/
if(ack==0)return(0);
Stop_I2c(); /*完毕总线*/
return(1);
}

/*******************************************************************
向有子地址器材发送多字节数据函数
函数原型: bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);
功用: 从发动总线到发送地址,子地址,数据,完毕总线的全过程,从器材
地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
假如回来1表明操作成功,不然操作有误。
留意: 运用前有必要已完毕总线。
********************************************************************/
bit ISendStr(uchar sla,uchar suba,uchar *s,uchar no)
{
uchar i;

Start_I2c(); /*发动总线*/
SendByte(sla); /*发送器材地址*/
if(ack==0)return(0);
SendByte(suba); /*发送器材子地址*/
if(ack==0)return(0);

for(i=0;i {
SendByte(*s); /*发送数据*/
if(ack==0)return(0);
s++;
}
Stop_I2c(); /*完毕总线*/
return(1);
}

/*******************************************************************
向无子地址器材发送多字节数据函数
函数原型: bit ISendStr(uchar sla,ucahr *s,uchar no);
功用: 从发动总线到发送地址,子地址,数据,完毕总线的全过程,从器材
地址sla,发送内容是s指向的内容,发送no个字节。
假如回来1表明操作成功,不然操作有误。
留意: 运用前有必要已完毕总线。
********************************************************************/
bit ISendStrExt(uchar sla,uchar *s,uchar no)
{
uchar i;

Start_I2c(); /*发动总线*/
SendByte(sla); /*发送器材地址*/
if(ack==0)return(0);

for(i=0;i {
SendByte(*s); /*发送数据*/
if(ack==0)return(0);
s++;
}
Stop_I2c(); /*完毕总线*/
return(1);
}

/*******************************************************************
向无子地址器材读字节数据函数
函数原型: bit IRcvByte(uchar sla,ucahr *c);
功用: 从发动总线到发送地址,读数据,完毕总线的全过程,从器材地
址sla,回来值在c.
假如回来1表明操作成功,不然操作有误。
留意: 运用前有必要已完毕总线。
********************************************************************/
bit IRcvByte(uchar sla,uchar *c)
{
Start_I2c(); /*发动总线*/
SendByte(sla+1); /*发送器材地址*/
if(ack==0)return(0);
*c=RcvByte(); /*读取数据*/
Ack_I2c(1); /*发送非就答位*/
Stop_I2c(); /*完毕总线*/
return(1);
}

/*******************************************************************
向有子地址器材读取多字节数据函数
函数原型: bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);
功用: 从发动总线到发送地址,子地址,读数据,完毕总线的全过程,从器材
地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
假如回来1表明操作成功,不然操作有误。
留意: 运用前有必要已完毕总线。
********************************************************************/
bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no)
{
uchar i;

Start_I2c(); /*发动总线*/
SendByte(sla); /*发送器材地址*/
if(ack==0)return(0);
SendByte(suba); /*发送器材子地址*/
if(ack==0)return(0);

Start_I2c(); /*重新发动总线*/
SendByte(sla+1);
if(ack==0)return(0);
for(i=0;i {
*s=RcvByte(); /*发送数据*/
Ack_I2c(0); /*发送就答位*/
s++;
}
*s=RcvByte();
Ack_I2c(1); /*发送非应位*/
Stop_I2c(); /*完毕总线*/
return(1);
}

/*******************************************************************
向无子地址器材读取多字节数据函数
函数原型: bit ISendStrExt(uchar sla,ucahr *s,uchar no);
功用: 从发动总线到发送地址,读数据,完毕总线的全过程.
从器材地址sla,读出的内容放入s指向的存储区,
读no个字节。假如回来1表明操作成功,不然操作有误。
留意: 运用前有必要已完毕总线。
********************************************************************/
bit IRcvStrExt(uchar sla,uchar *s,uchar no)
{
uchar i;

Start_I2c();
SendByte(sla+1);
if(ack==0)return(0);

for(i=0;i {
*s=RcvByte(); /*发送数据*/
Ack_I2c(0); /*发送就答位*/
s++;
}
*s=RcvByte();
Ack_I2c(1); /*发送非应位*/
Stop_I2c(); /*完毕总线*/
return(1);
}

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qiche/276742.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部