OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5627|回复: 9

STM32F407 模拟IIC 驱动24c128 无法读写

[复制链接]

1

主题

5

帖子

0

精华

新手上路

积分
20
金钱
20
注册时间
2017-5-28
在线时间
4 小时
发表于 2017-5-28 22:45:45 | 显示全部楼层 |阅读模式
1金钱
我用的是STM32f4 探索者 开发板, 24c02 能正常读写, 换了24c128 ,不能正常读写,每次读出来的数据都是255;
程序如下:大神帮我分析一下程序哪里有问题,我监测每次的应答消息都能正确!

u8 okflag = 0;

#define SDA_IN()  {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=0<<9*2;}         //PB9ê&#228;è&#235;&#196;£ê&#189;
#define SDA_OUT() {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=1<<9*2;}  //PB9ê&#228;3&#246;&#196;£ê&#189;

#define IIC_SCL    PBout(8) //SCL
#define IIC_SDA    PBout(9) //SDA         
#define READ_SDA   PBin(9)  //ê&#228;è&#235;SDA


void IIC_Init(void)
{                       
  GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//ê1&#196;üGPIOBê±&#214;ó

  //GPIOB8,B93&#245;ê&#188;&#187;ˉéè&#214;&#195;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//&#198;&#213;í¨ê&#228;3&#246;&#196;£ê&#189;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//í&#198;íìê&#228;3&#246;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//é&#207;à-
  GPIO_Init(GPIOB, &GPIO_InitStructure);//3&#245;ê&#188;&#187;ˉ
        IIC_SCL=1;
        IIC_SDA=1;
}

void IIC_Start(void)
{
        SDA_OUT();     //sda&#207;&#223;ê&#228;3&#246;
        IIC_SDA=1;                    
        IIC_SCL=1;
        delay_us(4);
        IIC_SDA=0;//START:when CLK is high,DATA change form high to low
        delay_us(4);
        IIC_SCL=0;//&#199;ˉ×&#161;I2C×ü&#207;&#223;£&#172;×&#188;±&#184;·¢&#203;í&#187;ò&#189;óê&#213;êy&#190;Y
}          
//2úéúIICí£&#214;1D&#197;o&#197;
void IIC_Stop(void)
{
        SDA_OUT();//sda&#207;&#223;ê&#228;3&#246;
        IIC_SCL=0;
        IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
        delay_us(4);
        IIC_SCL=1;
        IIC_SDA=1;//·¢&#203;íI2C×ü&#207;&#223;&#189;áê&#248;D&#197;o&#197;
        delay_us(4);                                                                  
}

u8 IIC_Wait_Ack(void)
{
        u8 ucErrTime=0;
        SDA_IN();     
        IIC_SDA=1;delay_us(1);          
        IIC_SCL=1;delay_us(1);         
        while(READ_SDA)
        {
                ucErrTime++;
                if(ucErrTime>250)
                {
                        IIC_Stop();
                        return 1;
                }
        }
        IIC_SCL=0;  
        return 0;  
}

void IIC_Ack(void)
{
        IIC_SCL=0;
        SDA_OUT();
        IIC_SDA=0;
        delay_us(2);
        IIC_SCL=1;
        delay_us(2);
        IIC_SCL=0;
}
//2&#187;2úéúACKó|′e                    
void IIC_NAck(void)
{
        IIC_SCL=0;
        SDA_OUT();
        IIC_SDA=1;
        delay_us(2);
        IIC_SCL=1;
        delay_us(2);
        IIC_SCL=0;
}                                                                              
                  
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
        SDA_OUT();             
    IIC_SCL=0;//à-μíê±&#214;ó&#191;aê&#188;êy&#190;Y′&#171;ê&#228;
    for(t=0;t<8;t++)
    {              
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1;           
                delay_us(2);   //&#182;&#212;TEA5767&#213;aèy&#184;&#246;&#209;óê±&#182;&#188;ê&#199;±&#216;D&#235;μ&#196;
                IIC_SCL=1;
                delay_us(2);
                IIC_SCL=0;       
                delay_us(2);
    }         
}             
//&#182;á1&#184;&#246;×&#214;&#189;ú£&#172;ack=1ê±£&#172;·¢&#203;íACK£&#172;ack=0£&#172;·¢&#203;ínACK   
u8 IIC_Read_Byte(unsigned char ack)
{
        unsigned char i,receive=0;
        SDA_IN();//SDAéè&#214;&#195;&#206;aê&#228;è&#235;
    for(i=0;i<8;i++ )
        {
        IIC_SCL=0;
        delay_us(2);
                IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
                delay_us(1);
    }                                         
    if (!ack)
        IIC_NAck();//·¢&#203;ínACK
    else
        IIC_Ack(); //·¢&#203;íACK   
    return receive;
}




//3&#245;ê&#188;&#187;ˉIIC&#189;ó&#191;ú
void AT24CXX_Init(void)
{
        IIC_Init();//IIC3&#245;ê&#188;&#187;ˉ
}
//&#212;úAT24CXX&#214;&#184;&#182;¨μ&#216;&#214;·&#182;á3&#246;ò&#187;&#184;&#246;êy&#190;Y
//ReadAddr:&#191;aê&#188;&#182;áêyμ&#196;μ&#216;&#214;·  
//·μ&#187;&#216;&#214;μ  :&#182;áμ&#189;μ&#196;êy&#190;Y
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{                                  
                u8 temp=0;                                                                                                                                                               
    IIC_Start();  
       
                IIC_Send_Byte(0XA0);           //·¢&#203;íD′&#195;üá&#238;
                IIC_Wait_Ack();//1

                IIC_Send_Byte(ReadAddr>>8);//·¢&#203;í&#184;&#223;μ&#216;&#214;·            
                IIC_Wait_Ack();       

                IIC_Send_Byte(ReadAddr%256);   //·¢&#203;íμíμ&#216;&#214;·
                IIC_Wait_Ack();          //2
//                if(!IIC_Wait_Ack())
//                {
//                        okflag = 12;
//                }
//                else
//                {
//                        okflag = 47;
//                }
                IIC_Start();                     
                IIC_Send_Byte(0XA1);           //&#189;&#248;è&#235;&#189;óê&#213;&#196;£ê&#189;                          
                IIC_Wait_Ack();       
       
    temp=IIC_Read_Byte(0);                  
    IIC_Stop();//2úéúò&#187;&#184;&#246;í£&#214;1ì&#245;&#188;t            
        return temp;
}

u8 AT24C128ReadOneByte(void) //test
{                                  
                u8 temp=0;                                                                                                                                                               
    IIC_Start();  
       
                IIC_Send_Byte(0XA0);           //·¢&#203;íD′&#195;üá&#238;
                IIC_Wait_Ack();//1

                IIC_Send_Byte(0);//·¢&#203;í&#184;&#223;μ&#216;&#214;·            
                IIC_Wait_Ack();       

                IIC_Send_Byte(0);   //·¢&#203;íμíμ&#216;&#214;·
                IIC_Wait_Ack();          //2

                IIC_Start();                     
                IIC_Send_Byte(0XA1);           //&#189;&#248;è&#235;&#189;óê&#213;&#196;£ê&#189;                          
                //IIC_Wait_Ack();       
                if(!IIC_Wait_Ack())
                        okflag = 20;
                else       
                        okflag=55;
    temp=IIC_Read_Byte(0);                  
    IIC_Stop();//2úéúò&#187;&#184;&#246;í£&#214;1ì&#245;&#188;t            
        return temp;
}
void AT24C128WriteOneByte(u8 DataToWrite) //test
{                                                                                                                                                                                          
  IIC_Start();  
       
        IIC_Send_Byte(0XA0);                   //·¢&#203;íD′&#195;üá&#238;
        IIC_Wait_Ack();    // 1
       
        IIC_Send_Byte(0);    //·¢&#203;í&#184;&#223;μ&#216;&#214;·          
        IIC_Wait_Ack();    // 2
       
  IIC_Send_Byte(0);   //·¢&#203;íμíμ&#216;&#214;·
        IIC_Wait_Ack();    //3
       
        IIC_Send_Byte(DataToWrite);     //·¢&#203;í×&#214;&#189;ú                                                          
       
        if(!IIC_Wait_Ack()) okflag=10;
        else        okflag=33;//4)okflag
               
  IIC_Stop();                     //2úéúò&#187;&#184;&#246;í£&#214;1ì&#245;&#188;t
        delay_ms(10);         
}
//&#212;úAT24CXX&#214;&#184;&#182;¨μ&#216;&#214;·D′è&#235;ò&#187;&#184;&#246;êy&#190;Y
//WriteAddr  ′è&#235;êy&#190;Yμ&#196;&#196;&#191;μ&#196;μ&#216;&#214;·   
//DataToWrite:òaD′è&#235;μ&#196;êy&#190;Y
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{                                                                                                                                                                                          
  IIC_Start();  
       
        IIC_Send_Byte(0XA0);                   //·¢&#203;íD′&#195;üá&#238;
        IIC_Wait_Ack();    // 1
       
        IIC_Send_Byte(WriteAddr/0x0100);    //·¢&#203;í&#184;&#223;μ&#216;&#214;·          
        IIC_Wait_Ack();    // 2
       
  IIC_Send_Byte(WriteAddr%256);   //·¢&#203;íμíμ&#216;&#214;·
        IIC_Wait_Ack();    //3
       
        IIC_Send_Byte(DataToWrite);     //·¢&#203;í×&#214;&#189;ú                                                          
        IIC_Wait_Ack();           //4
       
  IIC_Stop();                     //2úéúò&#187;&#184;&#246;í£&#214;1ì&#245;&#188;t
        delay_ms(10);         
}
//&#212;úAT24CXXà&#239;&#195;&#230;μ&#196;&#214;&#184;&#182;¨μ&#216;&#214;·&#191;aê&#188;D′è&#235;3¤&#182;è&#206;aLenμ&#196;êy&#190;Y
//&#184;&#195;oˉêyó&#195;óúD′è&#235;16bit&#187;ò&#213;&#223;32bitμ&#196;êy&#190;Y.
//WriteAddr  :&#191;aê&#188;D′è&#235;μ&#196;μ&#216;&#214;·  
//DataToWrite:êy&#190;Yêy×éê×μ&#216;&#214;·
//Len        :òaD′è&#235;êy&#190;Yμ&#196;3¤&#182;è2,4
void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len)
{         
        u8 t;
        for(t=0;t<Len;t++)
        {
                AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);
        }                                                                                                    
}

//&#212;úAT24CXXà&#239;&#195;&#230;μ&#196;&#214;&#184;&#182;¨μ&#216;&#214;·&#191;aê&#188;&#182;á3&#246;3¤&#182;è&#206;aLenμ&#196;êy&#190;Y
//&#184;&#195;oˉêyó&#195;óú&#182;á3&#246;16bit&#187;ò&#213;&#223;32bitμ&#196;êy&#190;Y.
//ReadAddr   :&#191;aê&#188;&#182;á3&#246;μ&#196;μ&#216;&#214;·
//·μ&#187;&#216;&#214;μ     :êy&#190;Y
//Len        :òa&#182;á3&#246;êy&#190;Yμ&#196;3¤&#182;è2,4
u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len)
{         
        u8 t;
        u32 temp=0;
        for(t=0;t<Len;t++)
        {
                temp<<=8;
                temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1);                                            
        }
        return temp;                                                                                                    
}
//&#188;ì2éAT24CXXê&#199;·&#241;&#213;y3£
//&#213;aà&#239;ó&#195;á&#203;24XXμ&#196;×&#238;oóò&#187;&#184;&#246;μ&#216;&#214;·(255)à′′&#230;′¢±ê&#214;&#190;×&#214;.
//è&#231;1&#251;ó&#195;&#198;&#228;&#203;&#251;24C&#207;μáD,&#213;a&#184;&#246;μ&#216;&#214;·òaDT&#184;&#196;
//·μ&#187;&#216;1:&#188;ì2aê§°ü
//·μ&#187;&#216;0:&#188;ì2a3é1|
u8 AT24CXX_Check(void)
{
        u8 temp;
        temp=AT24CXX_ReadOneByte(16383);//±ü&#195;a&#195;&#191;′&#206;&#191;a&#187;ú&#182;&#188;D′AT24CXX                          
        if(temp==0X55)return 0;                  
        else//&#197;&#197;3yμúò&#187;′&#206;3&#245;ê&#188;&#187;ˉμ&#196;&#199;é&#191;&#246;
        {
                AT24CXX_WriteOneByte(16383,0X55);
            temp=AT24CXX_ReadOneByte(16383);          
                if(temp==0X55)return 0;
        }
        return 1;                                                                                          
}

//&#212;úAT24CXXà&#239;&#195;&#230;μ&#196;&#214;&#184;&#182;¨μ&#216;&#214;·&#191;aê&#188;&#182;á3&#246;&#214;&#184;&#182;¨&#184;&#246;êyμ&#196;êy&#190;Y
//ReadAddr :&#191;aê&#188;&#182;á3&#246;μ&#196;μ&#216;&#214;· &#182;&#212;24c02&#206;a0~255
//pBuffer  :êy&#190;Yêy×éê×μ&#216;&#214;·
//NumToRead:òa&#182;á3&#246;êy&#190;Yμ&#196;&#184;&#246;êy
void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
{
        while(NumToRead)
        {
                *pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);       
                NumToRead--;
        }
}  
//&#212;úAT24CXXà&#239;&#195;&#230;μ&#196;&#214;&#184;&#182;¨μ&#216;&#214;·&#191;aê&#188;D′è&#235;&#214;&#184;&#182;¨&#184;&#246;êyμ&#196;êy&#190;Y
//WriteAddr :&#191;aê&#188;D′è&#235;μ&#196;μ&#216;&#214;· &#182;&#212;24c02&#206;a0~255
//pBuffer   :êy&#190;Yêy×éê×μ&#216;&#214;·
//NumToWrite:òaD′è&#235;êy&#190;Yμ&#196;&#184;&#246;êy
void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
{
        while(NumToWrite--)
        {
                AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
                WriteAddr++;
                pBuffer++;
        }
}



最佳答案

查看完整内容[请看2#楼]

这类型的问题解决起来很简单, 1. I2C的引脚请设置 为开漏输出.. 2. 波形用逻辑分析查看一下.(没有逻辑分析仪,一定要买,开发利器中少不了它,比示波器还好用) 3. 24C128的资料仔细看看. 一定可以解决.
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

50

主题

1805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6662
金钱
6662
注册时间
2016-5-29
在线时间
910 小时
发表于 2017-5-28 22:45:46 | 显示全部楼层
本帖最后由 操作系统 于 2017-5-29 08:27 编辑

这类型的问题解决起来很简单,

1.  I2C的引脚请设置 为开漏输出..
2. 波形用逻辑分析查看一下.(没有逻辑分析仪,一定要买,开发利器中少不了它,比示波器还好用)
3.  24C128的资料仔细看看.

一定可以解决.
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
20
金钱
20
注册时间
2017-5-28
在线时间
4 小时
 楼主| 发表于 2017-5-28 22:49:24 | 显示全部楼层
单个字节读书我是用着两个函数,不知道有没有问题,IIC_Wait_Ack();能正常应答
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{                                  
                u8 temp=0;                                                                                                                                                               
    IIC_Start();  
       
                IIC_Send_Byte(0XA0);           //·¢&#203;íD′&#195;üá&#238;
                IIC_Wait_Ack();//1

                IIC_Send_Byte(ReadAddr>>8);//·¢&#203;í&#184;&#223;μ&#216;&#214;·            
                IIC_Wait_Ack();       

                IIC_Send_Byte(ReadAddr%256);   //·¢&#203;íμíμ&#216;&#214;·
                IIC_Wait_Ack();          //2

                IIC_Start();                     
                IIC_Send_Byte(0XA1);           //&#189;&#248;è&#235;&#189;óê&#213;&#196;£ê&#189;                          
                IIC_Wait_Ack();       
       
    temp=IIC_Read_Byte(0);                  
    IIC_Stop();//2úéúò&#187;&#184;&#246;í£&#214;1ì&#245;&#188;t            
        return temp;
}

u8 AT24C128ReadOneByte(void) //test
{                                  
                u8 temp=0;                                                                                                                                                               
    IIC_Start();  
       
                IIC_Send_Byte(0XA0);           //·¢&#203;íD′&#195;üá&#238;
                IIC_Wait_Ack();//1

                IIC_Send_Byte(0);//·¢&#203;í&#184;&#223;μ&#216;&#214;·            
                IIC_Wait_Ack();       

                IIC_Send_Byte(0);   //·¢&#203;íμíμ&#216;&#214;·
                IIC_Wait_Ack();          //2

                IIC_Start();                     
                IIC_Send_Byte(0XA1);           //&#189;&#248;è&#235;&#189;óê&#213;&#196;£ê&#189;                          
                IIC_Wait_Ack();       
    temp=IIC_Read_Byte(0);                  
    IIC_Stop();//2úéúò&#187;&#184;&#246;í£&#214;1ì&#245;&#188;t            
        return temp;
}
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
20
金钱
20
注册时间
2017-5-28
在线时间
4 小时
 楼主| 发表于 2017-5-30 17:00:26 | 显示全部楼层
操作系统 发表于 2017-5-28 22:45
这类型的问题解决起来很简单,

1.  I2C的引脚请设置 为开漏输出..

I2C的引脚请设置 为开漏输出.. ,  问题解决了。为什么原子的例子程序不是开漏输出用在24c02也开的。
回复

使用道具 举报

50

主题

1805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6662
金钱
6662
注册时间
2016-5-29
在线时间
910 小时
发表于 2017-5-30 22:18:21 | 显示全部楼层
lui515520 发表于 2017-5-30 17:00
I2C的引脚请设置 为开漏输出.. ,  问题解决了。为什么原子的例子程序不是开漏输出用在24c02也开的。

i2c用开漏输出方式,就不用设置SDA的方向了.这样子代码就简化了.并且方便多从机接入.其它的方法实现了I2C,但它可能会不完美,有着这样或者那样的小问题存在.
至于原子哥代码为什么没有用开漏方式.也可以成功操作I2C.或者他另有高明之处吧.我个人意见比较死板,I2C都会设置为开漏.这一点,从STM8S的I2C引脚,不可以编程为推挽输出可以佐证.
回复

使用道具 举报

5

主题

33

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
206
金钱
206
注册时间
2015-8-7
在线时间
50 小时
发表于 2017-5-30 23:57:22 来自手机 | 显示全部楼层
操作系统 发表于 2017-5-30 22:18
i2c用开漏输出方式,就不用设置SDA的方向了.这样子代码就简化了.并且方便多从机接入.其它的方法实现了I2C, ...

话说设置开漏输出 引脚需不需要上拉电阻?我看网上介绍说需要外加上来电阻输出模式下才能高电平
回复

使用道具 举报

50

主题

1805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6662
金钱
6662
注册时间
2016-5-29
在线时间
910 小时
发表于 2017-5-31 07:44:18 | 显示全部楼层
卖姑娘的小火柴 发表于 2017-5-30 23:57
话说设置开漏输出 引脚需不需要上拉电阻?我看网上介绍说需要外加上来电阻输出模式下才能高电平

开漏,当然要接上拉电阻了.这是必须的.这是常识.
回复

使用道具 举报

5

主题

33

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
206
金钱
206
注册时间
2015-8-7
在线时间
50 小时
发表于 2017-5-31 10:56:05 | 显示全部楼层
操作系统 发表于 2017-5-31 07:44
开漏,当然要接上拉电阻了.这是必须的.这是常识.

那所以 正点的口子上有米有接上拉电阻 如果没得话 也就是不得不用其他的方式来驱动IIC了  而不能用开漏输出吧
回复

使用道具 举报

50

主题

1805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6662
金钱
6662
注册时间
2016-5-29
在线时间
910 小时
发表于 2017-5-31 13:34:38 | 显示全部楼层
卖姑娘的小火柴 发表于 2017-5-31 10:56
那所以 正点的口子上有米有接上拉电阻 如果没得话 也就是不得不用其他的方式来驱动IIC了  而不能用开漏输 ...

说得有道理.
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
20
金钱
20
注册时间
2017-5-28
在线时间
4 小时
 楼主| 发表于 2017-6-11 11:05:14 | 显示全部楼层
将GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;改为GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;就搞好了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-18 01:25

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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