基于51单片机IIC通信的AT24C02学习笔记

引言

最近在学习几种串行通信协议,感觉收获很多,这篇文章是学习IIC总线协议的第一篇文章,以后还会再写一篇关于PCF8591 IIC通信的ADDA转换芯片的文章.

关于IIC总线

IIC 即Inter-Integrated Circuit(集成电路总线),这种总线类型是由飞利浦半导体公司在八十年代初设计出来的一种简单、双向、二线制、同步串行总线,主要是用来连接整体电路(ICS) ,IIC是一种多向控制总线,也就是说多个芯片可以连接到同一总线结构下,同时每个芯片都可以作为实时数据传输的控制源。主要包括启始、停止、读、写、应答信号。这种方式简化了信号传输总线接口。

IIC总线上可以挂多个器件,而每个器件都有唯一的地址,这样可以标识通信目标。数据的通信的方式采用主从方式,主机负责主动联系从机,而从机则被动回应数据。

 

 

关于AT24C02

AT24C02是一个2K位串行CMOS E2PROM, 内部含有256个8位字节,CATALYST公司的先进CMOS技术实质上减少了器件的功耗。AT24C02有一个8字节页写缓冲器。该器件通过IIC总线接口进行操作,有一个专门的写保护功能。在单片机上的应用广泛, 可以实现掉电数据不丢失功能。

 

 

IIC总线数据有效性的规定

 

SCL=1期间,SDA必须保持稳定,SCL=0时,SDA才允许改变。

 

IIC 总线的几种信号

1.起始和终止信号:

 

 

从时序图可以看出,起始信号为,SCL=1,SDA下降沿;终止信号为SCL=1,SDA为上升沿,保持的时间是有限制的:

 

具体的程序实现如下:

起始信号:SDA=1保持时间大于4。7us,随后SDA=0保持时间大于4us

1
2
3
4
5
6
7
8
9
/*SDA下降沿*/
void  start()
{
SDA = 1;  //顺序不能反了,先是SDA=1;
SCL = 1;
delay();
SDA = 0;
delay();
}

终止信号:SDA=0保持时间大于4us,随后SDA=1保持时间大于4。7us

1
2
3
4
5
6
7
8
9
/*SDA上升沿*/
void  end()
{
     SDA = 0;         //顺序不能反了,先是SDA=0;
     SCL = 1;
     delay();
     SDA = 1;
     delay();
}

2.应答信号:

 

传送的每一个字节必须保证是8位长度。数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答信号(即一帧共有9位)。

如:主机往总线上发送一个字节的数据后,释放总线,从机会把总线拉低(即应答信号),以表示这一字节发送成功

同理主机从总线上读取完一个字节的数据后,主机会把总线拉低,"告诉"从机这一字节的数据接收成功

 

程序实现

应答信号:

1
2
3
4
5
6
7
8
9
void  ack()
{
     uchar i = 0;
     SCL = 1;
     delay();
     while (SDA == 1 && i < 250)i++;
     SCL = 0;             //SCL=0,SDA可以改变
     delay();
}

3.AT24C02的器件地址:

根据数据手册和原理图可以看出器件地址为:0x90/0x91其中最后一位是读写方向位,若下一个字节为向总线上发送数据,则为0x90,若下一个字节是从总线上读取数据,则为0x91。

4.往总线上写一字节的数据

程序实现:先写最高位,通过左移运算符,将一字节的数据一位一位的传送到总线上,其中CY存储的是左移后的进位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void  write_byte(uchar dat)
{
     uchar i;
     for (i = 0; i < 8; i++)
     {
         dat = dat << 1;           //如1011 0011 左移一位为0110 0110
         SCL = 0;             //SDL=0,才能往SDA送数据,或从SDA读数据
         delay();
         SDA = CY;                //上面左移后进位为1
         delay();
         SCL = 1;
         delay();
     }
     SCL = 0;
//      delay();
     SDA = 1;             //释放SDA
     delay();
}

 

5.从总线上读取一个字节的数据

程序实现:带返回值,先读高位,然后通过移位运算符,一位一位读入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
uchar read_byte()
{
     uchar dat = 0, tmp, i;
     SCL = 0;
     delay();
     for (i = 0; i < 8; i++)
     {
         SCL = 1;         //让SDA保持稳定,准备读取
         delay();
         tmp = SDA;         //读取此时SDA的状态
         dat = dat << 1;
         dat = dat | tmp;
         delay();
         SCL = 0;         //释放SDA总线,为下一次读取做准备
         delay();
     }
     return  dat;
}

AT24C02读写操作

1.通过以上几种信号的组合,可以向AT24C02指定单元地址写一字节的数据,可以看出,读写顺序为:起始,写器件地址,应答,写单元地址,应答,写数据,应答,终止。

程序实现:此函数无返回值,有两个形参, 内存单元地址,范围0-255;要写的数据,如0xfe;

1
2
3
4
5
6
7
8
9
10
11
void  write_AT24C02(uchar unit_addr, uchar dat)
{
     start();
     write_byte(AT24C02_ADDR + 0);     //下一个字节为写,所以是+0
     ack();
     write_byte(unit_addr);
     ack();
     write_byte(dat);
     ack();
     end();
}

  

 2.从AT24C02任意单元地址读取数据,可以看出读写顺序为:起始,写器件地址+0(下一个字节为写),应答,写单元地址,应答,起始,写器件地址+1(下一个字节为读取),读取数据,终止。

 

具体程序实现:此函数有返回值,一个形参;单元地址,范围:0-255;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
uchar read_AT24C02(uchar unit_addr)
{
     uchar dat;
     /*先写数据*/
     start();
     write_byte(AT24C02_ADDR + 0);       //下一个字节为写
     ack();
     write_byte(unit_addr);
     ack();
     start();
     write_byte(AT24C02_ADDR + 1);        //下一个字节为读
     ack();
     dat = read_byte();
     end();
     return  dat;
}

延时函数:

1
2
3
4
void  delay()         //短暂5us延时
{
     ;;
}

  

IIC初始化:

复制代码
void I2C_init()                //初始化
{
    SDA = 1;   
    delay();
    SCL = 1;   
    delay();
}
复制代码

 

具体应用

有了以上几个函数,我们就可以写主函数了, 功能是向内存单元211,写入数据0xae,然后在从内存单元211中读取出来,送给P1口led显示.注意:写完后要延时一会才能读取,否则不能成功读取.

1
2
3
4
5
6
7
void  main()
{
     write_AT24C02(211, 0xae);
     delay_10ms();                        //写完后,必须延时一定的时间才可以读取,否则不行
     P1 = read_AT24C02(211);
     while (1);
}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值