IIC总线使用详解

本文是用于个人学习记录,如有出错请多多指教!

                                          IIC总线

一、I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。

二、那什么是并行通信和串行通信?

(1)在微机系统中,CPU 与外部的基本通信方式有两种:

并行通信——数据各位同时传送;

串行通信——数据一位位顺序传送

图1 是这两种方式的示意图。一般快速设备之间采用并行通信,譬如CPU 与存储设备、存储器与存储器、主机与打印机等都采用并行通讯。并行通讯,有多少位数据就必须有多少根数据线,如下图是11 位数据就有11 根数据线。串行通信最少可以只需一根通信线,只发或只收。因而大大节省了系统资源,降低了系统成本。由于只用一根数据线,所以是以降低传送速度来换取资源的,它常用在传送距离远,速度要求不高的场合

(一条信息的各位数据被同时传送的通讯方式称为并行通讯.并行通讯的特点是:各数据位同时传送,传送速度快、效率高,但有多少数据位就需多少根数据线,因此传送成本高,且只适用于近距离(相距数米)的通讯.

一条信息的各位数据被逐位按顺序传送的通讯方式称为串行通讯.串行通讯的特点是:数据位传送,传按位顺序进行,最少只需一根传输线即可完成,成本低但送速度慢.串行通讯的距离可以从几米到几千米)

(2)串行通信的传送方式通常有3 种:

全双工、半双工及单工通讯: 以公路来类比,全双工的通讯就是一个双向车道,两个方向上的车流互不相干;半双工则像乡间小道那样,同一时刻只能让一辆小车通过,另一方向的来车只能等待道路空出来时才能经过;而单工则像单行道,另一方向的车辆完全禁止通行。

IIC就是半双工通信。

三、那么什么是同步通信与异步通信呢?

同步通讯与异步通讯: 根据通讯过程中是否有使用到时钟信号进行简单的区分。

同步通讯中,收发设备双方会使用一根信号线表示时钟信号,在时钟信号的驱动下双方进行协调,同步数据

异步通讯中,不使用时钟信号进行数据同步,它们直接在数据信号中穿插一些同步用的信号位,或者把主体数据进行打包,以数据帧的格式传输数据

  简单来说,同步通信是要求发收双方具有同频同相的同步时钟信号,双方使用频率一致的时钟,它的分组相比异步则大得多,称为一个数据帧,通过独特的bit串作为启停标识。发送方要以固定的节奏去发送数据,而接收方要时刻做好接收数据的准备,识别到前导码后马上要开始接收数据了。

异步通信在发送字符时,所发送的字符之间的时隙可以是任意的,双方可以有各自自己的时钟,传输通常是很小的分组,比如一个字符为一组,接收端必须时刻做好接收的准备,发送端可以在任意时刻开始发送字符,因此必须在每一个字符的开始和结束的地方加上标志,即加上开始位和停止位,以便使接收端能够正确地将每一个字符接收下来。(接收方是在数据的起始位和停止位的帮助下实现信息同步的)

优点:同步通信效率更高,更加适合对速度要求高的传输。

          异步通信通信设备简单、便宜,但传输效率较低。

四、通讯速率

时钟频率与数据传输率是如何对等的喃。因为一个SCL时钟周期只能传输1bit数据(并且只能在SCL的低电平期间进行SDA数据电平的变化),假如SCL的时钟频率为100KHz,那么1s中就能产生100K个SCL时钟周期,也就是说1s中可以传输100Kbit的数据。此时,可以看出时钟频率100KHz与数据传输率100Kbit/s就是一样的了。

         IIC传输位速率在标准模式下可达100Kbit/s,快速模式下可达400Kbit/s,高速模式下可达3.4Mbit/s;也可以理解为时钟频率在标准模式下可达100kHz,快速模式下可达400kHz,高速模式下可达3.4MHz。

eg:现在我需要通讯每秒传输速率200Kbit,那么我时钟频率得多少?

理论上计算:不计算起始与停止与应答时间,单单一个字节计算,每秒200Kbit即1秒钟需要200K个时钟周期(一个周期传输一个位),200K*T = 1s,即T = 5us  f = 1/5 =   200KHZ

所以要决定传输速率需求,我除了计算SCK周期还得知道从机的通讯能达到多少,如下图

 我是随便截图一个SPI的,IIC也是一样,只是我们注意时钟频率极限值

(1)通常以比特率(Bitrate)来表示,即每秒钟传输的二进制位数,单位为比特每秒(bit/s),单位bps/s((b,是“每”的意思,每秒传输多少位)

单位区别:

计算机中的信息都是二进制的0和1来表示,其中每一个0或1被称作一个位,用小写b表示,即bit(位);大写B表示byte,即字节,一个字节=八个位,即1B=8b;前面的大写K表示千的意思,即千个位(Kb)或千个字节(KB)。表示文件的大小单位,一般都使用字节(KB)来表示文件的大小。

Mbps 即 Milionbit pro second(百万位每秒);

Kbps 即 Kilobit pro second(千位每秒);

bps 即 bit pro second(位每秒)

进制:1Milionbit=1024Kilobit=1024*1024bit;2^10

这是通常用来衡量带宽的单位,指每秒钟传输的二进制位数;

而通常软件上显示的速度则是指每秒种传输的字节数(Byte)通常用B(大写)表示;

MB即百万字节也称兆字节;
KB即千字节;

B即字节;

之间关系为1MB=1024KB=1024*1024B;

所以:KBps和Kbps是完全不同的概念

bit一般用于网络速度的描述和各种通信速度中。
Byte用于计算硬盘、内存的大小

举个例子:我们经常说网线宽带:

1M带宽 = 1Mbps = 1000Kbps = 1000/8KBps = 125KBps;

所以就有了我们常说的 1M的带宽下载的速度一般不会超过125KB每秒

(2)波特率

波特率 波特率指数据信号对载波的调制速率,它用单位时间内载波调制状态改变次数来表示,其单位为波特(Baud)

注意:单位问题

首先先来说下 为什么串口通信中描述通信速率时用到了波特率,其单位都写成比特率的单位,波特率明明有自己的单位baud但为什么要用比特率的单位?

那这就得说下波特的定义,波特定义指的是:单位时间传送的码元个数

那什么是码元?一个数字脉冲就是一个码元。通俗的理解,电路传输信号是靠波形的变化来识别每一位(英文单位bit)信息的,那么这一位信息的波形就叫作码元。

比特:是英文的bit音译过来的,信息的度量单位。bit的意思是位,即一位信息,当用二进制0和1表示数据时,0是一位,1也是一位,就是1bit。

所以说当一个码元表示了一位信息,波特就等于比特。
也就是说:码元是二进制的,即波形有两种,就只能表示0和1,也就是说一个码元只能表示一位(0或1)。

  比特率在数值上和波特率有这样的关系:

  波特率与比特率的关系为:比特率=波特率X单个调制状态对应的二进制位数。

  I=S*log2(N)

  [1]其中I为传信率,S为波特率,N为每个符号负载的信息量,以比特为单位。

所以假设:波特率是600baud,若码元是二进制的,比特率是600bps I = 600*log2(2) = 600bps

所以这就是在串口通信中,大家会以波特率600bps写,因计算机是以二进制计算。

那什么时候不等?

一个码元表示多位信息的时候。

如果波形是四进制的,那么波形有四种,就能表示00 01 10 11四种数据,每一个码元就携带了两位的信 息。 依次类推,八进制的码元就能携带3位信息。

波特率是600baud,若码元是八进制的,比特率就是1800bps(因为一个码元携带了三位信息)。

(3)波特率与字节传输速率计算

特率115200 = 115200 (位/秒)

如果没有校验位,就应该除以 10,得到的是每秒字节数:
波特率115200bps = 115200 (位/秒) = 11520 Bps(字节/秒)

再除以 1024,就是每秒 KB 数:
传输速率 11520Bps/1024 = 11.25 KBps(KB/秒)

(4)IIC通讯速率

IIC传输位速率在标准模式下可达100Kbit/s,快速模式下可达400Kbit/s,高速模式下可达3.4Mbit/s

IIC协议中涉及到两根线:SCL与SDA。SCL就是时钟信号线,SCL线上的频率就叫时钟频率。在对IIC总线进行学习与使用时,经常会听到设置IIC的时钟频率为xxxHz,或者设置IIC的数据传输率为xxxKbit/s。明明概念里可以进行配置的只有一个时钟频率,那么这个数据传输率这位老兄是怎么个情况。

其实,时钟频率(Hz)与数据传输速率(bit/s)两者是相同的概念。

         时钟频率与数据传输率是如何对等的喃。因为一个SCL时钟周期只能传输1bit数据(并且只能在SCL的低电平期间进行SDA数据电平的变化),假如SCL的时钟频率为100KHz,那么1s中就能产生100K个SCL时钟周期,也就是说1s中可以传输100Kbit的数据。此时,可以看出时钟频率100KHz与数据传输率100Kbit/s就是一样的了。

频率和周期的关系是:f=1/T。

我们可以计算一下100KHz的时钟速率对应的一个周期的时间为多少:

T= 1/f = 1/100 000 = 0.00001S = 10us。

1/10us = 100K,等于1s中就能产生100K个SCL时钟周期,1s中可以传输100Kbit

根据我们规定,在时钟信号为高电平期间,数据线上数据必须保持稳定,只有时钟拉低期间,数据线上才允许高低电平发生变化。

因为IIC标准模式速率100Kbit/s,据我们上一句所讲只有时钟拉低才允许数据脚变化,也就是没一个时钟周期就会有一位数据,所以1s中可以传输100Kbit数据时就等于有1s中有100K时钟周期,那一个时钟周期时间 = 1/100k = 10us,所以呢就有了我们常看到的单片机IO模拟IIC通讯延时delay(5)操作。即

三、IIC总线结构

IIC总线由SDA和SCL,两条线构成,可发送可接收。一个主机可连接多个从设备。

SDA、SCL需要接上拉电阻,总线空闲状态下均保持高电平,而连接到总线的任意从设备输出低电平都将会使总线变低。

在电路中添加了R63和R64两个上拉电阻,常用的上下拉电阻值大多选取在1K到10K之间,具体到底多大通常要根据实际需求来选,通常情况下在标准范围内就可以了,不是一个固定的值。在实际的应用中,对于5V系统的单片机,通常选择4.7KΩ的电阻作为上拉电阻;对于3.3V系统的单片机,通常选择10KΩ的电阻作为上拉电阻

四、通信格式

1.首先先讲下数据的有效性。IIC总线进行数据传输时,时钟信号(SCL)为高电平期间,数据线上的数据必须保持稳定;时钟信号(SCL)为低电平期间,才允许数据线上的数据产生高电平或者低电平变化。

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

3.启动信号

在IIC总线进行一次数据传输时,首先由主机发出启动信号。启动IIC总线。即在SCL高电平期间,SDA出现下降沿现象则为启动信号。

void IIC_Start() /

{

SDA_OUT();     //设为输出 

IIC_SCL=1;

 IIC_SDA=1;    

 delay_us(5);

 IIC_SDA=0;

 delay_us(5);

IIC_SCL=0;//钳住I2C总线,准备发送或接收数据,因为SCL位低允许数据判断变化

4.停止信号

在数据传输完毕后,主机发送停止信号。即SCL为高电平期间,SDA产生上升沿信号。

void IIC_Stop()

{

SDA_OUT();   //为什么要加输出,因为我们应答执行中设置为输入,应答后就要发结束信号,所以要设置输出

IIC_SCL=1;

IIC_SDA=0;

delay_us(5);

IIC_SDA=1;//发送I2C总线结束信号

delay_us(5);    //在加延时是为留时间给从机判断,如果在快速通讯情况下,stop后就要start

}

5.应答信号/非应答信号

IIC总线规定每传输一个字节(8位)后,都要有一个应答信号,来确定数据是否被对方接收到。应答信号由接收设备产生,在SCL为高电平期间,接收设备将SDA拉低,表示传输正确,产生应答。否则如果是SDA拉高,非应答信号。

应答信号由接收设备产生,在SCL为高电平期间,接收设备将SDA拉低,表示传输正确,产生应答。

//主机产生应答信号

ACKvoid IIC_Ack(void)
{
    IIC_SCL=0;
    SDA_OUT();
    IIC_SDA=0;//在SCL上升沿带来前,准备好SDA拉低
    delay_us(5);
    IIC_SCL=1;
    delay_us(5);
    IIC_SCL=0;
}

//主机不产生应答信号NACK   当主机为接受设备,主机对最后一个字节不应答,以向发送设备表示数据传输结束。

void IIC_NAck()
{

 IIC_SCL=0;

//SDA_OUT();

IIC_SDA=1;;//在SCL上升沿带来前,准备好SDA至高,表示没应答

delay_us(5);

 IIC_SCL=1;

delay_us(5);

 IIC_SCL=0;
}

产生应答就是在第九个时钟上升沿,判断SDA的高低,是高电平的话,就是接收没应答,是低就是接收产生了应答

遵循9个脉冲SCL,发送数据和读取数据完之后遵循9个脉冲,如上图

6.等待从机应答信号,我们只负责主机应答信号的产生,从机应答信号我们控制不了

//返回值:1 接收应答失败
                 0 接收应答成功

u8 IIC_Wait_Ack(void)
{
    u8 Time=0;

//注:以下是引脚模拟,没有设置开漏输出和挂上拉电阻

//第 8 个时钟下降沿后,从机主动把 SDA 拉低。直到检测到 SCL 来了上升沿,

    SDA_IN();      //SDA设置为输入 

    delay_us(5);  

    IIC_SCL=1; 读取SDA是都拉低,判断从机是否有应答
    while(GPIO_ReadInputDataBit((GPIOB,GPIO_Pin_7))//看自己定义那个引脚为数据脚
    {
        Time++;
        if(ucErrTime>250)
        {
            IIC_Stop();
            return 1;
        }
    }
    IIC_SCL=0;//时钟输出0    ,wei  
    return 0;  

IIC总线写入与读取数据是根据IIC的有效规定,即时钟信号(SCL)为高电平期间,数据线上的数据必须保持稳定;时钟信号(SCL)为低电平期间,才允许数据线上的数据产生高电平或者低电平变化。

6.写入一个字节

// 发送一个字节 

void IIC_Send_Byte(u8 txd)//32
{                        
    u8 t;   
    SDA_OUT();         
    IIC_SCL=0;//拉低时钟开始数据传输,允许该地变化
    for(t=0;t<8;t++)
    {              
        if((txd&0x80)>>7)//与1000 0000求取最高位,再右移7位,此时最高位在最低位上,从而判断是1还是0
            IIC_SDA=1;//是1  发送1 
        else
            IIC_SDA=0;
        txd<<=1;       //最高位出啊输完后,换下一位,所以左移1位      

       delay_us(5);   //数据准备好了
        IIC_SCL=1;//拉高时钟,从机读取数据
        delay_us(5); 
        IIC_SCL=0;    
 

    }     
}

7.读取一个字节

//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 IIC_Read_Byte(unsigned char ack)
{
    unsigned char i,receive=0;
    SDA_IN();//SDA设置为输入
  for(i=0;i<8;i++ )
    {
        IIC_SCL=0; 
        delay_us(5);
        IIC_SCL=1;       //根据数据有效性,时钟上升沿期间,数据保持稳定,所以这时候读取数据    
        receive<<=1;  
        if(GPIO_ReadInputDataBit((GPIOB,GPIO_Pin_7))receive++;           //看底下图片           
         delay_us(5); 
  }                     
    if (!ack)  //当主机为接受设备,主机对最后一个字节不应答,以向发送设备表示数据传输结束。
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   

    return receive;
  
}

 

 

Published by

风君子

独自遨游何稽首 揭天掀地慰生平