搜索
bottom↓
回复: 139

开源,STM32口线模拟I2C程序

[复制链接]

出50入0汤圆

发表于 2009-5-19 19:18:37 | 显示全部楼层 |阅读模式
在STM32的I2C上摔了一跤,测试了官方提供的几个例程和库,都有不同缺陷,也无法弥补:
1、查询方式,在连续读数据的过程中不能中断
2、DMA方式类似,在同一DMA中I2C的级别必须最高,否则同1.
3、中断方式也不能有更高优先级中断I2C,否则同1.
鉴于以上原因,无奈的口线模拟了I2C。(仅仅代表个人看法,欢迎指正)
附件中的项目文件已经过测试,为感谢OUR这几年的帮助,先开源这个小程序。
点击此处下载 ourdev_446117.rar(文件大小:38K) (原文件名:STM32模拟IIC.rar)

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入4汤圆

发表于 2009-5-19 20:25:56 | 显示全部楼层
帮顶一个,stm32的iic的设计缺陷实在是一大败笔。
我也同楼主一样,用模拟的方式去实现那些功能。

出0入0汤圆

发表于 2009-5-19 20:28:24 | 显示全部楼层
继续观望

出0入0汤圆

发表于 2009-5-19 22:04:52 | 显示全部楼层
还没有用到呢,就是要这样把毛病贴出来,大家可以少走弯路

出0入0汤圆

发表于 2009-5-20 16:05:14 | 显示全部楼层
我准备用 UART -> UART -> I2C

出0入0汤圆

发表于 2009-5-20 18:36:58 | 显示全部楼层
用IO模拟方式,不是更没法用DMA和中断吗?

出0入0汤圆

发表于 2009-5-20 20:43:22 | 显示全部楼层
Mark

出50入0汤圆

 楼主| 发表于 2009-5-20 20:59:43 | 显示全部楼层
用口线模拟就是为了防止连读或连写的时候出现错误。DMA和中断是不能用了,但是提高了可靠性。
做产品嘛,还是可靠至上,再说I2C没必要很好的实时性。

出0入0汤圆

发表于 2009-5-20 22:48:55 | 显示全部楼层

出0入0汤圆

发表于 2009-5-22 08:38:11 | 显示全部楼层
STM32的IIC确实麻烦,最近做毕业设计的时候,搞了两天,硬件IIC可以读24C16和CD3315可就是读写不了TEA5767,那个郁闷啊!(毕业设计要交了,急)。无奈第三天开始自己模拟IIC....

出0入0汤圆

发表于 2009-6-6 15:15:01 | 显示全部楼层
哎  STM  I2C  SPI都有一些问题,也可能时自己没有用熟

出0入0汤圆

发表于 2009-6-8 16:31:34 | 显示全部楼层
感觉还是用IO模拟的好用,移植性也好。

出0入0汤圆

发表于 2009-7-14 09:04:33 | 显示全部楼层
在页写的时候应该是有bug的,如果写入的地址不是页开始,那么,
    NumOfPage   =  length / I2C_PageSize;     //要写入的页数
    NumOfSingle =  length % I2C_PageSize;     //不足一页的个数
这个判断就是不正确的。

如I2C_PageSize=8,WriteAddress=6,length=4,就会执行到
      if(NumOfPage== 0)   //数据小于一页
      {
        I2C_BufferWrite(pBuffer,NumOfSingle,WriteAddress,DeviceAddress);   //写少于一页的数据
      }
此时,NumOfSingle=4,即从地址6连续写入4个字节,超过页大小了。

出0入0汤圆

发表于 2009-9-29 16:36:38 | 显示全部楼层
这个24C64能用吗?需要改不?

出0入0汤圆

发表于 2009-9-29 17:09:59 | 显示全部楼层
应该用不了,24C64读写是16位地址

出0入0汤圆

发表于 2009-10-3 11:11:50 | 显示全部楼层
由于I2C1_SDA缺省引脚和FSMC不能同时使用,我也被迫选择了I2C模拟方式。

出0入0汤圆

发表于 2009-10-4 11:02:39 | 显示全部楼层
xiexie!!!!!!!!!!!!!!!!!!!

出0入0汤圆

发表于 2009-10-6 11:16:06 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-10-7 14:09:17 | 显示全部楼层
不错啊 我也用模拟的啊

出0入0汤圆

发表于 2009-10-8 00:06:38 | 显示全部楼层
mark

出0入137汤圆

发表于 2009-10-19 12:05:45 | 显示全部楼层
写得不错,留下

出0入0汤圆

发表于 2009-11-5 16:57:47 | 显示全部楼层
连续整了I2C两天,读写字节,一会可以一会不可以,及其不稳定,准备放弃用模拟来实现。

出0入0汤圆

发表于 2009-11-9 16:41:35 | 显示全部楼层
记号

出0入0汤圆

发表于 2009-11-11 18:57:11 | 显示全部楼层
STM32的I2C真是折磨人。

出0入0汤圆

发表于 2009-11-11 21:01:55 | 显示全部楼层
ji

出0入0汤圆

发表于 2010-2-6 10:48:03 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-2-9 11:45:11 | 显示全部楼层
我也是IO模拟,
用在现在的产品上,感觉可靠性第一.

出0入0汤圆

发表于 2010-2-9 13:15:46 | 显示全部楼层
回复【23楼】marx ●█〓
STM32的I2C真是折磨人。
-----------------------------------------------------------------------

早就体会到了,深有感触.
鸡肋...

出0入0汤圆

发表于 2010-2-9 16:21:10 | 显示全部楼层
有得参考,正在学习STM

出0入0汤圆

发表于 2010-2-21 07:51:37 | 显示全部楼层
确实I2C有点问题

出0入0汤圆

发表于 2010-2-21 08:04:37 | 显示全部楼层
LM3S的IIC我用在产品上了

出0入0汤圆

发表于 2010-2-21 08:19:19 | 显示全部楼层
楼上,上量的产品么?

出0入0汤圆

发表于 2010-2-21 09:03:34 | 显示全部楼层
正要学STM,先谢谢了

出0入0汤圆

发表于 2010-2-21 22:31:48 | 显示全部楼层
Mark

出0入0汤圆

发表于 2010-3-5 15:24:22 | 显示全部楼层
被迫使用模拟I2C 谢谢

出0入0汤圆

发表于 2010-4-6 15:45:41 | 显示全部楼层
肯定得顶呀.

出0入0汤圆

发表于 2010-4-12 14:56:51 | 显示全部楼层
有得参考,正在学习STM

出0入0汤圆

发表于 2010-4-12 16:46:20 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-15 01:00:04 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-15 09:53:51 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-15 11:51:35 | 显示全部楼层
在STM32上的I2C例程中写到:“由于板上EEPROM为M24C02而非M24C08,因此在I2c_ee.c需把I2C_Pagesize由16改为4。”

AT24C02A, 2K SERIAL EEPROM: Internally organized with 32 pages of 8 bytes each,
the 2K requires an 8-bit data word address for random word addressing.

AT24C08A, 8K SERIAL EEPROM: The 8K is internally organized with 64 pages of 16
bytes each. Random word addressing requires a 10-bit data word address.

我想问的是:为何要把16改为4呢?

出0入0汤圆

发表于 2010-4-16 12:05:46 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-18 09:39:07 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-27 13:49:41 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-27 13:49:54 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-6-17 23:02:11 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-6-17 23:47:43 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-6-18 10:20:33 | 显示全部楼层
标一下i2c

出0入0汤圆

发表于 2010-6-18 13:43:37 | 显示全部楼层
回复【楼主位】ground
-----------------------------------------------------------------------

mark

出0入0汤圆

发表于 2010-7-7 12:24:32 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-7 15:06:41 | 显示全部楼层
谢谢!

出0入0汤圆

发表于 2010-7-7 16:40:44 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-7 19:32:34 | 显示全部楼层
我也喜欢模拟的,IIC反正不需要高速

出0入0汤圆

发表于 2010-7-8 10:04:15 | 显示全部楼层
楼主,手册没说I2C查询方式不能被中断吧!
I2C确实设计的不好,很难用.
如果读取已知长度的数据还好,可以提前准备NAK,STOP,
如果读取未知长度的数据,必须多读3个字节才能发出STOP.

出0入0汤圆

发表于 2010-8-8 09:24:28 | 显示全部楼层
回复【楼主位】ground
-----------------------------------------------------------------------

你好,我参考你的程序调试通过了MXC6202加速度传感器,想请教你一个问题:在STM32和从设备通信时要读回数据,可为什么只把STM32的模拟IIC引脚只设置为输出模式,哪读数据的时候数据是怎么输入到端口数据寄丛器的?

出0入0汤圆

发表于 2010-8-8 11:33:09 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-8 11:54:45 | 显示全部楼层
/****************************************/       
#define Set_24XXX_SDA(void)        {PIN_SDA=1;}
#define Clr_24XXX_SDA(void)        {PIN_SDA=0;}
#define Get_24XXX_SDA(void)        {PIN_SDA;}          
#define Set_24XXX_SCL(void)        {PIN_SCL=1;}
#define Clr_24XXX_SCL(void)        {PIN_SCL=0;}                                                                  
/****************************************/
static void nop(void)
{        asm("nop");
        asm("nop");
        asm("nop");
}                               
/****************************************/                                                                  
static void ProgrameDelay(int16u x)
{        while(x--);
}
/****************************************/
static void Start(void)
{        Clr_24XXX_SCL();     
        Set_24XXX_SDA();
        Set_24XXX_SCL();
        nop();
        Clr_24XXX_SDA();
        nop();
        Clr_24XXX_SCL();
        Set_24XXX_SDA();     
}
/****************************************/
void Stop(void)
{        Clr_24XXX_SCL();
        Clr_24XXX_SDA();
        Set_24XXX_SCL();
        nop();
        Set_24XXX_SDA();
        nop();
        Clr_24XXX_SCL();
}                                                                                         
/****************************************/
static int8u GetAck(void)
{        int8u ack;
        Clr_24XXX_SCL();
        Set_24XXX_SDA();
        Set_24XXX_SCL();
        nop();
        ack= Get_24XXX_SDA();                 
        Clr_24XXX_SCL();
        return ack;
}
/****************************************/
static void Ack(void)
{        Clr_24XXX_SDA();
        Set_24XXX_SCL();
        nop();
        Clr_24XXX_SCL();
        nop();
        Set_24XXX_SDA();
}                          
/****************************************/
static void Nack(void)
{        Set_24XXX_SDA();
        Set_24XXX_SCL();
        nop();
        Clr_24XXX_SCL();
}                                  
/****************************************/
static void SendByte(int8u sendbyte)
{        int8u i;
        for(i=8;i>0;i--)
           {        Clr_24XXX_SCL();
                if(sendbyte & 0x80)
                {        Set_24XXX_SDA();
                }
                else
                {        Clr_24XXX_SDA();
                }
                sendbyte<<= 1;
                Set_24XXX_SCL();
                nop();
           }
        Clr_24XXX_SCL();
}                                                          
/****************************************/
static int8u ReceiveByte(void)
{        int8u resualt,i=8;
        Clr_24XXX_SCL();
        while(i--)
        {        Set_24XXX_SCL();
                resualt= (resualt<<1)|Get_24XXX_SDA();  
                Clr_24XXX_SCL();
        }
        return resualt;
}
/****************************************/       
int8u Rw24XXX(int16u address,int8u *buf,int16u number,int8u control)
{        int16u i;
        int8u *ptr;
        int8u error=1;
        int8s time=3;
        while(1)
           {        if(--time < 0) break;
                ptr= buf;
                Start();
                   SendByte(control&0xfe); if(GetAck())continue;       
                   SendByte(address>>8); if(GetAck())continue;        //如果地址小于2字节的,如24c02,04,16,32可以屏蔽此句
                   SendByte(address); if(GetAck())continue;

                   if(!(control&0x01))
            {        i= number;
                      error= 0;                     
                      while(i--)
                {        SendByte(*ptr++); if(!GetAck())continue;
                        error= 1;
                        break;
                }
                      if(error == 1) continue;
                      break;
            }
                   else
            {        Start();
                    SendByte(control); if(GetAck())continue;
                    while(--number)
                    {        *ptr++= ReceiveByte();
                            Ack();
                    }
                    *ptr= ReceiveByte();        
                    Nack();
                    error= 0;
                    break;
            }
        }
        Stop();
        if(!(control&0x01))
        {        ProgrameDelay(1000);
        }
        return error;
}                                          
/****************************************/

出0入0汤圆

发表于 2010-8-9 01:05:48 | 显示全部楼层
thank you very much.

出0入0汤圆

发表于 2010-8-9 07:53:19 | 显示全部楼层
模拟的移植方便

出0入0汤圆

发表于 2010-8-9 08:48:08 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-8-23 15:13:52 | 显示全部楼层
正在调试此I2C,看到此贴,真乃雪中送炭,谢拉。先看看。。。学习模拟I2C。

出0入0汤圆

发表于 2010-8-27 15:26:53 | 显示全部楼层
ST I2C 存在什么问题啊?请教大家

出0入0汤圆

发表于 2010-9-14 10:58:57 | 显示全部楼层
我现在已经被IIc搞得一头雾水

出0入0汤圆

发表于 2010-9-17 11:20:17 | 显示全部楼层
嗯,确实有问题:

(原文件名:1.JPG)

我也想用你的模拟IIC了

出0入0汤圆

发表于 2010-9-17 16:35:26 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-17 17:32:00 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-18 06:12:51 | 显示全部楼层
测试了楼主程序,有点问题,读的时候第二次Start的时候出现低电平尖峰(约0.5us),修改如下


(原文件名:1.jpg)

出0入0汤圆

发表于 2010-9-18 15:06:21 | 显示全部楼层
不错!!!!!!!模拟的就是好用啊!!!!!!!!!!!!!!!!

出0入0汤圆

发表于 2010-9-19 08:45:44 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-19 08:46:08 | 显示全部楼层
不错!!!!!!!模拟的就是好用啊!!!!!!!!!!!!!!!!

出0入0汤圆

发表于 2010-9-19 09:10:47 | 显示全部楼层
还是直接模拟的吧,硬件的IIC把我搞残废了

出0入0汤圆

发表于 2010-9-19 13:44:47 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-26 20:43:09 | 显示全部楼层
MARK
头像被屏蔽

出0入0汤圆

发表于 2010-9-27 22:49:32 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-9-28 15:21:31 | 显示全部楼层
学习了,mark

出0入0汤圆

发表于 2010-10-19 09:11:08 | 显示全部楼层
模拟的  怎么用在 两个cpu通讯呢

出0入0汤圆

发表于 2010-11-30 15:38:06 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-12-2 15:46:00 | 显示全部楼层
一直用的就是模拟....

出0入0汤圆

发表于 2010-12-2 22:56:14 | 显示全部楼层
mark

出0入21汤圆

发表于 2010-12-3 19:21:26 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-5 12:36:11 | 显示全部楼层
回复【12楼】hcdragon  
在页写的时候应该是有bug的,如果写入的地址不是页开始,那么,
    numofpage   =  length / i2c_pagesize;     //要写入的页数
    numofsingle =  length % i2c_pagesize;     //不足一页的个数
这个判断就是不正确的。
如i2c_pagesize=8,writeaddress=6,length=4,就会执行到
      if(numofpage== 0)   //数据小于一页
      {
        i2c_bufferwrite(pbuffer,numofsingle,writeaddress,deviceaddress);   //写少于一页的数据
      }
此时,numofsingle=4,即从地址6连续写入4个字节,超过页大小了。
-----------------------------------------------------------------------

我在此也遇到问题,可以改成
/*************************************************/
if(NumOfPage== 0)   //数据小于一页
{
I2C_BufferWrite(pBuffer,I2C_PageSize-Addr,WriteAddress);   //写少于一页的数据
I2C_BufferWrite(pBuffer+I2C_PageSize-Addr,NumOfSingle-(I2C_PageSize-Addr),WriteAddress+I2C_PageSize-Addr);   //写少于一页的数据     
}
/*************************************************/

出0入0汤圆

发表于 2011-1-14 09:58:38 | 显示全部楼层
thank you

出0入0汤圆

发表于 2011-2-12 10:55:36 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-2-13 11:32:10 | 显示全部楼层
用口线模拟的应该是可以通用的,所以说你的开源程序很有借鉴价值,帮顶一下!

出0入0汤圆

发表于 2011-2-14 12:43:01 | 显示全部楼层
谢谢

出0入0汤圆

发表于 2011-2-14 12:45:14 | 显示全部楼层
纠结中,没有心情去研究AT系列的存储器,太小,不实用。

出0入0汤圆

发表于 2011-2-25 21:32:19 | 显示全部楼层
回复【楼主位】ground
在stm32的i2c上摔了一跤,测试了官方提供的几个例程和库,都有不同缺陷,也无法弥补:
1、查询方式,在连续读数据的过程中不能中断
2、dma方式类似,在同一dma中i2c的级别必须最高,否则同1.
3、中断方式也不能有更高优先级中断i2c,否则同1.
鉴于以上原因,无奈的口线模拟了i2c。(仅仅代表个人看法,欢迎指正)
附件中的项目文件已经过测试,为感谢our这几年的帮助,先开源这个小程序。
点击此处下载  (原文件名:stm32模拟iic.rar)
-----------------------------------------------------------------------

1、查询方式,在连续读数据的过程中不能中断
这问题让我也碰上了。

出0入0汤圆

发表于 2011-3-22 12:33:18 | 显示全部楼层
留作后备方案吧,STM32的IIC不是容易吃下的,但也要先试试硬件。

出0入0汤圆

发表于 2011-3-23 12:50:05 | 显示全部楼层
回复【89楼】b260123292
留作后备方案吧,stm32的iic不是容易吃下的,但也要先试试硬件。
-----------------------------------------------------------------------

放弃了,STM的IIC实在……

出0入0汤圆

发表于 2011-3-28 16:04:30 | 显示全部楼层
模拟IIC一方面可以用来深入理解IIC协议,另一方面确实可以避免一些原生IIC的问题,这些问题包括对IIC理解不深刻,对MCU理解不深刻等等。MARK,以后备用。。。

出0入0汤圆

发表于 2011-4-10 22:10:49 | 显示全部楼层
MARK.备用

出0入0汤圆

发表于 2011-4-20 11:35:55 | 显示全部楼层
程序,经过测试 ,非常不完善,读写都有很大问题。。。。不建议采用
头像被屏蔽

出0入0汤圆

发表于 2011-6-14 21:50:31 | 显示全部楼层
MARK.备用

出0入0汤圆

发表于 2011-6-28 08:53:48 | 显示全部楼层
使用24C64时:

//读出1串数据         存放读出数据  待读出长度      待读出地址       器件类型(24c64)       
bool I2C_ReadByte(u8* pBuffer,   u8 length,     u16 ReadAddress,  u8 DeviceAddress)
{               
    if(!I2C_Start())return FALSE;
        I2C_SendByte(DeviceAddress & 0xFFFE);   //设置器件写地址
    if(!I2C_WaitAck()){I2C_Stop(); return FALSE;}
        I2C_SendByte((u8)((ReadAddress & 0x1F00) >> 8));   //设置高起始地址
        I2C_WaitAck();
    I2C_SendByte((u8)(ReadAddress & 0x00FF));   //设置低起始地址      
    I2C_WaitAck();
    I2C_Start();
        I2C_SendByte(DeviceAddress | 0x0001);     //设置器件读地址
    I2C_WaitAck();
    while(length)
    {
      *pBuffer = I2C_ReceiveByte();
      if(length == 1)I2C_NoAck();
      else I2C_Ack();
      pBuffer++;
      length--;
    }
    I2C_Stop();
    return TRUE;
}

//写入1字节数据       待写入数据    待写入地址       器件类型(24C64)
bool I2C_WriteByte(u8 SendByte, u16 WriteAddress, u8 DeviceAddress)
{               
    if(!I2C_Start())return FALSE;
        I2C_SendByte(DeviceAddress & 0xFFFE);   //设置器件地址
    if(!I2C_WaitAck()){I2C_Stop(); return FALSE;}
        I2C_SendByte((u8)((WriteAddress & 0x1F00) >> 8));   //设置高起始地址
        I2C_WaitAck();
    I2C_SendByte((u8)(WriteAddress & 0x00FF));   //设置低起始地址
             
    I2C_WaitAck();       
    I2C_SendByte(SendByte);
    I2C_WaitAck();   
    I2C_Stop();
        delay(1);
        //注意:因为这里要等待EEPROM写完,可以采用查询或延时方式(10ms)
    //Systick_Delay_1ms(10);
    return TRUE;
}

出0入0汤圆

发表于 2011-6-28 12:45:50 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-14 22:46:15 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-20 11:49:51 | 显示全部楼层
回复【楼主位】ground  
-----------------------------------------------------------------------

mark

出0入0汤圆

发表于 2011-8-24 18:43:36 | 显示全部楼层
怎么都没有关中断?

出0入0汤圆

发表于 2011-9-21 18:43:25 | 显示全部楼层
多谢楼主,硬件IIC把我害惨了。

出0入0汤圆

发表于 2011-9-21 19:14:04 | 显示全部楼层
mark
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 09:10

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表