共2条
1/1 1 跳转至页
问
那位大侠能给小弟细讲一下I2C总线呀,
看了半天还是有点迷茫,谢谢! 答 1: 把协议好好读几遍,比在这里问更有效果。有具体的点不明白时,才拿上来问。 答 2: 谢谢协议已经读料好几遍了,但是对于SDA,SCL线的作用还是有点迷茫,在传送一个8位字节前和传送后他们的变化,不好意思,第一次用,谢谢了computer00,在给讲一下吧 答 3: SDA就是数据线,SCL就是时钟线。空闲时两个都为高。
在数据正常发送过程中,只有当SCL为低时才能改变状态。
如果SCL为高时,SDA改变状态,就会产生启始或停止条件。
具体是:如果SCL为高,SDA由高到低,则产生启始条件(或者是重复启始条件)。
如果SCL为高,SDA由低到高,则产生停止条件。
数据必须在启始条件后发送,第一个字节为设备地址。
这些在协议里面都写得很清楚,自己去看吧,晕菜~~~~~~~~~ 答 4: 多读几遍 答 5: 多谢/*****************************************uchar RcvB()*****************************************
该函数是字节数据传送函数,功能是用来接收从器件传来的数据,并判断总线错误(不发应答信号),发完后
调用应答函数
***********************************************************************************************/
uchar RcvB()
{
uchar retc;
uchar BitCnt;
retc=0;
Sda_I2C=1; /*置数据线为输入方式*/
for(BitCnt=0;BitCnt<8;BitCnt++)
{
_NOP();
Scl_I2C=0; /*置时钟线为低准备接受数据位*/
_NOP(); /*时钟低电平周期*/
_NOP();
_NOP();
_NOP();
_NOP();
Scl_I2C=1; /*置时钟线为高使数据线上数据有效*/
_NOP();
_NOP();
retc=retc<<1;
if(Sda_I2C==1) retc=retc+1; /*读数据位,接收到数据位放入retc中*/
_NOP();
_NOP();
}
Scl_I2C=0;
_NOP();
_NOP();
return(retc);
}
这是MCU从从器件中读书据的函数,帮忙分析一下,
尤其是
Scl_I2C=1;/*置时钟线为高使数据线上数据有效*/
难道非要SCL为高MCU才能读到数据吗?
if(Sda_I2C==1) retc=retc+1;难道从器件每发送一个BIT都要把SDA置高吗?
答 6: 协议里面不是写得好清楚吗???“6.1 数据的有效性
SDA 线上的数据必须在时钟的高电平周期保持稳定数据线的高或低电平状态只有在SCL 线的时钟
信号是低电平时才能改变见图4)。”
if(Sda_I2C==1) retc=retc+1;难道从器件每发送一个BIT都要把SDA置高吗?
这句话的意思是,如果Sda_I2C为高(即Sda_I2C等于1),那么retc就加1,加1就相当于把最后一位置1。
这样就表示收到了一个1,并把它放在retc的最低位。如果Sda_I2C不等于1,即收到一个0,retc就
不加1,也就是最低位为0,表示收到一个0。如果还需要接收其它的位,则将retc往左移动一位
(即上面那句retc=retc<<1;或者写成retc<<=1;),然后又跟上面的过程一样,把接下来收到的一位放到最后。 答 7: 非常感谢非常感谢computer00,有机会请你吃饭:) 答 8: 只要把时序看明白了,按照时序写就OK了 答 9: 谢谢。
那位大侠能给小弟细讲一下I2C总线呀,
看了半天还是有点迷茫,谢谢! 答 1: 把协议好好读几遍,比在这里问更有效果。有具体的点不明白时,才拿上来问。 答 2: 谢谢协议已经读料好几遍了,但是对于SDA,SCL线的作用还是有点迷茫,在传送一个8位字节前和传送后他们的变化,不好意思,第一次用,谢谢了computer00,在给讲一下吧 答 3: SDA就是数据线,SCL就是时钟线。空闲时两个都为高。
在数据正常发送过程中,只有当SCL为低时才能改变状态。
如果SCL为高时,SDA改变状态,就会产生启始或停止条件。
具体是:如果SCL为高,SDA由高到低,则产生启始条件(或者是重复启始条件)。
如果SCL为高,SDA由低到高,则产生停止条件。
数据必须在启始条件后发送,第一个字节为设备地址。
这些在协议里面都写得很清楚,自己去看吧,晕菜~~~~~~~~~ 答 4: 多读几遍 答 5: 多谢/*****************************************uchar RcvB()*****************************************
该函数是字节数据传送函数,功能是用来接收从器件传来的数据,并判断总线错误(不发应答信号),发完后
调用应答函数
***********************************************************************************************/
uchar RcvB()
{
uchar retc;
uchar BitCnt;
retc=0;
Sda_I2C=1; /*置数据线为输入方式*/
for(BitCnt=0;BitCnt<8;BitCnt++)
{
_NOP();
Scl_I2C=0; /*置时钟线为低准备接受数据位*/
_NOP(); /*时钟低电平周期*/
_NOP();
_NOP();
_NOP();
_NOP();
Scl_I2C=1; /*置时钟线为高使数据线上数据有效*/
_NOP();
_NOP();
retc=retc<<1;
if(Sda_I2C==1) retc=retc+1; /*读数据位,接收到数据位放入retc中*/
_NOP();
_NOP();
}
Scl_I2C=0;
_NOP();
_NOP();
return(retc);
}
这是MCU从从器件中读书据的函数,帮忙分析一下,
尤其是
Scl_I2C=1;/*置时钟线为高使数据线上数据有效*/
难道非要SCL为高MCU才能读到数据吗?
if(Sda_I2C==1) retc=retc+1;难道从器件每发送一个BIT都要把SDA置高吗?
答 6: 协议里面不是写得好清楚吗???“6.1 数据的有效性
SDA 线上的数据必须在时钟的高电平周期保持稳定数据线的高或低电平状态只有在SCL 线的时钟
信号是低电平时才能改变见图4)。”
if(Sda_I2C==1) retc=retc+1;难道从器件每发送一个BIT都要把SDA置高吗?
这句话的意思是,如果Sda_I2C为高(即Sda_I2C等于1),那么retc就加1,加1就相当于把最后一位置1。
这样就表示收到了一个1,并把它放在retc的最低位。如果Sda_I2C不等于1,即收到一个0,retc就
不加1,也就是最低位为0,表示收到一个0。如果还需要接收其它的位,则将retc往左移动一位
(即上面那句retc=retc<<1;或者写成retc<<=1;),然后又跟上面的过程一样,把接下来收到的一位放到最后。 答 7: 非常感谢非常感谢computer00,有机会请你吃饭:) 答 8: 只要把时序看明白了,按照时序写就OK了 答 9: 谢谢。
共2条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
【换取逻辑分析仪】自制底板并驱动ArduinoNanoRP2040ConnectLCD扩展板被打赏47分 | |
【分享评测,赢取加热台】RISC-V GCC 内嵌汇编使用被打赏38分 | |
【换取逻辑分析仪】-基于ADI单片机MAX78000的简易MP3音乐播放器被打赏48分 | |
我想要一部加热台+树莓派PICO驱动AHT10被打赏38分 | |
【换取逻辑分析仪】-硬件SPI驱动OLED屏幕被打赏36分 | |
换逻辑分析仪+上下拉与多路选择器被打赏29分 | |
Let'sdo第3期任务合集被打赏50分 | |
换逻辑分析仪+Verilog三态门被打赏27分 | |
换逻辑分析仪+Verilog多输出门被打赏24分 | |
【分享评测,赢取加热台】使用8051单片机驱动WS2812被打赏40分 |