单片机关于I2C的ack问题

uchar I2C_SendByte(uchar dat, uchar ack)函数其中与ack相关的部分是

while(I2C_SDA && (ack == 1))//等待应答,也就是等待从设备把I2C_SDA拉低
{
b++;
if(b > 200) ** //如果超过200us没有应答发送失败,或者为非应答,表示接收结束
**{
I2C_SCL = 0;
I2C_Delay10us();
return 0;
}
}

I2C_SCL = 0;
I2C_Delay10us();

在main中有
I2C_SendByte(0xa0, 1);//发送写器件地址
I2C_SendByte(addr, 1);//发送要写入内存地址
I2C_SendByte(dat, 0)_; //发送数据

为什么发送数据时 ack为0了不为1,以及这个ack代表什么意义,ack不是从机将sda下拉的信号吗?

7个回答

while(I2C_SDA && (ack == 1)) 这里的含义是 根据传入的 ack 来决定是否需要 应答, I2C_SendByte(dat, 0)_; 传入的 参数是 0 , 就是不需要对方给应答 , 前面2条 指令需要对方应答 。

主机和从机是相对的,如果这里是单片机和E2PROM通信的话,MCU就是主机,E2PROM就从机。
ACK就应答的意思,/* while(I2C_SDA && (ack == 1))*/ 的意思就是等待数据线为高,即单片机把一个字节的数据发完了,再把数据线拉低,然后等待E2PROM把数据线拉高,如果拉高了就是从机(E2PROM)有应答,如果等待时间到了后没有拉高就是从机(E2PROM)无应答。
出现无应答的情况就是I2C总线出错或者从机(E2PROM)正在忙碌状态。

你说的是否是发送数据开始的时序电平,建议用示波器抓波形分析,除了开始和结束时序外,8位一应答。

这里是 ack 是传入的 参数, 属于 变量 , 不是 硬件 ack , 我也是很努力的在指导你哦, 希望采纳我的答案 。

1.从写入器件地址到写入内存地址再到最后写入数据,从程序上看这是一个同步IO操作,及你的I2C_SendByte()是一个同步IO操作函数,
前面MCU与外挂E2PROM进行的只是外挂E2PROM的寄存器操作(表明器件地址与内存地址),外挂E2PROM执行时间很快,所以代码作者
是可以也有必要确认ACK的,但是到了最后进行的外挂E2PROM写操作,是涉及到E2PROM擦除和写入的,一般NVM的擦除时间都比较长,
MCU一直在这里等待外挂E2PROM擦写数据是不明智的,所以作者可以选择做好的擦写数据不确认ACK,直接跳过。
题者可以考虑去了解下嵌入式相关异步IO,就明白了。【以上属于个人愚见,请参考】

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
i2c 调试OLED之无ACK
最近在tiny4412上调试一款oled,此oled具有SPI 和I2c两种接口,可以供选择。 SPI接口的很快调试好了。但是I2c接口的却调试了很久没有调试出来。 通过逻辑分析仪抓波形,发现是oled不回复ack信号,导致所有的初始化命名都没有发送出去。 但是为什么没ACK信号呢? 按淘宝店家提供的资料,硬件上已经确认无误。 无奈用公司的小开发去试试,也是用的硬件i2c,竟然可以点...
关于单片机STM32 I2C E2PROM问题
现在遇到一个问题是:我保存的数据从1到3000,数据有3000个,每保存一个数据需要一个地址,也需要3000个地址,rn而I2C_Send7bitAddress和I2C_SendData都是8位,最大不能超过256个地址和256个数据,现在本人有3000个数据,怎样保存超过256个地址和256个数据,希望大家提供编程程序以及算法,最好编程有注释,也详细越好,谢谢大家帮忙!!rn
单片机I2C通信程序
I2C软件模拟时序,独立文件,可以直接调用,移植性高,只需修改数据时钟线
单片机的I2C的仿真实验
本实验能够仿真I2C的演示,本实验你可以体会到I2C的仿真演示。
430单片机I2C程序
基于430开发的有关I2c协议的代码程序
单片机 I2C 总线
单片机 I2C 总线 单片机 I2C 总线
单片机课件 I2C
单片机I2C东流电子单片机\单片机课件\8第八课--I2C.
430 单片机 I2C 程序
430学习资料 详细介绍了430单片机的i2c协议的实现方法和注意要点。
avr单片机i2c读写
用单片机进行i2c总线的读写 用单片机进行i2c总线的读写 用单片机进行i2c总线的读写
通用 单片机 I2C 程序
通用 单片机 I2C 程序,以ADV7172为例,适当修改可做其他用
单片机模拟i2c总线
单片机模拟i2c总线 单片机模拟i2c总线 单片机模拟i2c总线 V 单片机模拟i2c总线单片机模拟i2c总线
STC单片机I2C程序
STC单片机利用IO模拟I2C程序,晶振22.1184M。
I2C程序(单片机模拟)
I2C程序,小程序!!!!!!!!!!!!!!!!!!!!
单片机 模拟i2c协议
模拟iic协议的头文件测试可用的. 测试单片机为 stc89c52rc mpu6050 通讯
羚羊单片机I2C传输
用Spce061A I/O 模拟I2C时序,进行串行数据传输,并完成了与一般Rom的数据交换。
单片机课件 I2C串行总线
单片机课件_第1课--绪论.ppt │ 单片机课件_第2课--C51.ppt │ 单片机课件_第3课--IO口.ppt │ 单片机课件_第3课--LED.ppt │ 单片机课件_第4棵--KEY.ppt │ 单片机课件_第5课--ASM.ppt │ 单片机课件_第6课--Interrupt.ppt │ 单片机课件_第6课--定时器.ppt │ 单片机课件_第7课--串口.ppt │ 单片机课件_第8课--I2C串行总线.ppt
单片机模拟I2C总线
用51单片机来模拟i2c总线 有程序和实例 免费的资料到哪里去找
【单片机】I2C通信原理
I2C(Inter-Integrated Circuit) 步骤:(主机->从机) 1. 发送slave address字节 + ack(在此寻址,省去片选) 2. 发送command + ack(0x01为读;0x02为写) 3. 发送address + ack(读写data的address) 4. 发送data + ack(传输数据)写:
iic i2c 简单单片机
iic i2c readme 简单单片机 端口 labview
单片机 I2C总线
I2C总线是Inter-IntegratedCircuit(集成电路总线),这种总线类型是由飞利浦半导体公司在八十年代初设计出来的,主要是用来连接整体电路(ICS) ,IIC是一种多向控制总线,也就是说多个芯片可以连接到同一总线结构下,同时每个芯片都可以作为实时数据传输的控制源。 ...
单片机I2C教学课件
单片机I2C,HR版,控制与实现,液晶显示器始终的制作等等,看看有益,高手绕道
单片机I2c模拟程序
用8051单片机的I/O口实现I2C传输。
单片机与I2C的编程
这是单片机与I2C通信的一段程序,已经编译通过的了,完全是可以下载下来看的了!大家下载下来看看吧,应该对你们有用的!
带I2C接口的单片机
单片机作为I2C总线主控制器资料. I2C 总线的基本概念和功能包括主控器被控器数据传送地址设置传送格式以及被控器地址的使用
关于延时ACK的思考
在网络上很容易搜到关于延时ACK相关的信息以及触发条件,一般网上有一种说法是神秘的40ms的延时ACK反馈机制,但是在一般网上所说的都是在单独的一来一回的情景下展开的,很少有文章会讲关于客户端多个报文发送的条件下,除了40ms的延时返回外,是否还有什么机制触发延时ACK。...
关于I2C的问题。
tmErrorCode_t UserWrittenI2CWrite (tmUnitSelect_t tUnit,UInt32 AddrSize, UInt8* pAddr,rnUInt32 WriteLen, UInt8* pData)rnrn /* Variable declarations */rn tmErrorCode_t err = TM_OK;rnrn/* Customer code here */rn/* ...*/rnrn/* ...*/rn/* End of Customer code here */rnrn return err;rnrnrn这个函数的5个形参谁能帮忙解释下,没有开发文档,只有个函数声明。[img=https://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/003/onion/3.gif][/img]
关于i2c驱动的问题
在linux2.6.28内核中的include/linux/i2c.h中有这样的一个结构体:struct i2c_client_address_data rn const unsigned short *normal_i2c;rn const unsigned short *probe;rn const unsigned short *ignore;rn const unsigned short * const *forces;rn;rnrn可是在内核2.6.38中没有了?问下38中是怎样处理i2c操作的?用什么来代替这个结构体了?
关于I2C通信协议的问题...
以下是部分模拟I2C接口的代码rn用于单片机与外部EEP通信进行读写rn现在有一些疑问 望解答rn1.什么是发送一上位数据?作用或功能是什么?rn2.入口参数sla各指向哪里?rn3.sla是否指外存储器的地址?(选择外存储器) 还是外存储器ROM内的地址?(数据存放区的首地址)rn4.如果sla不是外部ROM首地址,读写函数中的*p都指向了CPU内部RAM的地址,怎样控制片外ROM的存储地址?rnrnrnrnrn//==============================================================rnvoid I2C_WRBYT(uchar idata *p) //写一字节数据rnrnuchar idata n=8;rnuchar idata temp;rntemp=*p;rnwhile(n--)rnrnif((temp&0x80)==0x80)rnrnVSDA=1;rnVSCL=1;rnDLY5USrnVSDA=0;rnVSCL=0;rnrnelsernrnVSDA=0;rnVSCL=1;rnDLY5USrnVSCL=0;rnrntemp=temp<<1;rnrnrn//=============================================================rnvoid I2C_RDBYT(uchar idata *p) //读一字节数据rnrnuchar idata n=8;rnuchar idata temp=0;rnwhile(n--)rnrnVSDA=1;rnVSCL=1;rntemp=temp<<1;rnif(VSDA==1)rntemp=temp|0x01;rnelserntemp=temp&0xfe;rnVSCL=0;rnrn*p=temp;rnrn//======================================================================rnint I2C_WRNBYT(uchar *sla,uchar n) //写数据rnrnuchar idata *p;rnI2C_START(); rnI2C_WRBYT(sla); //发送一上位数据rnI2C_CACK(); //检查应答rnif(F0==1)rnrnNACK=1;rnreturn 0;rnrn//p=MTD;rnp=buffer_recv;rnwhile(n--)rnrnI2C_WRBYT(p);rnI2C_CACK();rnif(F0==1)rnrnNACK=1;rnreturn 0;rnrnp++;rnrnI2C_STOP();rnreturn 1;rnrn//======================================================================rnvoid I2C_RDNBYT(uchar idata *sla,uchar n) //读数据 rnrnuchar idata *p;rnI2C_START();rnI2C_WRBYT(sla);rnI2C_CACK();rnif(F0==1)rnrnNACK=1;rnreturn;rnrn//p=MRD;rnp=buffer_send;rnwhile(n--)rnrnI2C_RDBYT(p);rnI2C_MACK();rnp++;rnrnI2C_MNACK();rnI2C_STOP();rn
关于i2c的驱动问题
同志们,i2c设备的地址是平台决定的,还是芯片自己决定的?我要移植个ov5648camera的驱动,前后用的都是ov5648(芯片一样,但不是同一个camera)。现在问题是单独装前或后都可以用,如果两个都装,就只能识别一个。两个用的i2c地址都是0x36,该如何修改呢?小弟积分不多,希望好心人解答小弟疑问。
关于i2c总线的问题
写入数据0x0f, 第一次读出为0x0f,以后都读出为0xff。。。。写入其他数据也一样,只有第一次读取了正确数据。。。rn请问这是为什么???rn
关于I2C总线的问题
void SendByte(unsigned char c)rnrn unsigned char BitCnt;rn rn for(BitCnt=0;BitCnt<8;BitCnt++) /*要传送的数据长度为8位*/rn rn if((c<
89和12单片机的I2C通信时序问题
今天用ADC偶然发现了这个问题,分享给各位朋友。 89的I2CDelay:#define I2CDelay() {_nop_();_nop_();_nop_();_nop_();}12的I2CDelay:void Delay_us(unsigned char us) { do { _nop_(); _nop_(); _nop_();
关于STM32系列单片机I2C通信的问题,求教各位大牛
最近再做一个关于STM32F103系列单片机I2C通信的项目,因为以前没有玩过单片机所以有一些东西实在搞不懂,也没人可以咨询,所以来求教各位大牛了rn先贴我的第一个问题:下面是一个简单的I2C写数据以及读数据的函数[code=c]void I2C_WriteByte(unsigned char write_address,unsigned char byte)rnrn I2C_GenerateSTART(I2C2,ENABLE);rn //产生起始条件rn while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));rn //等待ACKrn I2C_Send7bitAddress(I2C2,EEPROM_ADDR,I2C_Direction_Transmitter);rn //向设备发送设备地址rn while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));rn //等待ACKrn I2C_SendData(I2C2, write_address);rn //寄存器地址rn while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));rn //等待ACKrn I2C_SendData(I2C2, byte);rn //发送数据rn while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));rn //发送完成rn I2C_GenerateSTOP(I2C2, ENABLE);rn //产生结束信号rn[/code]rn[code=c]void I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)//将EEPROM的数据读入缓冲器rn rnrn I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件rn while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));//检查最近一次 I2C事件是否是输入的事件rnrn /* In the case of a single data transfer disable ACK before reading the data */rn if(NumByteToRead==1) rn rn I2C_AcknowledgeConfig(I2C1, DISABLE);//使能或者失能指定 I2C的应答功能rn rn I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);//向指定的从 I2C设备传送地址字,选择发送方向rn while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//检查最近一次 I2C事件是否是输入的事件rn I2C_Cmd(I2C1, ENABLE);//使能或者失能 I2C外设rn I2C_SendData(I2C1, ReadAddr); //通过外设 I2Cx发送读取地址()rn while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));//检查最近一次 I2C事件是否是输入的事件rn I2C_GenerateSTART(I2C1, ENABLE);//产生 I2Cx传输 START条件rn while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));//检查最近一次 I2C事件是否是输入的事件rn I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver);//向指定的从 I2C设备传送地址字,选择接收方向rn while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//检查最近一次 I2C事件是否是输入的事件rn /* While there is data to be read */rn while(NumByteToRead) rn rn /* Test on EV7 and clear it */rn if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) //检查最近一次 I2C事件是否是输入的事件rn rn if(NumByteToRead == 2)rn rn I2C_AcknowledgeConfig(I2C1, DISABLE);//使能或者失能指定 I2C的应答功能rn rn if(NumByteToRead == 1)rn rn I2C_GenerateSTOP(I2C1, ENABLE);//产生 I2Cx传输 STOP条件rn rn *pBuffer = I2C_ReceiveData(I2C1);//返回通过 I2Cx最近接收的数据rn pBuffer++; rn NumByteToRead--; rn rn rn /* Enable Acknowledgement to be ready for another reception */rn I2C_AcknowledgeConfig(I2C1, ENABLE);//使能或者失能指定 I2C的应答功能rnrn[/code]rn我查资料说STM32和器件通信有以下步骤:rn写:检测SDA是否空闲;rn->按I2C协议发出起始讯号;rn->发出7位器件地址和写模式;rn->要写入的存储区首地址;rn->用页写入方式或字节写入方式写入数据;rn rn读:检测SDA是否空闲;rn->按I2C协议发出起始讯号;rn->发出7位器件地址和写模式(伪写);rn->发出要读取的存储区首地址;rn->重发起始讯号;rn->发出7位器件地址和读模式;rn->接收数据;rn无论读和写在发送完要写入或者读取的器件地址后都要再发送一个要写入或者读取的存储区地址,我的疑问是,这个地址读和写分别如何确定的呢?rn还有一个疑问是:STM32有I2C1和I2C2两个I2C,如果我想做一下自回环,即I2C1给I2C2发送一个数据,I2C2收到后在传给I2C1一个数据,其中I2C1做主设备,I2C2做从设备,那么I2C1给I2C2发数据的时候器件地址是什么呢,I2C2给I2C1回数据的时候器件地址又是什么呢rn东西有点多,跪求大神给解答!谢谢了
关于I2C
I2C第一个字节里面只有7个是地址,一个器件的地址不是8位吗,那寻址时不是少了一位。
单片机模拟I2C总线通信
单片机模拟I2C总线通信,虚拟i2c的程序
基于PROTEUS的I2C 单片机源程序
用PROTEUS仿真,AT89C51控制的的I2C 单片机源程序
单片机I2C读写24c02指导
单片机 2引脚 模拟I2C发送接收数据,详细代码
pic32单片机i2c通讯ads1014
pic32单片机通过dynamic,i2c读写ads1014寄存器
STM32F0系列单片机I2C驱动程序
STM32F0系列单片机模拟I2C驱动程序,已封装好接口,配置引脚后可直接使用
pic 单片机的I2C 接口代码
带 proteus 电路的 pic单片机的I2C接口驱动程序,详细例子代码
相关热词 c# stream 复制 android c# c#监测窗口句柄 c# md5 引用 c# 判断tabtip 自己写个浏览器程序c# c# 字符串变成整数数组 c#语言编程写出一个方法 c# 转盘抽奖 c#选中treeview