51单片机常用通信方式之IIC通信(二)

发布时间:2022-12-02 08:00

        IIC通信是一种同步通信方式,同步通信是采用一个同步时钟线,连到收发双方,使收发双方达到完全同步。则IIC通信硬件连接就有四根线VCC、GND、SDA、SCL,SDA是传送数据的,SCL是控制时序的,IIC它是有规矩的,用到这种通信方式,就得按照它的规矩来做,它才会听话,才能完成通信,也称为IIC通信协议。

IIC通信协议:

        IIC通信时,需要用到开始信号、停止信号、等待响应信号、发送字节信号、读取字节信号;

开始信号的条件:当SCL为高电平的时候,SDA线上由高到低的跳变被定义为起始条件;

结束信号的条件:当SCL为高电平的时候,SDA线上由低到高的跳变被定义为停止条件;

在设置这些高低电平时,可以在代码中直接设置,这个也叫软件(代码)模拟IIC通信;

IIC通信的起始信号和结束信号:

        当 SCL 线为高电平时,SDA 线由高到低的下降沿,为传输开始标志(S)。直到主设备 发出结束信号(P),否则总线状态一直为忙。结束标志(P)规定为,当 SCL 线为高电平 时,SDA 线由低到高的上升沿

51单片机常用通信方式之IIC通信(二)_第1张图片

 

IIC通信的应答信号:

        IIC 的数据字节定义为 8-bits 长度,对每次传送的总字节数量没有限制。对每一次传输 必须伴有一个应答(ACK)信号,其时钟由主设备提供,而真正的应答信号由从设备发出, 在时钟为高时,通过拉低并保持 SDA 的值来实现。

         如果从设备忙,它可以使 SCL 保持在低电平,这会强制使主设备进入等待状态。当从 设备空闲后,并且释放时钟线,原来的数据传输才会继续。 

51单片机常用通信方式之IIC通信(二)_第2张图片

IIC通信的接收数据信号和发送数据信号:

        开始标志(S)发出后,主设备会传送一个 7 位的 Slave 地址,并且后面跟着一个第 8 位,称为 Read/Write 位。R/W 位表示主设备是在接受从设备的数据还是在向其写数据。然 后,主设备释放 SDA 线,等待从设备的应答信号(ACK)。每个字节的传输都要跟随有一 个应答位。应答产生时,从设备将 SDA 线拉低并且在 SCL 为高电平时保持低。数据传输总 是以停止标志(P)结束,然后释放通信线路。然而,主设备也可以产生重复的开始信号去 操作另一台从设备,而不发出结束标志。综上可知,所有的 SDA 信号变化都要在 SCL 时钟 为低电平时进行,除了开始和结束标志。 

51单片机常用通信方式之IIC通信(二)_第3张图片 响应信号、发送字节信号,接收字节信号,我都会在代码中实现出来;

        此文章并没有实现任何的功能,只是把IIC底层驱动实现出来,你们用到IIC,完全可以把驱动利用起来,下篇文章,我教大家利用IIC实现和OLED屏幕的通信。

废话不多说,直接上图:

 IIC点C文件:

#include "iic.h"


//总线引脚定义
sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */
//延迟函数
void IIC_Delay(unsigned char i)//延时一段时间
{
  while(i--)
	{
		_nop_();
		_nop_();
	}		
}
//开始信号
void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;//当SCL为高电平的时候,SDA线上由高到低的跳变被定义为起始条件
    IIC_Delay(5);
    SDA = 0;
    IIC_Delay(5);
    SCL = 0;	
}

//停止信号
void IIC_Stop(void)
{
    SDA = 0;
    SCL = 1;//SCL为高电平的时候,SDA线上由低到高的跳变被定义为停止条件;
    IIC_Delay(5);
    SDA = 1;
    IIC_Delay(5);
}

//等待应答信号(作用很大)
bit IIC_WaitAck(void)
{
    bit ackbit;
	
    SCL  = 1;
    IIC_Delay(5);
    ackbit = SDA;
    SCL = 0;
    IIC_Delay(5);
    return ackbit;
}

//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
    unsigned char i;

    for(i=0; i<8; i++)
    {
        SCL  = 0;
        IIC_Delay(5);
        if(byt & 0x80) SDA  = 1;
        else SDA  = 0;
        IIC_Delay(5);
        SCL = 1;
        byt <<= 1;
        IIC_Delay(5);
    }
    SCL  = 0;  
}

//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
	unsigned char i, da;
	for(i=0; i<8; i++)
	{   
		SCL = 1;
		IIC_Delay(5);
		da <<= 1;
		if(SDA) da |= 1;
		SCL = 0;
		IIC_Delay(5);
	}
	return da;    
}

头文件

#ifndef _IIC_H
#define _IIC_H

#include "main.h"

void IIC_Start(void); 
bit IIC_WaitAck(void);  
void IIC_SendAck(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 

#endif

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号