打印

24c02读写求助

[复制链接]
2291|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wjiwji|  楼主 | 2013-5-15 11:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近在搞一个项目,其中用到了24c02,从网上下了一个驱动。一开始在开发板做的时候,用的是AT24C02N,读写还可以。不过AT24C02N在我们这边电子市场不好买,现在市场上清一色的的AT24C02BN,买了一些回来试的时候发现不能用,具体情况是:写器件地址0xA0有ACK回应,但接下来写地址add就怎么也等不来ACK,程序就卡在这里了。掰了好久,又是调延时又是改顺序都没有用就是卡在写add无应答那里,没法只好来坛子里请各位前辈帮帮忙,看看错误出在那里,小弟这里先谢了啊!

相关帖子

沙发
wjiwji|  楼主 | 2013-5-15 13:12 | 只看该作者

使用特权

评论回复
板凳
ayb_ice| | 2013-5-15 13:28 | 只看该作者
拿到通用编程器试试

不过根据你的习惯特点,基本是程序问题

使用特权

评论回复
地板
wjiwji|  楼主 | 2013-5-15 13:59 | 只看该作者
#include <msp430x14x.h>
typedef unsigned char uchar;
typedef unsigned int  uint;

#define SCL_H P3OUT |= BIT2
#define SCL_L P3OUT &= ~BIT2
#define SDA_H P3OUT |= BIT0
#define SDA_L P3OUT &= ~BIT0

#define SDA_in  P3DIR &= ~BIT0   //SDA改成输入模式
#define SDA_out P3DIR |= BIT0    //SDA变回输出模式
#define SDA_val P3IN&BIT0        //SDA的位值

#define TRUE    1
#define FALSE   0

//#define

/*******************************************
函数名称:delay
功    能:延时约15us的时间
参    数:无
返回值  :无
********************************************/
void delay(void)
{
    uchar i;
   
        for(i = 0;i < 15;i++)
          _NOP();
}       
/*******************************************
函数名称:start
功    能:完成IIC的起始条件操作
参    数:无
返回值  :无
********************************************/
void start(void)
{
        SCL_L;
        SDA_H;
        SCL_H;
        delay();
        SDA_L;
        delay();
        SCL_L;
        delay();
}
/*******************************************
函数名称:stop
功    能:完成IIC的终止条件操作
参    数:无
返回值  :无
********************************************/
void stop(void)
{
          SCL_L;
        SDA_L;
        delay();
        SCL_H;
        delay();
        SDA_H;
        delay();          
}
/*******************************************
函数名称:mack
功    能:完成IIC的主机应答操作
参    数:无
返回值  :无
********************************************/
void mack(void)
{
        SDA_L;
        _NOP(); _NOP();
        SCL_H;
        delay();
        SCL_L;
        _NOP();_NOP();
        SDA_H;     
        delay();
}
/*******************************************
函数名称:mnack
功    能:完成IIC的主机无应答操作
参    数:无
返回值  :无
********************************************/
void mnack(void)
{
        SDA_H;
        _NOP();_NOP();
        SCL_H;
        delay();
        SCL_L;
        _NOP();_NOP();
        SDA_L;   
        delay();      
}

/**********检查应答信号函数******************/
/*如果返回值为1则证明有应答信号,反之没有*/
/*******************************************
函数名称:check
功    能:检查从机的应答操作
参    数:无
返回值  :从机是否有应答:1--有,0--无
********************************************/
uchar check(void)
{
        uchar slaveack;
   
        SDA_H;
        _NOP(); _NOP();
        SCL_H;
        _NOP(); _NOP();
        SDA_in;
        _NOP(); _NOP();
        slaveack = SDA_val;   //读入SDA数值
        SCL_L;
        delay();
    SDA_out;
    if(slaveack)    return FALSE;
    else            return TRUE;
}
/*******************************************
函数名称:write1
功    能:向IIC总线发送一个1
参    数:无
返回值  :无
********************************************/
void write1(void)
{
        SDA_H;
        delay();
        SCL_H;
        delay();
        SCL_L;                               
        delay();
}
/*******************************************
函数名称:write0
功    能:向IIC总线发送一个0
参    数:无
返回值  :无
********************************************/
void write0(void)
{
        SDA_L;
        delay();
        SCL_H;
        delay();                         
        SCL_L;                               
        delay();
}
/*******************************************
函数名称:write1byte
功    能:向IIC总线发送一个字节的数据
参    数:wdata--发送的数据
返回值  :无
********************************************/
void write1byte(uchar wdata)
{
        uchar i;
   
        for(i = 8;i > 0;i--)
        {
                if(wdata & 0x80)        write1();
                else                             write0();
                wdata <<= 1;
        }                  
       
        SDA_H;
        _NOP();
}
/*******************************************
函数名称:writeNbyte
功    能:向IIC总线发送N个字节的数据
参    数:outbuffer--指向发送数据存放首地址
          的指针
          n--数据的个数
返回值  :发送是否成功的标志:1--成功,0--失败
********************************************/
uchar writeNbyte(uchar * outbuffer,uchar n)
{
        uchar i;
   
        for(i = 0;i < n;i++)
        {
                write1byte(* outbuffer);
                if(check())      
                {
                        outbuffer++;                       
                }
                else
                {
                        stop();
                        return FALSE;
                }
        }

        stop();
        return TRUE;                       
}
/*******************************************
函数名称:read1byte
功    能:从IIC总线读取一个字节
参    数:无
返回值  :读取的数据
********************************************/
uchar read1byte(void)
{
        uchar  rdata = 0x00,i;
    uchar flag;
   
        for(i = 0;i < 8;i++)
        {
                SDA_H;
                delay();
                SCL_H;
        SDA_in;
                delay();
                flag = SDA_val;
                rdata <<= 1;
                if(flag)        rdata |= 0x01;
        SDA_out;
                SCL_L;
                delay();
        }

        return rdata;
}
/*******************************************
函数名称:readNbyte
功    能:从IIC总线读取N个字节的数据
参    数:inbuffer--读取后数据存放的首地址
          n--数据的个数
返回值  :无
********************************************/
void readNbyte(uchar * inbuffer,uchar n)
{
        uchar i;
   
        for(i = 0;i < n;i++)
        {
                inbuffer[i] = read1byte();
                if(i < (n-1))        mack();
                else            mnack();
        }
         
        stop();
}

#include "IIC.h"
#include <msp430x14x.h>
typedef unsigned char uchar;
typedef unsigned int  uint;

#define deviceaddress 0xa0

/*******************************************
函数名称:delay_10ms
功    能:延时约6ms,等待EEPROM完成内部写入
参    数:无
返回值  :无
********************************************/
void delay_10ms(void)
{
        uint i = 6000;
        while(i--);
}
/*******************************************
函数名称:Write_1Byte
功    能:向EEPROM中写入1个字节的数据
参    数:Wdata--写入的数据
          dataaddress--数据的写入地址
返回值  :写入结果:1--成功,0--失败
********************************************/
uchar Write_1Byte(uchar wdata,uchar dataaddress)
{
//          uchar t;
//        t = check();
        start();
        write1byte(deviceaddress);

        if(check() == 1)
        write1byte(dataaddress);
        else
        return 0;
        _NOP();
        _NOP();
        _NOP();
        _NOP();
        _NOP();
        _NOP();
        _NOP();
        _NOP();       
        _NOP();
        _NOP();
        if(check())
                write1byte(wdata);
        else
        return 0;
        _NOP();
        _NOP();
        if(check())            stop();
        else            return 0;
   
    delay_10ms();       //等待EEPROM完成内部写入
        return 1;
}
/*******************************************
函数名称:Write_NByte
功    能:向EEPROM中写入N个字节的数据
参    数:outbuf--指向写入数据存放首地址的指针
          n--数据个数,最大不能超过8,由页地址
             决定其最大长度
          dataaddress--数据写入的首地址
返回值  :写入结果:1--成功,0--失败
********************************************/
uchar Write_NByte(uchar * outbuf,uchar n,uchar dataaddress)
{
        uchar  flag;
   
        start();
        write1byte(deviceaddress);                  //写入器件地址
        if(check() == 1)
        write1byte(dataaddress);                //写入数据字地址
        else
        return 0;
        _NOP();
        _NOP();
        if(check())
        flag=writeNbyte(outbuf,n);
        else
        return 0;
    delay_10ms();       //等待EEPROM完成内部写入
        if(flag)    return 1;
        else        return 0;

}
/*******************************************
函数名称:Read_1Byte_currentaddress
功    能:从EEPROM的当前地址读取1个字节的数据
参    数:无
返回值  :读取的数据
********************************************/
uchar Read_1Byte_currentaddress(void)
{
        uchar temp;
   
        start();
        write1byte((deviceaddress|0x01));
        if(check())       
        temp = read1byte();
        else
        return 0;
        mnack();
        stop();
        return temp;
}
/*******************************************
函数名称:Read_NByte_currentaddress
功    能:从EEPROM的当前地址读取N个字节的数据
参    数:readbuf--指向保存数据地址的指针
          n--读取数据的个数
返回值  :读取结果:1--成功,0--失败
********************************************/
uchar Read_NByte_currentaddress(uchar * readbuf,uchar n)
{   
    start();
        write1byte((deviceaddress|0x01));
        if(check())
        readNbyte(readbuf,n);
        else
        return 0;
   
        return  1;
}

/*******************************************
函数名称:Read_1Byte_Randomaddress
功    能:从EEPROM的指定地址读取1个字节的数据
参    数:dataaddress--数据读取的地址
返回值  :读取的数据
********************************************/
uchar Read_1Byte_Randomaddress(uchar dataaddress)
{
        uchar temp;
   
        start();
        write1byte(deviceaddress);
        if(check())       
        write1byte(dataaddress);
        else
        return 0;
        if(check())
        {
                start();
                write1byte((deviceaddress|0x01));
        }
        else   
        return 0;
        _NOP();
        _NOP();
        _NOP();
        if(check())       
    {temp = read1byte();}
        else
        return 0;

        mnack();
        stop();
        return temp;
}
/*******************************************
函数名称:Read_NByte_Randomaddress
功    能:从EEPROM的指定地址读取N个字节的数据
参    数:readbuf--指向保存数据地址的指针
          n--读取数据的个数
          dataaddress--数据读取的首地址
返回值  :读取结果:1--成功,0--失败
********************************************/
uchar Read_NByte_Randomaddress(uchar * readbuf,uchar n,uchar dataaddress)
{
        start();
        write1byte(deviceaddress);
        if(check())       
        write1byte(dataaddress);
        else
        return 0;
        if(check())
        {
                start();
                write1byte(deviceaddress|0x01);
        }
        else
        return 0;
        _NOP();
        _NOP();
        _NOP();
        _NOP();
        if(check())
        readNbyte(readbuf,n);
        else
        return 0;
       
        return 1;       
}
程序是这样的,帮忙看看。单步没有发现时序的异常,可就是写地址无ACK响应。

使用特权

评论回复
5
wjiwji|  楼主 | 2013-5-15 14:22 | 只看该作者

使用特权

评论回复
6
wjiwji|  楼主 | 2013-5-15 15:40 | 只看该作者
郁闷,怎么没有人知道怎么回事呀

使用特权

评论回复
7
ayb_ice| | 2013-5-15 15:51 | 只看该作者
看了一下程序,程序基本没有问题,但

有些地方要插入延时程序,特别是IO信号变化的地方,有些地方延时明显不够(除非MCU时钟较低),适当加长

强烈建议SDA_in,SDA_out在SCL_L时操作,同时在SDA_out操作前设置SDA输出电平

使用特权

评论回复
8
lrhsx33| | 2013-5-15 16:15 | 只看该作者
ayb_ice 发表于 2013-5-15 15:51
看了一下程序,程序基本没有问题,但

有些地方要插入延时程序,特别是IO信号变化的地方,有些地方延时明显不够 ...

使用特权

评论回复
9
wjiwji|  楼主 | 2013-5-15 19:09 | 只看该作者
ayb_ice大神果然一语中的,把SDA_in,SDA_out和延时改了,马上就可以了。真是太感谢了!!!

使用特权

评论回复
10
wjiwji|  楼主 | 2013-5-15 19:20 | 只看该作者
刚才又做了几个实验,发现延时还不是最重要的,最影响读写的是SDA_in,和SDA_out是在SCL_L还是SCL_H操作。实验表明必须在SCL_L时操作才不会出错,在SCL_H操作时很少正确。其中原因还不得其解,还希望大神不吝赐教呀。
PS:困扰了我好几天的问题终于得到解决了,再次感谢ayb_ice大神,其他有需要的朋友也可以借鉴下这个程序啊

使用特权

评论回复
11
logokfu| | 2013-5-15 20:28 | 只看该作者
wjiwji 发表于 2013-5-15 19:20
刚才又做了几个实验,发现延时还不是最重要的,最影响读写的是SDA_in,和SDA_out是在SCL_L还是SCL_H操作。 ...

延时本来就不是很重要的,毕竟IIC通信有100K,400K的速率。

使用特权

评论回复
12
东北小辉辉| | 2013-5-16 03:49 | 只看该作者
关注一下

使用特权

评论回复
13
ayb_ice| | 2013-5-16 07:53 | 只看该作者
搞定了又不送分的

使用特权

评论回复
14
hjhand| | 2013-5-16 09:19 | 只看该作者
学习学习一下!!不过看EEPROM的datasheet 里面介绍的,只有在SCL为低时,SDA上面的高低电平变化才是有效的,这不是IIC通讯的协议吗?怎么要用程序区验证这个东西啊??

使用特权

评论回复
15
juliuszwj| | 2013-5-16 10:11 | 只看该作者
       要充分保证协议里几个时序要求,建立时间、保持时间等。每次操作结束也要有一定时间延时。不行示波器看波形。

使用特权

评论回复
16
爱就一个字| | 2013-5-16 12:28 | 只看该作者
IIC没搞明白,很简单的问题,本人在调试24C02时,遇到一个关键点,希望对大家有点帮助,24C02在数据写进去之后,如果接下来就进行读操作的话,记得在读写之间加延时

使用特权

评论回复
17
18230145925| | 2013-5-16 12:57 | 只看该作者
菜鸟求25F4096指导。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

13

主题

19

帖子

1

粉丝