历史上的今天
返回首页

历史上的今天

今天是:2025年05月20日(星期二)

正在发生

2018年05月20日 | I2C模拟程序----汇编语言格式

2018-05-20 来源:eefocus

模块名:I2C总线驱动    型号:I2C


功能描述:

此模块包括发送数据及接收数据,应答位发送,并提供了几个直接面对器件的操作函数,能很
方便的与用户程序进行连接并扩展。
    需要注意的是,函数是采用延时方法产生 SCL 脉冲,对高晶振频率要做一定的修改!!
    在写E2PROM的时候一定要延时!!!
    
说明:

1us机器周期,晶振频率要小于12MHz
返回 1 则操作成功,返回 0 则操作失败。
sla 为器件从地址,suba 为器件子地址。

*************************************************************************************/

#include "AT89X52.h"
#include

#define   _Nop() _nop_()    //定义空指令

sbit   SDA = P1^3;     //模拟I2C数据传输位
sbit   SCL = P1^2;     //模拟I2C时钟控制位

bit   bdata I2C_Ack;    //应答标志位

 

/************************************ I2C_Start ************************************

函数名:void I2C_Start()
入口:
出口:

功能描述:启动I2C总线,即发送I2C初始条件
调用函数: 
全局变量:

创建者:陈曦    日期:2005-6-15
修改者:           日期:

**********************************************************************************/

void I2C_Start()
{
SDA = 1;      //发送起始条件的数据信号
_Nop();
SCL = 1;
_Nop();       //起始条件建立时间大于4.7us,延时
_Nop();
_Nop();
_Nop();
_Nop();
SDA = 0;      //发送起始信号
_Nop();       //起始条件建立时间大于4us,延时
_Nop();
_Nop();
_Nop();
_Nop();
SCL = 0;      //钳住I2C总线准备发送或接收数据
_Nop();
_Nop();
}


/************************************ I2C_Stop ************************************

函数名:void I2C_Stop()
入口:
出口:

功能描述:结束I2C总线,即发送I2C结束条件
调用函数: 
全局变量:

创建者:陈曦   日期:2005-6-15
修改者:    日期:

**********************************************************************************/


void I2C_Stop()
{
SDA = 0;      //发送结束条件的数据信号
_Nop();
SCL = 1;      //发送结束条件的时钟信号
_Nop();       //结束条件建立时间大于4us,延时
_Nop();
_Nop();
_Nop();
_Nop();
SDA = 1;      //发送I2C总线结束信号
_Nop();
_Nop();
_Nop();
_Nop();
}

/************************************ I2C_CheckAck ************************************

函数名:bit I2C_CheckAck(void)
入口:
出口:0(无应答),1(有应答)

功能描述:
检验I2C总线应答信号,有应答则返回1,否则返回0,超时值取255

调用函数:void I2C_Stop()
全局变量:

创建者:陈曦   日期:2005-6-15
修改者:          日期:

**********************************************************************************/

bit I2C_CheckAck(void)
{
uchar errtime = 255;     // 因故障接收方无 Ack,超时值为255
SDA = 1;
_Nop();
_Nop();
_Nop();
SCL = 1;
_Nop();         //时钟电平周期大于 4 us
_Nop();
_Nop();
_Nop();
_Nop();
while(SDA)
{
   errtime--;
   if(errtime==0)
   {
    I2C_Stop();
    return(0);
   }
}
SCL = 0;
_Nop();
return(1);
}

/************************************ I2C_SendB ************************************

函数名:void I2C_SendB(uchar c)
入口:uchar 型数据
出口:

功能描述:
字节数据传送函数,将数据 c 发送出去,可以是地址,也可以是数据,发完后等待应答,并对
此状态位进行操作

调用函数:bit I2C_CheckAck()
全局变量:I2C_Ack

创建者:陈曦   日期:2005-6-15
修改者:          日期:

**********************************************************************************/

void I2C_SendB(uchar c)
{
uchar BitCnt;

for (BitCnt=0; BitCnt<8; BitCnt++)   //要传送的数据长度为8位
{
   if((c<   {
    SDA = 1;
   }
   else
   {
    SDA = 0;
   }

   _Nop();
   _Nop();
   SCL = 1;        //置时钟线为高通知被控器开始接收数据位
   _Nop();         //保证时钟高电平周期大于 4us
   _Nop();
   _Nop();
   _Nop();
   _Nop();
   SCL = 0;
}

_Nop();
_Nop();

I2C_Ack = I2C_CheckAck();     //检验应答信号
_Nop();
_Nop();
}


/************************************ I2C_RcvB ************************************

函数名:uchar I2C_RcvB()
入口:
出口:uchar型数据

功能描述:
接收从器件传来的数据,并判断总线错误(不发应答信号),收完后需要调用应答函数。

调用函数:
全局变量:

创建者:陈曦   日期:2005-6-15
修改者:          日期:

**********************************************************************************/

uchar I2C_RcvB()
{
uchar retc;
uchar BitCnt;         //位

retc = 0;
SDA = 1;          //置数据总线为输入方式
for(BitCnt=0;BitCnt<8;BitCnt++)
{
   _Nop();
   SCL = 0;         //置时钟线为低准备接收数据位
   _Nop();          //时钟低电平周期大于4.7us
   _Nop();
   _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);
}

/************************************ I2C_Ackn ************************************

函数名:void I2C_Ackn(bit a)
入口:0或1
出口:

功能描述:主控制器进行应答信号(可以是应答或非应答信号)
调用函数:
全局变量:

创建者:陈曦   日期:2005-6-15
修改者:          日期:

**********************************************************************************/


void I2C_Ackn(bit a)
{
if(a==0)      //在此发送应答或非应答信号
{
   SDA = 0;
}
else
{
   SDA = 1;
}
_Nop();
_Nop();
_Nop();
SCL = 1;
_Nop();       //时钟电平周期大于 4 us
_Nop();
_Nop();
_Nop();
_Nop();
SCL = 0;      //清时钟线钳住I2C总线以便继续接收
_Nop();
_Nop();
}

/******************************** I2C_ISendB ************************************

函数名:bit I2C_ISendB(uchar sla, uchar suba, uchar c)
入口:从器件地址 sla,子地址 suba, 发送字节 c
出口:0(操作有误),1(操作成功)

功能描述:从启动总线到发送地址、数据,结束总线的全过程,
     如果返回1,表示操作成功,否则操作有误。

调用函数:I2C_Start(),I2C_SendB(uchar c),I2C_Stop()
全局变量:I2C_Ack

创建者:陈曦   日期:2005-6-15
修改者:           日期:

**********************************************************************************/

bit I2C_ISendB(uchar sla, uchar suba, uchar c)
{
I2C_Start();     //启动总线

I2C_SendB(sla);     //发送器件地址
if(!I2C_Ack)
{
   return(0);
}

I2C_SendB(suba);    //发送器件子地址
if(!I2C_Ack)
{
   return(0);
}

I2C_SendB(c);     //发送数据
if(!I2C_Ack)
{
   return(0);
}

I2C_Stop();      //结束总线
return(1);
}

/********************************** I2C_IRcvB ************************************

函数名:bit I2C_IRcvB(uchar sla, uchar suba, uchar *c)
入口:从器件地址 sla, 子地址 suba, 收到的数据在 c
出口:1(操作成功),0(操作有误)

功能描述:从启动总线到发送地址、读数据,结束总线的全过程。

调用函数: I2CS_tart(),
     I2C_SendB(uchar c),
     I2C_RcvB(),
     I2C_Ackn(bit a),
     I2C_Stop()

全局变量:I2C_Ack

创建者:陈曦   日期:2005-5-15
修改者:          日期:

**********************************************************************************/

bit I2C_IRcvB(uchar sla, uchar suba, uchar *c)
{
I2C_Start();      //启动总线

I2C_SendB(sla);
if(!I2C_Ack)
{
   return(0);
}

I2C_SendB(suba);     //发送器件子地址
if(!I2C_Ack)
{
   return(0);
}

I2C_Start();      //重复起始条件

I2C_SendB(sla+1);     //发送读操作的地址
if(!I2C_Ack)
{
   return(0);
}

*c = I2C_RcvB();     //读取数据
I2C_Ackn(1);      //发送非应答位
I2C_Stop();       //结束总线
return(1);
}


推荐阅读

史海拾趣

DATEL Inc公司的发展小趣事

进入21世纪,随着电子医疗的兴起,DATEL Inc.看到了新的发展机遇。公司开始研发适用于医疗领域的数据采集产品,如医用传感器、生命体征监测仪等。通过与医疗机构紧密合作,DATEL Inc.成功推出了一系列高性能、高可靠性的医疗数据采集产品,为医疗行业的数字化转型做出了重要贡献。

Greenwich Instruments Ltd公司的发展小趣事

面对日益激烈的市场竞争和不断变化的客户需求,Greenconn Corp积极推动智能制造转型。公司引进先进的生产设备和技术,优化生产流程和管理模式,提高生产效率和产品质量。同时,公司还加强与高校、科研机构的合作,共同研发智能制造关键技术,推动智能制造技术在连接器生产领域的应用。这些努力不仅提升了Greenconn Corp的竞争力,还为公司的可持续发展奠定了坚实基础。

AIC [Analog Intergrations Corporation]公司的发展小趣事

Greenconn Corp自创立之初便致力于连接器技术的研发与创新。在20世纪末,随着电子产品的普及和通讯技术的飞速发展,连接器作为电子设备间的桥梁,其重要性日益凸显。Greenconn Corp凭借其敏锐的市场洞察力和强大的研发实力,成功研发出了一系列高性能、高可靠性的连接器产品,迅速在汽车电子、通信设备等领域占据了一席之地。这些创新产品不仅满足了市场对连接器高质量、高效率的需求,还推动了整个电子行业的发展。

Frequency Management International公司的发展小趣事

Frequency Management International公司成立于1971年,自创立之初,FMI便专注于为通信市场提供快速交货和严格公差的石英晶体和晶体振荡器。在成立初期,公司凭借其高质量的产品和可靠的服务,逐渐在通信市场中站稳了脚跟。随着技术的不断进步和市场需求的日益增长,FMI不断扩大生产规模,提升产品质量,为公司的后续发展奠定了坚实的基础。

意华(CZT)公司的发展小趣事

为了提高产品质量,意华先后通过了ISO9001、ISO14001、IECQC080000等多项国际质量管理体系认证。这些认证不仅证明了公司的质量管理水平,也为客户提供了更可靠的产品保障。通过持续的质量改进和过程控制,意华的产品质量得到了显著提升,赢得了更多客户的认可。

功得(CONQUER)公司的发展小趣事

在市场竞争日益激烈的环境下,功得公司意识到仅仅依靠创新是不够的,还需要有高品质的产品来赢得客户的信任。因此,公司开始注重产品质量管理,建立了完善的质量控制体系。功得公司严格把控原材料采购、生产工艺和成品检验等环节,确保每一件产品都符合高标准的质量要求。这种对品质的执着追求,使得功得公司的产品在市场上赢得了良好的口碑,品牌知名度也逐渐提升。

问答坊 | AI 解惑

国赛常见IC芯片价格,资料!

本帖最后由 paulhyde 于 2014-9-15 09:24 编辑 国赛常见IC芯片价格,资料!在网上找了个905的IC,找了半天,楞是找不全!!价格方面,资料方面.........一个一个找,麻烦啊........:\'( 小弟突发奇想,我们是不是可以在这个论坛里建立个板块,主 ...…

查看全部问答>

基于Bootsplash嵌入式Linux启动画面定制

在基于linux的嵌入式仿真平台开发中,终端的美观和可定制是一个重要的问题。开机时滚动在屏幕上的字符串和单调的penguin图标,使嵌入式设备仍然脱离不了pc的痕迹,linux控制台上单调的“白纸黑字”型表现方式可谓大煞风景。改造linux控制台使之美观 ...…

查看全部问答>

有谁知道哪里能定制电机呢

有谁知道哪里能定制电机呢??需要BLDC,24V,3A电流,功率72W,额定转速8000~1WRPM,最大转矩0.07Nm。电机伸出轴长需要80mm。轴直径不小于5mm。带霍尔,1.5m导线。…

查看全部问答>

wince 6.0 比 5.0的优越之处

相信有高手已经在做wince6.0了,想请问下,它比5.0有啥明显的好处? 增加了啥功能?有没有增加D3DM驱动? 开发效率驱动调试方面有啥提高?…

查看全部问答>

KEIL汇编中单步调试中如何看一个ram的值(求救)

比如 data_led equ 60h .... loop: mov data_led,a inc a jmp loop ... 如何看data_led的变化?在那个窗口可以观察到? 是用那个memeny window吗 那个好像是看rom的窗口 不知道是不是 因为我用那个窗口试过,在0x60h单元中的值总是不会变 ...…

查看全部问答>

Symbol MC1000 win4.2系统 怎么发出Beep声

Symbol MC1000 win4.2系统 怎么发出Beep声。 我看了symbol的例子 CS_ScanSample2 老半天都看不懂他是怎么发声的。 请各位指点一下。…

查看全部问答>

请教ADS调试ARM的问题,不知道如何入门。。

如题。 正在学习ARM的开发,采用的是ARM920T的内核。为了进一步熟悉其架构,现想先进行一些简单的开发,比如用汇编调试一下MOV等指令,看看内部寄存器的变化情况,选用JTAG仿真器和AXD进行调试。这个应该算是最简单的入门吧? 现在的问题是,我用 ...…

查看全部问答>

万利的199的板子到哪儿买?直接找万利吗?

                                  …

查看全部问答>

听说stm32每一个芯片只有一个全球唯一的ID

                                 上次在研讨会上,ST公司的专家说的,有没有人知道怎么读出这个ID。…

查看全部问答>

coreislocked-up

具体情况为: 1、我的ICF文件如下: define symbol __ICFEDIT_intvec_start__ = 0x08000000; define symbol __ICFEDIT_region_ROM_start__ = 0x08000000 ; define symbol __ICFEDIT_region_ROM_end__   = 0x0807FFFF; def ...…

查看全部问答>