我们从2011年坚守至今,只想做存粹的技术论坛。  由于网站在外面,点击附件后要很长世间才弹出下载,请耐心等待,勿重复点击不要用Edge和IE浏览器下载,否则提示不安全下载不了

 找回密码
 立即注册
搜索
查看: 1699|回复: 3

[技术文章] IIC接口AT24C02存储芯片的操作

[复制链接]

该用户从未签到

683

主题

98

回帖

3283

积分

二级逆天

积分
3283

终身成就奖社区居民忠实会员宣传大使奖

QQ
发表于 2016-3-5 16:23:56 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区

您需要 登录 才可以下载或查看,没有账号?立即注册

×
从今天早上开始看AT24C02的手册,凭着有些撮的英语水平,24页的资料,愣是啃了半天,上午的时光就过去了。
  AT24C02是一款EEPROM芯片,IIC接口,就是两条线:SDA与SCL;不过对于单单操纵这款芯片而言,没有设计到IIC总线协议之中所谓的仲裁。因而,大体看下了芯片手册,心中就知道大概怎么操作了。
  另外,24C02的2K是指2Kbit。一般的话,存储器都用字节来衡量,所以其实24c02只有256byte。是不是比较小?这256byte又分成了32pages,每页有8byte。
  现在来看看该如何编写代码,首先得知道起始与停止条件
       31184257-9afa97828829449390576039018abcb4.png                  
所谓起始条件:在SCL高电平期间,SDA的一个下降沿;
所谓停止条件:在SCL高电平期间,SDA的一个上升沿;
当然起始和停止条件与普通的位传送是不同的,位传送的时序如图所示
31184336-f7a5a5c582b2497a8f4ee8b7f8616d6f.png
可以看到,在SCL的高电平期间,SDA是不允许变化的;而只有在SCL的电平期间,SDA才能够出现变化;
当传输完1字节之后,可能需要有一个应答信号。说到这儿,就需要明白几个概念:发送器、接受器、主器件、从器件。
发送器:在总线上发送数据的器件。
接受器:在总线上接受数据的器件。
主器件:控制信息交互的器件,产生SCL时钟信息,产生起始与停止条件。
从器件:受从器件控制的器件。
那这儿的应答信号,就是总线上的接受器每接受到一个字节后产生的应答。如图所示:
31184415-28e356e22ac84da6bc7e0551f9f799d0.png
需要注意的是,在等待应答信号之前,需要将SDA置高,即释放掉总线。
24c02写的方式有两种:字节写、页写(就是连续写多个字节)。
掌握了字节写,对于页写就容易的多了。
字节写的时序如图所示:
31184510-0ce36f9ace744f908e431c501682718f.png
字节写的时序:首先是起始条件(由MCU产生),接着单片机向总线上传送器件地址,总线上地址相同的器件会有一个ACK(即应答信息),然后向器件写入字地址(告诉24c02想把信息写在那个地址,24c02刚好有256个字节,8bit的字地址信息刚好表示),同样会有一个应答信息,紧接着需要写入需要传送的数据(8位),同理会有一个应答信息。最后,需要主器件产生一个停止条件。Ok,写字节就结束了,是不是很简单,页写只不过是在这一步没有发送停止条件,而是接着发数据,这个时候24c02会知道你要写下一个字节,它会自动的加地址。
再来看看如何读取,读取有三种方式:当前地址读、随机读(我得承认这个名字不是太好)、顺序读。
当前地址读取是指你可以读取到芯片内部地址计数器(最近一次操作留下的值)加上1的地址上的值。看清楚是加上1地址上的值,不过不太明白有何用处。
接下来的随机读取跟是让我迷惑(刚看手册时候),随机的意思不就是产生一个无脑的地址,然后去读取,这样的话,读取有什么意义?不过我想错了,你可以看看时序图:
31184551-5dc74e3b01494189a772374fd3f28c71.png
看到了,先发写命令了,也传送了字地址,然后没有发写的内容。转而,重新开始发起始条件、器件地址(这次最后一位是读),然后再接受总线传送来的数据,此后主控器作为接受方,不用发应答信号,直接发一个停止条件,就ok了。
所以要想指定一个地址,就可以用随机读这个方法。不过随机读说法不太形象,改为指定地址读跟容易理解。
顺序读跟页写是对应的,只是在随机读或当前地址读后面接着接受数据。

写了三页,貌似不是很长。那就贴上代码,来充长。
个人喜欢写一个头文件,然后,再写一个c文件。
头文件部分:
#ifndef __hal_24c02_h__
#define __hal_24c02_h__

#include"reg52.h"
#include"hal.h"
#include"datatype.h"
#include"delay.h"

sbit scl=P3^7;//IIC时钟线
sbit sda=P3^6;//IIC数据线

#define SCL scl
#define SDA sda

//起始条件,SCL高电平时候,SDA的一个下降沿
#define HAL_24C02_START() {SDA=1;SCL=1;SDA=0;}
//停止条件,SCL高电平时候,SDA的一个上升沿
#define HAL_24C02_STOP() {SDA=0;SCL=1;SDA=1;}
#define HAL_24C02_BYTE_ADDR(addr) hal_24c02_send_char(addr)
#define HAL_24C02_ACK() hal_24c02_acknowledge(0)

void hal_24c02_init();
void hal_24c02_send_char(uchar val);
uchar hal_24c02_receive_char();
void hal_24c02_search_device(bit a2,bit a1,bit a0,bit rw);
void hal_24c02_acknowledge(bit mcu);

//学会使用以下两个函数即可
//需要注意写完之后,等待5ms之后,再去读取
void hal_24c02_byte_write(bit a2,bit a1,bit a0,uchar byte_addr,uchar byte_data);
uchar hal_24c02_byte_read(bit a2,bit a1,bit a0,uchar byte_addr);

#endif


C文件部分:
#include"hal_24c02.h"

//初始化,需将时钟线和数据线拉高
void hal_24c02_init()
{
         SCL=1;
         SDA=1;
}

//IIC协议要求从高位开始传送,传送1字节
void hal_24c02_send_char(uchar val)
{      
         uchar i;
         SCL=0;//此时,SCL被拉低,才允许SDA变化
         for(i=0;i<8;i++)
         {
                    if(val&(0x80>>i))
                           SDA=1;
                    else
                           SDA=0;
                   SCL=1;//拉高SCL,不允许SDA变化
                   delay_ms(1);
                   SCL=0;//拉低SCL,开始下1bit传送
         }
         //不包括应答脉冲,此时,SCL被拉低,SDA未被释放
         SDA=1;//释放数据线
         //SCL处于低电平;SDA处于高电平
}

uchar hal_24c02_receive_char()
{
          //SCL低电平 SDA高电平
          uchar tmp=0,i;
          for(i=0;i<8;i++)
          {
                 SCL=1;
                   if(SDA)
                            tmp=tmp|(0x80>>i);
                   SCL=0;
          }
          return tmp;
          //SCL低电平 SDA高电平
}

//a2、a1、a0:表示器件地址
//rw:1 代表读操作;0 代表写操作
void hal_24c02_search_device(bit a2,bit a1,bit a0,bit rw)
{
         uchar tmp;
         tmp=0xa0|(a2?0x08:0x00)|(a1?0x04:0x00)|(a0?0x02:0x00)|rw;
         hal_24c02_send_char(tmp);
}

//参数mcu=1,表示由主机主动产生应答信号,此时还需要将SDA拉低
//参数mcu=0,表示非主机参数应答信号,此时主机只需要产生SCL脉冲
//返回1:表示有应答;0:无应答
void hal_24c02_acknowledge(bit mcu)
{
         //SCL处于低电平;SDA处于高电平
         if(mcu)      SDA=0;//产生1应答信号
         SCL=1;
         delay_ms(1);
         while(SDA);//等待应答
         SCL=0;
         if(mcu)      SDA=1;//释放总线
         //SCL处于低电平;SDA处于高电平
}

//参数a2,a1,a0:器件地址
//参数byte_addr:字节地址
//参数byte_data:需要写的数据
void hal_24c02_byte_write(bit a2,bit a1,bit a0,uchar byte_addr,uchar byte_data)
{
          HAL_24C02_START()
          hal_24c02_search_device(a2,a1,a0,0);
          HAL_24C02_ACK();
          HAL_24C02_BYTE_ADDR(byte_addr);
          HAL_24C02_ACK();
          hal_24c02_send_char(byte_data);
          HAL_24C02_ACK();
          HAL_24C02_STOP()
}

//参数a2 a1 a0为器件地址;
//参数byte_char为需要读取的字节地址
//返回一个uchar型
uchar hal_24c02_byte_read(bit a2,bit a1,bit a0,uchar byte_addr)
{
          uchar val=0;
          HAL_24C02_START()
          hal_24c02_search_device(a2,a1,a0,0);//伪写
          HAL_24C02_ACK();
          HAL_24C02_BYTE_ADDR(byte_addr);//伪写的目的,就是为了传送地址
          HAL_24C02_ACK();
          HAL_24C02_START();
          hal_24c02_search_device(a2,a1,a0,1);//真读
          HAL_24C02_ACK();
          val=hal_24c02_receive_char();
          //NO ACK
          HAL_24C02_STOP()
          return val;
}
回复

使用道具 举报

  • TA的每日心情
    开心
    昨天 10:08
  • 签到天数: 107 天

    [LV.6]常住居民II

    69

    主题

    1万

    回帖

    2万

    积分

    三级逆天

    你必须非常努力才能显

    积分
    22139

    终身成就奖社区居民忠实会员社区劳模最爱沙发原创达人特殊贡献奖原创先锋奖优秀斑竹奖宣传大使奖

    QQ
    发表于 2016-3-6 05:00:57 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    35

    主题

    7586

    回帖

    1212

    积分

    二级逆天

    积分
    1212

    社区居民忠实会员社区劳模原创达人最爱沙发终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖

    QQ
    发表于 2016-3-6 05:56:19 | 显示全部楼层
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2024-6-14 16:03
  • 签到天数: 16 天

    [LV.4]偶尔看看III

    0

    主题

    1万

    回帖

    7618

    积分

    二级逆天

    积分
    7618

    终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖

    QQ
    发表于 2018-1-3 15:18:38 | 显示全部楼层
    回复

    使用道具 举报

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

    本版积分规则

    公告:服务器刚移机,
    大家请不要下载东西。
    会下载失败


    Copyright ©2011-2024 NTpcb.com All Right Reserved.  Powered by Discuz! (NTpcb)

    本站信息均由会员发表,不代表NTpcb立场,如侵犯了您的权利请发帖投诉

    ( 闽ICP备2024076463号-1 ) 论坛技术支持QQ群171867948 ,论坛问题,充值问题请联系QQ1308068381

    平平安安
    TOP
    快速回复 返回顶部 返回列表