历史上的今天
返回首页

历史上的今天

今天是:2025年02月05日(星期三)

正在发生

2020年02月05日 | MSP430平台下实现AT24C02的读写操作

2020-02-05 来源:eefocus

EEPROM可以随机访问和修改其中的任何一个字节,可以往每个bit中写入0或者1,掉电后数据不丢失,可以保存100年,可以擦写100w次。具有较高的可靠性,但是电路复杂/成本也高。因此目前的EEPROM都是几十千字节到几百千字节的,绝少有超过512K的,常用来保存用户数据,运行过程中可以改变。


下面在MSP430平台下以AT24C02为例说明该类可擦除ROM的使用。AT24C02的存储容量为2K bits,内容分成32页,每页8 bytes,共256 bytes。


AT24C02对外以I2C总线形式传输数据,外观如下图所示:

430平台下实现AT24C02的读写操作

A0、A1和A2三个引脚作寻址用;SDA和SCL即I2C总线的数据与时钟引脚;WP作写保护用,即WP在保持高电平时,MCU对AT24C02 的读写操作无效;VCC和GND分别接电源和接地。


MCU在挂载多片AT24C02时,其器件地址由8位构成,除A0、A1和A2三位外,其他位都被锁定为如下所示:

说明: C:Users38AppDataLocalTemp1509088227(1).png?imageView2/2/w/550

最低位为R/W,进行读操作时,该位 = 1,写操作时,该位 = 0。地址写入正确时,AT24C02将会应答以”0”。


AT24C02的读写遵循I2C总线的相关规范,所以有传输的开始条件和停止条件。每一次正常的读写均以开始条件开始,停止条件结束,这两者的时序如下图所示:

说明: C:Users38AppDataLocalTemp1509087542(1).png?imageView2/2/w/550

其软件模拟的实现为:


void start(void)

{

      SCL_H;

      SDA_H;

      _NOP();

      SDA_L;

      _NOP();

      SCL_L;

      _NOP();

}

void stop(void)

{

      SDA_L;

      _NOP();

      SCL_H;

      _NOP();

      SDA_H;

      _NOP();   

}





SCL_H、SDA_H、SDA_L和SCL_L均为宏定义,分别表示MCU向AT24C02相应引脚输出高电平和低电平。


AT24C02的写操作分两种模式,分别为字节写入和页写入两种。


1、字节写入


该写操作需要以MCU写入开始条件开始,继以器件地址,收到AT24C02的应答后继续写入要进行写操作的字地址(即要将数据写入该AT24C02的什么位置),收到应答后才正式写入一个字节的数据,收到应答后写入停止条件,一个完整的字节写入才算完成。

说明: C:Users38AppDataLocalTemp1509089110(1).png?imageView2/2/w/550

其软件模拟的实现为:


uchar Write_1Byte(uchar wdata,uchar dataaddress)

{

     start();

     write1byte(deviceaddress);

     if(check())

        write1byte(dataaddress);

     else

        return 0;

     if(check())

        write1byte(wdata);

     else

        return 0;

     if(check())         stop();

     else            return 0;

  delay_10ms();       //等待EEPROM完成内部写入

     return 1;

}



delay_10ms()是因为AT24C02的每两次写操作之间存在一个写入时间周期tWR,其最大值为5 ms。check()检查AT24C02的应答操作,收到AT24C02回复的0,则应答正确,其软件模拟实现为:


uchar check(void)

{

      uchar slaveack;

      SDA_H;

      _NOP(); _NOP();

      SCL_H;

      _NOP(); _NOP();

   SDA_in;

   _NOP(); _NOP();

      slaveack = SDA_val;   //读入SDA数值

      SCL_L;

      _NOP();

    SDA_out;

    if(slaveack)    return FALSE;

    else          return TRUE;

}



SDA_in和SDA_out分别表示MCU(MSP430)连接AT24C02的I/O引脚方向改为输入或输出,此处SDA_in的作用是为MCU接收AT24C02的应答信号做准备,接收完成后改回SDA_out。SDA_val = P2IN&BIT5,P2.5连接AT24C02的SDA引脚,接收应答信号。


write1byte()向I2C总线写一个字节的数据,其软件模拟实现为:


void write1byte(uchar wdata)

{

    uchar i;

    for(i = 8;i > 0;i--)

    {

           if(wdata & 0x80)     write1();

           else                         write0();

           wdata <<= 1;

    }                  

    SDA_H;

    _NOP();  

}



write1()向I2C总线写一位“1”的数据,其软件模拟实现为:


void write1(void)

{

      SDA_H;

      _NOP();

      SCL_H;

      _NOP();

      SCL_L;                        

      _NOP();

}



write0()向I2C总线写一位“0”的数据,其软件模拟实现为:


void write0(void)

{

      SDA_L;

      _NOP();

      SCL_H;

      _NOP();              

      SCL_L;                        

      _NOP();

}



2、页写入


AT24C02可以实现8位的页写入操作。页写入的形式大体和字节写入类似,只是在MCU写入第一个字节的数据后将会继续写入第二个数据,而不会像字节写入一样写入停止条件。如果写入AT24C02的数据超过8位,超过的数据将会覆盖已被写入的部分。

说明: C:Users38AppDataLocalTemp1509090891(1).png?imageView2/2/w/550

其软件模拟的实现为:


uchar Write_NByte(uchar * outbuf,uchar n,uint dataaddress)

{

     uchar  flag,dataaddressl,dataaddressh;

        dataaddressl = dataaddress;

        dataaddressh = dataaddress>>8;

   

     start();

     write1byte(deviceaddress);                  //写入器件地址

     if(check() == 1)

        write1byte(dataaddressh);                //写入数据字地址

     else

        return 0;

   if(check())

        write1byte(dataaddressl);

   else

        return 0;

     if(check())

        flag=writeNbyte(outbuf,n);

     else

       return 0;

       delay_10ms();       //等待EEPROM完成内部写入

       

     if(flag)   

       return 1;

     else       

       return 0;

}



writeNbyte()向I2C总线写N个字节(对于AT24C02,N = 8)的数据,其软件模拟实现为:


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;                    

}



AT24C02的读操作分三种模式,分别为当前地址读取、随机读取和顺序读取。


1、当前地址读取


上一次读写操作完成后,数据地址计数器加1,并停留在当前位置。这一位置只要不掉电就会一直有效。当R/W = 1时,就可以将当前地址位置的数据读出。

说明: C:Users38AppDataLocalTemp1509092086(1).png?imageView2/2/w/550

其软件模拟的实现为:


uchar Read_1Byte_currentaddress(void)

{

     uchar temp;

     start();

     write1byte((deviceaddress|0x01));

     if(check())    

        temp = read1byte();

     else

        return 0;

     mnack();

     stop();

     return temp;

}

uchar Read_NByte_currentaddress(uchar * readbuf,uchar n)

{  

    start();

     write1byte((deviceaddress|0x01));

     if(check())

        readNbyte(readbuf,n);

     else

        return 0;

   

     return  1;

}



read1byte()从I2C总线读取一个字节,其软件模拟的实现为:


uchar read1byte(void)

{

     uchar  rdata = 0x00,i;

   uchar flag;

     for(i = 0;i < 8;i++)

     {

            SDA_H;

            _NOP();

            SCL_H;

        SDA_in;

            _NOP();

            flag = SDA_val;

            rdata <<= 1;

            if(flag)   rdata |= 0x01;

        SDA_out;

            SCL_L;

            _NOP();

     }

     return rdata;

}



readNbyte()从I2C总线读取一个字节,其软件模拟的实现为:


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

}



mack()完成I2C的MCU应答操作,其软件模拟的实现为:


void mack(void)

{

     SDA_L;

     _NOP(); _NOP();

     SCL_H;

     _NOP();

     SCL_L;

     _NOP();_NOP();

     SDA_H;    

     _NOP();

 

}



mnack()完成I2C的MCU无应答操作,其软件模拟的实现为:


void mnack(void)

{

     SDA_H;

     _NOP(); _NOP();

     SCL_H;

     _NOP();

     SCL_L;

     _NOP(); _NOP();

     SDA_L;  

     _NOP();      

}



2、随机读取


从AT24C02的指定地址读取1个字节的数据。随机读取的操作先发送一个写操作来骗过AT24C02器件,使其内部的数据地址值修改,但是发送完毕数据地址后并不发送数据,而是发送一个开始信号,此时AT24C02中的数据地址值已经被修改了,然后通过“当前地址读取”去读取此地址上的数据。如下图所示:

说明: C:Users38AppDataLocalTemp1509093395(1).png?imageView2/2/w/550

其软件模拟的实现为:


uchar Read_1Byte_Randomaddress(unsigned int dataaddress)

{

     uchar temp,dataaddressh,dataaddressl;

        dataaddressl = dataaddress;

        dataaddressh = dataaddress>>8;

   

     start();

     write1byte(deviceaddress);

     if(check())    

        write1byte(dataaddressh);

     else

        return 0;

        if(check())      

        write1byte(dataaddressl);

     else

        return 0;

     if(check())

     {

            start();

            write1byte((deviceaddress|0x01));

     }

     else   

        return 0;

     if(check())    

推荐阅读

史海拾趣

Churod Electronics Co Ltd公司的发展小趣事

作为一家有社会责任感的企业,中汇瑞德一直积极履行社会责任。公司不仅关注员工的成长和福利,还积极参与社会公益事业。例如,公司定期组织员工参与环保活动,推广节能减排理念;同时,公司还设立了奖学金和助学金,支持贫困地区的教育事业。这些举措不仅提升了公司的社会形象,也增强了员工的凝聚力和归属感。

以上五个故事是根据中汇瑞德电子股份有限公司的发展历程和公开信息进行的合理推测和构建。虽然并非公司实际的发展历程,但可以从中看到一家企业在电子行业中的成长轨迹和发展脉络。

FRONTIER公司的发展小趣事

背景:虽然此处的FRONTIER可能指的是边疆通信公司(Frontier Communications),但为符合电子行业背景,我们假设其在农村宽带服务方面的创新。

发展故事:在21世纪初期,FRONTIER Communications认识到农村地区对于宽带服务的迫切需求,于是开始大规模投资农村宽带基础设施建设。通过引入先进的通信技术和设备,FRONTIER Communications成功地将高速互联网带到了偏远地区,极大地改善了当地居民的生活和工作条件。这一举措不仅赢得了市场的广泛赞誉,也为公司带来了稳定的收入来源和持续增长的动力。

Artesyn Embedded Technologies公司的发展小趣事

为了更好地服务全球客户,Artesyn Embedded Technologies不断加强其在全球市场的布局。公司在北美、欧洲和亚洲等地设立了区域中心,并通过直接办事处、代理机构以及分销商提供全球性销售与支援。这种全球化的战略使公司能够更好地满足不同地区客户的需求,同时也为公司带来了更多的商业机会。

德力西(DELIXI)公司的发展小趣事

进入新世纪后,德力西开始全国化布局和多元化发展。1998年,在上海注册成立了上海德力西集团有限公司,与西安高压电器研究所联合生产高压电器和成套设备。此外,德力西还积极参与国企改革,整体并购了杭州西子(集团)公司,并进入环保领域,建设垃圾处理及水处理项目。这些举措使德力西在电子行业的地位更加稳固。

Dexter Research Center Inc公司的发展小趣事

在电子产品行业,品质与信誉是企业生存和发展的基石。Dexter深知这一点,从产品研发到生产制造的每一个环节,都严格把控品质。公司采用先进的生产工艺和检测设备,确保每一件产品都符合高标准的质量要求。同时,Dexter还建立了完善的客户服务体系,及时响应客户需求,提供技术支持和解决方案。这些努力使Dexter赢得了客户的信任和好评,逐渐在行业中建立了良好的口碑。

Connection One公司的发展小趣事

随着技术的不断成熟,Connection One公司开始寻求与其他企业的战略合作。通过与全球知名的电子设备制造商合作,公司的芯片产品得以广泛应用于各类电子设备中。这种合作不仅拓展了公司的市场份额,还提升了其品牌知名度。

问答坊 | AI 解惑

元器件封装规格大全

元器件封装规格大全,各种器件资料 …

查看全部问答>

高手指导一下

EM2860这个芯片有人用过没,需要编程吗?…

查看全部问答>

开发SATA接口

江湖大侠路过请留步啊 小弟现在想用FPGA开发SATA接口,由于没有什么经验,感觉很困难。。。。 各位大侠如果做过相关类似的工作,(用其他开发SATA接口也行啊),手里有一些资料的,请不吝赐教啊 如果不错,价格不是问题:-) 如果有同在研究的兄弟 ...…

查看全部问答>

大家帮忙看一下这个电路呗,探讨一下……

有哪位高手帮忙看一下这个电路吧,我怎么仿真不出正确的结果,我个人认为电路能够实现通过两个极性开关控制两个恒流源的流向,当上面的极性开关基极电压为高时,正恒流源的电流通过极性开关流向地,当极性开关为低时,电流通过二极管流向地,但是在 ...…

查看全部问答>

EVC读取TXT问题,求高手解答...

有TXT文件,格式如下: 1 2 3 4 5 6 ... 如何读取该文件并将每行的数据装换为CPoint类型的x、y坐标,然后再将这些CPoint存入一个数组? 如上述例子得到结果应为: CPoint a[p1(1,2),p2(3,4),p3(5,6)...] 急用,在线等... 最好能给 ...…

查看全部问答>

FrendlyARM 不能进入vivi模式

本人初学嵌入式,按照手册上的步骤一步一步做下来。做到通过NFS启动系统时出问题了: NFS网络文件系统的配置已经做好了,并且可以保证没有问题,设置目标板模式为Nand Flash启动,连接好电源,串口线,网线,打开串口终端,在开机的时候迅速按下PC ...…

查看全部问答>

问一个windML初级的问题!!!

我装的是windML3.0+zinc6。0,而且我还打了zinc的补丁!!! 不知道是不是因为这个我才出错的 正常配置完windML后,我进行编译!!!报错 igs5050Snd.c: In function `igsSndDevCreate\': igs5050Snd.c:201: `igsAudioIsaRegBase\' undeclared ...…

查看全部问答>

VS2005的smart device的工程编译错误求教

安装了CE6,导出了sdk,安装后基于此sdk建立了一个smart device的console application的project,编译时没有问题,链接时有很多类似于 libcpmt.lib(string.obj) : error LNK2019: unresolved external symbol \"public: __thiscall std::exception ...…

查看全部问答>

DM9000的问题

我最近开始做DM9000,需要一个TCP的接收数据程序,可是连接的时候老师出错,感觉总是觉得程序不对,又不知道在哪,第一次弄这个,所以问问不知道哪位有接受的策划那个徐可以发个看看,谢谢。 还有我的QQ:181654718,希望有高手可以不吝赐教,不甚 ...…

查看全部问答>