【I²C协议】STC89C51单片机IIC通信(代码+原理)

什么是I²C协议

IIC,即I²C,全称 Inter-Integrated Circuit,字面上的意思是集成电路之间,它其实是I²C Bus简称,所以中文应该叫 集成电路总线 ,是由PHILIPS公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备。IIC属于半双工同步通信方式。

特点

  • 简单性和有效性

由于接口直接在组件之上,因此IIC总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件

  • 多主控(multimastering)

其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。

在这里插入图片描述

构成

IIC串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL,其时钟信号是由主控器件产生。所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。对于并联在一条总线上的每个IC都有唯一的地址。
在这里插入图片描述

通信协议

IIC总线在传输数据的过程中一共有三种类型信号,分别为:开始信号、结束信号和应答信号。

开始信号、结束信号、应答信号

要通信,总得先发个开始信号吧。就像你要和别人说话,总要先喊他一声一样。
如下图所示,
协议规定,当SCLK时钟信号一直处于高电平状态时,SDA线由高电平跳变到低电平这个动作,表示起始信号。注意此时就算SDA数据线的电平跳变完,SCLK线依然是高电平哦。
当连接在IIC总线上的外设模块检测到这个信号时,就知道数据要开始传输了。对于结束信号同理,协议规定,当SCLK时钟信号一直处于高电平状态时,SDA线由低电平跳变到高电平这个动作,表示结束信号。
在这里插入图片描述
应答信号:发送器每发送一个字节(8个bit),就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。 应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
在这里插入图片描述

数据传输

协议规定,在数据的传输过程中,SCLK为高电平时,外设模块开始采集SDA数据线上的数据,此时要求SDA数据线上的电平状态必须稳定(不然鬼知道这一位数据是0还是1),当SCLK为低电平时才允许SDA线上的数据跳变成另外一种状态。

引用别人,感觉讲的很好
现在,我想传输1bit数据,该位数据为1,从上文知道,我们在发完开始信号之后,此时SDA数据线的电平状态为低电平,SCLK信号依然是高电平。难道这个时候外设就要开始读取数据了吗?这显然不是的,从发完开始信号到真正的数据传输之间,会有一段缓冲时间,让我们去准备数据,在准备数据阶段,先将SCLK信号拉低一段时间,在这期间将SDA数据线拉高一段时间(即数据1),然后再将SCLK信号拉高,此时这个时钟信号的高电平被外设检测到的话,外设就知道要读取数据了,从而SDA上的数据就会被外设读到了。依次类推,传输下一位数据。
在这里插入图片描述
在主机传完一个字节的数据之后,就应该释放总线(协议规定,当SDA和SCLK同时为高时,表示空闲状态)然后把SDA数据线连接的IO口从输出模式转换成输入模式,这样才能拿到SDA数据线上的应答信号。这样,一个字节的数据就从主机到外设传输完毕了。

器件地址 在模块手册上会有注明

代码示例

使用STC89C51单片机

#include "reg52.h"
#include "intrins.h"

sbit scl = P0^1;
sbit sda = P0^3;

void IIC_Start()
{
	sda = 1;
	scl = 1;
	_nop_();
	sda = 0;
	_nop_();
}

void IIC_Stop()
{
	sda = 0;
	scl = 1;
	_nop_();
	sda = 1;
	_nop_();
}

char IIC_ACK()
{
	char flag;
	sda = 1;//就在时钟脉冲9期间释放数据线
	_nop_();
	scl = 1;
	_nop_();
	flag = sda;
	_nop_();
	scl = 0;
	_nop_();
	
	return flag;
}

void IIC_Send_Byte(char dataSend)
{
	int i;
	
	for(i = 0;i<8;i++){
		scl = 0;//scl拉低,让sda做好数据准备
		sda = dataSend & 0x80;//1000 0000获得dataSend的最高位,给sda
		_nop_();//发送数据建立时间
		scl = 1;//scl拉高开始发送
		_nop_();//数据发送时间
		scl = 0;//发送完毕拉低
		_nop_();//
		dataSend = dataSend << 1;
	}
}


void main()
{
		int a = 10;
	
		IIC_Start();

}

本人参考学习地址:http://t.csdnimg.cn/6o9tE

  • 18
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值