huhang 发表于 2014-5-10 16:24:57

两个单片机之间进行模拟I2C通讯

有大侠做过两个单片机之间进行I2C通信的吗?一般单片机端当主机用两条数据线去模拟i2c当主机读取外围的从设备比较简单,但单片机端模拟从机与另外一个单片机模拟I2C当主机进行通信就没搞过了,有人这么做过吗,能否贴出单片机端模拟从机的I2C协议代码,研究一下

ningming 发表于 2014-5-10 16:31:57

高速模拟有难度,不过低速度传送肯定是没有问题的。

tragedy 发表于 2014-5-10 16:34:04

额,还有模拟从机的么

huhang 发表于 2014-5-10 16:35:00

ningming 发表于 2014-5-10 16:31
高速模拟有难度,不过低速度传送肯定是没有问题的。

有用过吗,能否给点参考代码,比较急,所以也没时间去一点一点时序研究

dlmaowf 发表于 2014-5-10 21:15:31

只模拟过主机,没模拟过从机

wangpengcheng 发表于 2014-5-10 21:22:05

没做过,你也别等了,呵呵,有等的时间,自己都把协议看了N遍了!你做一个贴出来也行啊

czzhouyun 发表于 2014-5-10 21:24:04

自己做吧,与其模拟IIC不如直接模拟串口了,这个见过ZLG早期的一款LED驱动芯片上模拟的从机IIC

dr2001 发表于 2014-5-10 21:39:29

模拟从机也是对着IIC写时序就行了,和主机没啥区别,但似乎基本没什么人实现这个。

模拟从机,重要的就是检测到SCL的变化,然后尽快把SCL拉低,等SDA数据准备好再放。这样SCL Strech可以保证时序正确。
从机拉低SCL的速度决定了初始SCL的最高波特率。

huhang 发表于 2014-5-17 15:59:27

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;
                                        }*/
                                        //--------------------------------------------------------------------------------------
                                }
                                       
                        }                               
                }
        }
}

huhang 发表于 2014-5-17 16:00:07

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);                                                                                        //½«½ÓÊÕµ½µÄÊý¾Ý·µ»Ø
}

huhang 发表于 2014-5-17 16:00:38

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;
}

huhang 发表于 2014-5-17 16:00:59

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();
}

huhang 发表于 2014-5-17 16:01:31

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;
}

huhang 发表于 2014-5-17 16:02:32

上面为测试成功的代码,供有需要的参考,花了一两天时间写后测试通过的

liguangqang 发表于 2014-5-17 16:06:25

从机还是用带硬件I2c的好,不然从机什么也做不了,我用带硬件I2C的芯片做过

huhang 发表于 2014-5-17 16:12:41

liguangqang 发表于 2014-5-17 16:06
从机还是用带硬件I2c的好,不然从机什么也做不了,我用带硬件I2C的芯片做过 ...

我这里是没有办法了,之前的老产品,要改造,现在缺少通信接口,只能这么干,属于变态的设计了

liguangqang 发表于 2014-5-17 16:27:25

如做产品,做出来后生不如死。。。。。小心呀

huhang 发表于 2014-5-17 21:10:47

liguangqang 发表于 2014-5-17 16:27
如做产品,做出来后生不如死。。。。。小心呀

利害关系都有跟总工说过,但硬要这么干,哎,悲剧,刚进新公司,又不好强硬说此方案不可行,说了,还怀疑个人能力

huhang 发表于 2014-5-17 21:16:23

huhang 发表于 2014-5-17 21:10
利害关系都有跟总工说过,但硬要这么干,哎,悲剧,刚进新公司,又不好强硬说此方案不可行,说了,还怀疑 ...

不过我把其简化了,Start和Stop信号从机都不检测,现在在STM32上测试,还算靠谱,从机CPU也没有太多的运算要处理,所以勉强还可以用,主要是用在51上,而且51的单片机的外部中断还被占用了,也没办法利用中断去判断起始和结束跳变沿。哎,老产品还是单片机的,这才是悲剧所在,现在的新产品,谁还去用模拟的I2C做从机通信呀,随便找个CPU也是一大堆的串口,SPI接口啥的

liguangqang 发表于 2014-5-19 07:50:20

不检测start 和stop 是不靠谱的,意味着没有握手标记,帧格式有不确定性。如自定义通信格式,两线通信办法还是有多的方法。可参考单总线协议来做成半双工的(DS18B20)。

bs1234 发表于 2014-5-24 21:21:29

本帖最后由 bs1234 于 2014-5-24 21:28 编辑

可以不用I2C通信,用3个IO口通信就可以了,协议为NXP的DSA协议。你可以搜一下DSA协议。而且DSA可以做到半双工通信。

armok 发表于 2014-5-24 21:41:03

zjtzlqr 发表于 2014-5-28 21:43:15

armok 发表于 2014-5-24 21:41
楼主的标题不合格,已经被封锁id.

这位楼主前面是想寻求解决方案的,但后来他自己把调通的从机代码贴出来了,想了解这方面知识的人,后面根据楼主贴出来的代码,还是很有参考价值的,好像不应该封ID吧。这样以后大家都不敢积极讨论了,个人认为楼主的贴出来的代码很有参考价值

孤舟蓑笠翁 发表于 2014-5-28 21:47:37

我也是来学习的

颜靖峰 发表于 2014-5-28 23:22:12

哈哈大笑'哈哈大笑
页: [1]
查看完整版本: 两个单片机之间进行模拟I2C通讯