IIC通信协议笔记

参考优秀资料:

  1. IIC通信----基本原理-CSDN博客
  2. 通信协议——IIC协议_iic通信协议-CSDN博客
  3. 【通信协议】IIC通信协议详解-CSDN博客

IIC,中文名:集成电路总线;
![[Pasted image 20240909170412.png]]IIC是串行的,半双工的,多主多从的,同步通信总线;“同步”体现在IIC的主从设备共用一条SCL时钟线。
IIC总线一般有两根信号线:SDA数据线,SCL时钟线。
如上图所示,IIC有一个SDA总线(最上面那根),也有一个SCL总线,所有设备的SDA端都接到SDA总线上,所有设备的SCL端都接到SCL总线上。

IIC支持的传输速率如下:有5种
模式速率
标准模式(Standard Mode)100kb/s
快速模式(Fast Mode)400kb/s
增强快速模式(Fast Mode Plus1Mb/s
高速模式(High Speed Mode)3.4Mb/s
极速模式(Ultra-FastMode)5Mb/s
一般单片机是用标准模式。
IIC通信涉及到四种信号:

起始信号、数据信号、应答信号、终止信号;对应的是:起始位、数据传输位(固定是8bit)、应答位(ACK或者NACK)、终止位。

  1. 双高状态:SDA和SCL由于上拉电阻的作用都处于高电平状态
  2. 起始位:SCL为高电平,SDA由高电平转为低电平;启动信号是一种电平跳变时序信号,而不是一个电平信号。重点是时序,就是这个变化的过程
  3. 终止位:SCL为高电平,SDA由低电平转为高电平,终止信号是一种电平跳变时序信号,而不是一个电平信号。重点是时序,就是这个变化的过程
  4. 数据传输位:输出到SDA上的每个字节必须是8bit,先传输字节高位,后传输字节低位;这里SCL和SDA的时序需要重点注意:只有在SCL为低电平时,SDA才能允许发生高低电平的变化(数据变化),SCL为高电平时,SDA要稳定在一个状态
  5. 应答位:发送器每发送8bit的数据,就会在第9个时钟脉冲前释放SDA数据线(这个时候SDA不由发送器写入数据),由接收器反馈一个信号;如果要正确反馈ACK(表示接收到数据)的信号,就要:接收器在第9个时钟脉冲前的那个低电平期间,将数据线SDA拉低(低电平),在SCL为高电平期间,SDA稳定为低电平,这时就能正确反馈一个ACK应答信号;
  6. NACK信号:非应答信号,这时第九个时钟脉冲期间SDA为高电平,表示接收器没有成功接收该字节。
如果接收器是主控器(决定是否继续收发数据的器件),则它在收到最后一个字节数据后,会发送一个NACK信号,用来通知发送器结束数据的发送,并释放SDA线,以便后续终止信号的发送。

搭配代码理解:

#include "bsp_iic.h"

#define DELAY_TIME	5  // 这是用于延时的,会影响IIC的传输速率,默认就好

//
static void I2C_Delay(unsigned char n)
{
    do
    {
	    // _nop_()等效于汇编里面的NOP指令,也就是空一个机器周期
	    // 对于STC15F2K60S2单片机,一个机器周期为12个时钟周期,该单片机主频为12M
	    // 可以换算得1个机器周期就是1us;IIC通信要求读取一个有效位的时间要大于4us,
	    // 这里是满足的,注意看DELAY_TIME;2us*5=10us
        _nop_();_nop_();		
    }
    while(n--);      	
}

// 起始信号
void I2CStart(void)
{
	// 初始时,scl,sda均为高电平
    sda = 1;
    scl = 1;
	I2C_Delay(DELAY_TIME);
	// scl保持高电平,sda变为低电平:高变低
    sda = 0;
	I2C_Delay(DELAY_TIME);
	// scl变为低电平,准备数据传输
    scl = 0;    
}

//
void I2CStop(void)
{
	// 终止时,scl为高,sda由低变高
    sda = 0;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 1;
	I2C_Delay(DELAY_TIME);
}

//
void I2CSendByte(unsigned char byt)
{
    unsigned char i;

	// 数据传输,8bit,先传高再传低
    for(i=0; i<8; i++){
        scl = 0;
		I2C_Delay(DELAY_TIME);
        if(byt & 0x80){
            sda = 1;
        }
        else{
            sda = 0;
        }
		I2C_Delay(DELAY_TIME);
        scl = 1;
        byt <<= 1;
		I2C_Delay(DELAY_TIME);
    }

	// 传完后scl变0,等待ACK
    scl = 0;  
}

//
unsigned char I2CReceiveByte(void)
{
	unsigned char da;
	unsigned char i;

	// 设备接收数据,注意这里的SCL是要与发送端同步的;不能更改sda的值
	for(i=0;i<8;i++){   
		scl = 1;
		I2C_Delay(DELAY_TIME);
		da <<= 1;
		if(sda) 
			da |= 0x01;
		scl = 0;
		I2C_Delay(DELAY_TIME);
	}
	return da;    
}

//
unsigned char I2CWaitAck(void)
{
	unsigned char ackbit;
	// 等待应答信号,此时sda控制权不在自己手上,所以不能更改sda的值
    scl = 1;
	I2C_Delay(DELAY_TIME);
    ackbit = sda; 
    scl = 0;
	I2C_Delay(DELAY_TIME);
	
	return ackbit;
}

//
void I2CSendAck(unsigned char ackbit)
{
	// 发送响应位,和数据传输位思路类似
    scl = 0;
    sda = ackbit; 
	I2C_Delay(DELAY_TIME);
    scl = 1;
	I2C_Delay(DELAY_TIME);
    scl = 0; 
	sda = 1;
	I2C_Delay(DELAY_TIME);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值