两个单片机之间进行模拟I2C通讯
有大侠做过两个单片机之间进行I2C通信的吗?一般单片机端当主机用两条数据线去模拟i2c当主机读取外围的从设备比较简单,但单片机端模拟从机与另外一个单片机模拟I2C当主机进行通信就没搞过了,有人这么做过吗,能否贴出单片机端模拟从机的I2C协议代码,研究一下 高速模拟有难度,不过低速度传送肯定是没有问题的。 额,还有模拟从机的么 ningming 发表于 2014-5-10 16:31高速模拟有难度,不过低速度传送肯定是没有问题的。
有用过吗,能否给点参考代码,比较急,所以也没时间去一点一点时序研究 只模拟过主机,没模拟过从机 没做过,你也别等了,呵呵,有等的时间,自己都把协议看了N遍了!你做一个贴出来也行啊 自己做吧,与其模拟IIC不如直接模拟串口了,这个见过ZLG早期的一款LED驱动芯片上模拟的从机IIC 模拟从机也是对着IIC写时序就行了,和主机没啥区别,但似乎基本没什么人实现这个。
模拟从机,重要的就是检测到SCL的变化,然后尽快把SCL拉低,等SDA数据准备好再放。这样SCL Strech可以保证时序正确。
从机拉低SCL的速度决定了初始SCL的最高波特率。 void SlaveI2C_Test(void)
{
start_scan(); //¼ì²âÆðʼÐźÅ
if(START_flag==1)
{
START_flag = 0; //¿ªÊ¼ÐźÅÇåÁã
I2C_rxadd(); //ÊÕÈ¡µØÖ·¼°ÃüÁî
//------------·´À¡½ÓÊÕÓ¦´ð------------
while(scl == 0);//µÈ´ý¸øÖ÷»ú×¼±¸½ÓÊÕÓ¦´ð
SDA_OUT();
SDA_Reset;
while(scl == 1){;}//µÈ´ýÖ÷»ú½ÓÊÕÓ¦´ðÍê³É
SDA_IN();
//------------------------------------
//------------------------------------
if(DEV_address == 0xa0 || DEV_address == 0xa1) //ÅжÏÊÇ·ñΪ±¾»úµØÖ·
{
m = 0; //³õʼ»¯m
if(R_W == 0) //Ö÷»úÏò±¾»úдÊý¾Ý
{
while(1)
{
I2C_Rec = I2C_rxbyte();
//------------·´À¡½ÓÊÕÓ¦´ð------------
while(scl == 0);//µÈ´ý¸øÖ÷»ú×¼±¸½ÓÊÕÓ¦´ð
SDA_OUT();
SDA_Reset;
while(scl == 1){;}//µÈ´ýÖ÷»ú½ÓÊÕÓ¦´ðÍê³É
SDA_IN();
//------------------------------------
//------------STOP Ðźżì²â-----------
m++;
/* while(scl == 0){;}//¼ì²âSTOP
if(scl==1)
{
while(sda==0){;}
while(sda==1)
{
GPIO_WriteBit(GPIOF, GPIO_Pin_6, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOF, GPIO_Pin_6)));
return;
}
}*/
//-------------------------------------
if(m == I2C_Rec)//³¤¶È×Ö·û
{
//STOP_flag = 1;
GPIO_WriteBit(GPIOF, GPIO_Pin_6, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOF, GPIO_Pin_6)));
return;
}
}
}
else if(R_W == 1) //Ö÷»úÏò±¾»ú¶ÁÊý¾Ý
{
while(1)
{
I2C_txbyte(I2C_Send);
m++;
//----------------½ÓÊÕÖ÷»úÓ¦´ð£¬´Ë¹¦ÄÜÖ÷»úÐèÒª¿ªÆôÏò´Ó»ú¶ÁÊý¾Ý³É¹¦ºó·¢Ë͵ÄÓ¦´ðÐźÅ----------------------------------
while(scl == 0){;}
while(scl == 1)
{
if(sda == 1)//½ÓÊÕµ½Ö÷»úÇëÇó¶ÁÊý¾ÝµÄ×îºóÒ»¸ö×Ö½ÚNACKʱ£¬Í£Ö¹·¢ËÍ
{
GPIO_WriteBit(GPIOF, GPIO_Pin_10, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOF, GPIO_Pin_10)));
return;
}
}
//--------------------------------------------------------------------------------
//----------------½ÓÊչ̶¨³¤¶È×Ö½ÚÊý¾ÝºóÇ¿ÐÐÍ˳ö·¢ËÍ
/*if(m == 20)
{
//STROBE = 1;
GPIO_WriteBit(GPIOF, GPIO_Pin_10, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOF, GPIO_Pin_10)));
return;
}*/
//--------------------------------------------------------------------------------------
}
}
}
}
} u8 I2C_rxbyte()
{
u8 i,j,k=0;
while(scl == 1); //µÈ´ýSCLÀµÍ
for(i = 0 ;i < 8 ;i++)
{
while( ! scl); //µÈ´ýSCLÓÉ0±äΪ1
if(sda == 1)
j = 1;
else
j = 0;
k=(k << 1) | j;
while(scl); //SCL¸ßµçƽʱµÈ´ý
}
return(k); //½«½ÓÊÕµ½µÄÊý¾Ý·µ»Ø
}
void I2C_rxadd()
{
u8 i,j,k=0;
while(scl == 1);//µÈ´ýÖ÷»úÀµÍSCL
for(i = 0 ;i < 8 ;i++)
{
while( ! scl);//SCL=0ʱ£¬Ò»Ö±µÈ´ý£¬SCL=1ʱ¶ÁÈ¡SDAÊý¾Ý£¬Ö÷»úSCLµÈÓÚ1±ØÐë±£³ÖÒ»¶¨µÄʱ¼ä³¤¶È£¬²ÅÄܱ£Ö¤¿É¿¿¶ÁÈ¡//µÈ´ýSCLÓÉ0±äΪ1
if(sda == 1)
j = 1;
else
j = 0;
k=(k << 1) | j; //½«ÊÕµ½µÄλ·ÅÈëKÖÐ
while(scl == 1);//SCL¸ßµçƽʱµÈ´ý SCL=0ʱ¸Ãλ¶ÁÈ¡Íê³É£¬×¼±¸¶ÁÈ¡ÏÂÒ»BIT
}
R_W=k&0x01; //Ö÷»úÊǶÁ»¹ÊÇд
//DEV_address= (k >> 1) & 0x7f; //Çó³öÇ°7λµÄÉ豸µØÖ·
DEV_address = k;
}
void I2C_txbyte(u8 dat_byte)
{
u8 i,temp;
temp = dat_byte;
//while(scl == 1);//SCLϽµÑØ¿ªÊ¼¶Á
//while(sda == 0); //µÈ´ýÖ÷»úÊÍ·ÅÊý¾Ý×ÜÏß
SDA_OUT();
for (i = 0 ;i < 8 ;i++) //´Ó×î¸ßλ¿ªÊ¼£¬ÒÀ´Î·¢ËÍ8λ
{
while(scl == 0);//µÈ´ýÖÃ1ºó¸øÖ÷»ú·¢ËÍÊý¾Ý
if(temp&0x80)
{
SDA_Set;
}
else
{
SDA_Reset;
}
temp = temp << 1;
//temp = temp << 1; //½«Òª·¢Ë͵ÄÊý×î¸ßλÒƵ½CYÖÐ
//sda = CY; //Êý¾ÝÏß·¢ËÍCYÖдæµÄλÊý¾Ý
//while(scl == 0);
//while(scl == 1);
while(scl == 1);//Ϊ1ʱµÈ´ýÖ÷»ú¶ÁÈ¡Êý¾Ý£¬Îª0ʱÖ÷»ú¶ÁÈ¡Íê³É¡£
//while(scl == 0); //
}
//sda = 1; //·¢ÍêÊÍ·ÅÊý¾Ý×ÜÏß
//SDA_Set;
SDA_IN();
} void start_scan()
{
u8 NN = 10;
if(START_flag == 0)
{
if(scl == 1)
{
while(sda == 1){;}//SDAϽµÑØΪSTARTÐźÅ
while(sda == 0)
{
START_flag = 1;
GPIO_WriteBit(GPIOF, GPIO_Pin_8, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOF, GPIO_Pin_8)));
return;
}
}
}
//START_flag = 1;
} 上面为测试成功的代码,供有需要的参考,花了一两天时间写后测试通过的 从机还是用带硬件I2c的好,不然从机什么也做不了,我用带硬件I2C的芯片做过 liguangqang 发表于 2014-5-17 16:06
从机还是用带硬件I2c的好,不然从机什么也做不了,我用带硬件I2C的芯片做过 ...
我这里是没有办法了,之前的老产品,要改造,现在缺少通信接口,只能这么干,属于变态的设计了 如做产品,做出来后生不如死。。。。。小心呀 liguangqang 发表于 2014-5-17 16:27
如做产品,做出来后生不如死。。。。。小心呀
利害关系都有跟总工说过,但硬要这么干,哎,悲剧,刚进新公司,又不好强硬说此方案不可行,说了,还怀疑个人能力 huhang 发表于 2014-5-17 21:10
利害关系都有跟总工说过,但硬要这么干,哎,悲剧,刚进新公司,又不好强硬说此方案不可行,说了,还怀疑 ...
不过我把其简化了,Start和Stop信号从机都不检测,现在在STM32上测试,还算靠谱,从机CPU也没有太多的运算要处理,所以勉强还可以用,主要是用在51上,而且51的单片机的外部中断还被占用了,也没办法利用中断去判断起始和结束跳变沿。哎,老产品还是单片机的,这才是悲剧所在,现在的新产品,谁还去用模拟的I2C做从机通信呀,随便找个CPU也是一大堆的串口,SPI接口啥的 不检测start 和stop 是不靠谱的,意味着没有握手标记,帧格式有不确定性。如自定义通信格式,两线通信办法还是有多的方法。可参考单总线协议来做成半双工的(DS18B20)。 本帖最后由 bs1234 于 2014-5-24 21:28 编辑
可以不用I2C通信,用3个IO口通信就可以了,协议为NXP的DSA协议。你可以搜一下DSA协议。而且DSA可以做到半双工通信。 armok 发表于 2014-5-24 21:41
楼主的标题不合格,已经被封锁id.
这位楼主前面是想寻求解决方案的,但后来他自己把调通的从机代码贴出来了,想了解这方面知识的人,后面根据楼主贴出来的代码,还是很有参考价值的,好像不应该封ID吧。这样以后大家都不敢积极讨论了,个人认为楼主的贴出来的代码很有参考价值 我也是来学习的 哈哈大笑'哈哈大笑
页:
[1]