找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 19564|回复: 4
打印 上一主题 下一主题
收起左侧

基于51的IIC通讯原理及协议详解(I2C)

  [复制链接]
跳转到指定楼层
楼主
ID:94349 发表于 2015-11-10 02:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
IIC 的一些特征:
两条总线:串行数据总线(SDA)和串行时钟总线(SCL)
真正的多主机总线
连接到相同总线的ic数量只受到总线的最大电容400pF限制。
串行8位双向数据在标准模式下可达100K bit/s
快速模式400K bit/s,高速模式下3.4Mbit/s.

数据有效性规定:
IIC总线在进行数据传输时,SCL在高电平区间,SDA上的电平必须保持稳定
SDA的数据的高或者低电平状态只有在SCL线的时钟信号是低电平时才能改变。

起始和停止条件:
起始:SCL高电平时,SDA由高电平向低电平切换。
停止:SCL高电平时,SDA由低电平向高电平切换。

模拟时序如下:
起始与终止:

应答与非应答:

总线上进行一次数据传输的通信格式:


相关模拟时序的驱动函数:包括(start,stop,respons,write_byte,read_byte)
-----------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------
//SCL高电平区间,SDA一个下降沿启动信号
void Start()
{
    SDA=1;
   delay();
    SCL=1;
   delay();
    SDA=0;
   delay();
}
-----------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------
//SCL在高电平区间,SDA一个上升沿停止信号
void Stop()
{
    SDA=0;
   delay();
    SCL=1;
   delay();
    SDA=1;
   delay();
}
-----------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------
//SCL在高电平区间,SDA被从设备拉低表示应答,
//(SDA==1)&&(i<255)表示如果一段时间未收到从期间
//的应答则默认从期间已经收到而不再等待应答信号
void Respons()
{
    uchari=0;
    SCL=1;
   delay();
   while((SDA==1)&&(i<255))
       i++;
    SCL=0;
   delay();   
}
-----------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------
//CY 为PSW寄存器中的CY位
//先移位,然互使用SCL控制发出去
void Write_Byte(uchar date)
{
    uchari,temp;
   temp=tada;
   for(i=0;i<8;i++)
    {
      temp=temp<<1;
       SCL=0;
      delay();
      SDA=CY;
      delay();
       SCL=1;
      delay();
    }
    SCL=0;
   delay();
    SDA=1;
   delay();
}

-----------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------
//定义临时变量K,K左移一位后与SDA进行或运算,
//依次把8个独立地位放入一个字节中来接受完成
void Read_Byte()
{
    uchari,k;
    SCL=0;
   delay();
    SDA=1;
   for(i=0;i<8;i++)
    {
       SCL=1;
      delay();
      k=(k<<1)|SDA;
       SCL=0;
      delay();
    }
   delay();
    returnk;
}
-----------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------
底层驱动完成以后,我们需要对实际的芯片使用通讯协议来进行操作。
目前大多的情况下一般比较受欢迎的是AT24cxx 系列。
AT24Cxx系列主要有:    以下系列:

以下仅以AT24C02为例来进行说明:
AT24C02芯片地址为:1010,其控制字格式如下:

其中A2,A1,A0为可编程选择地址,此处A2,A1,A0均接地,即000,
因此发送写信号的寻址字节为:10100000,即0XA0,
因此发送读信号的寻址字节为:10100001,即0XA1,

下图为写一个字节的数据格式,有图可知道:向AT24C02中写入一个字节的时候,需要:
先发一个起始信号,再发一个字节的控制字,
在发送一个字节的控制字地址,都得到应答信号后,
再发送要存入的数据,最后发一个停止信号!
So,一个字节的数据已经写入AT24C02中,OK!下面是数据格式,如图:

程序如下:
-----------------------------------------------------------------------------------------------------------------------
//任意地址,写入数据
void Write_Add(uchar address,uchar date)
{
   Start();

   Write_Byte(0xA0);
   Respons();
   Write_Byte(address);
   Respons();
   Write_Byte(date);
   Respons();

    Stop
}
-----------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------
下图为读一个字节的数据格式,其读取一个字节的数据和写入时候差不多,此处不再累赘,读一字节数据格式如图:

程序如下:
-----------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------
//任意地址,读出数据
void Read_Add(uchar address)
{
    uchardate;

   Start();
   Write_Byte(0XA0);
   Respons();
   Write_Byte(address);
   Respons();

   Start();
   Write_Byte(0XA1);
   Respons();
   date=Read_Byte();
   Stop();

    returnbyte;      
}
-----------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------


以上几位IIC的基本通讯时序的相关讲解,可参与时序图进行理解!!

评分

参与人数 3黑币 +15 收起 理由
SKYLAR123 + 5 赞一个!
muzhi + 5 很给力!
爱学习的陈先生 + 5

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏14 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:644141 发表于 2019-12-3 22:15 | 只看该作者
收藏了,谢谢。但还是有些不知道SDA=CY是什么意思?
回复

使用道具 举报

板凳
ID:342911 发表于 2019-12-12 00:30 | 只看该作者
很清楚的解释,多谢分享
回复

使用道具 举报

地板
ID:630001 发表于 2019-12-12 07:25 来自手机 | 只看该作者
写字节函数中的第二行是date变量,程序笔误了
回复

使用道具 举报

5#
ID:634190 发表于 2019-12-12 16:54 | 只看该作者
厉害,求指导
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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