IIC通信协议总结
通信协议中常用术语介绍:
通信类型:如串行异步全双工
异步:没有时钟线,一般配置相同的波特率(不发送数据块,而是一个一个字符发送)
同步:有相同的时钟线,不用考虑传输周期(要是协议最大范围之内的速率)(发送数据块给到另一端称之为同步,要求发送和接收方的时钟必须一致。)
全双工:同时可以收发(类似于电话)
半双工:可以收发,不能同时(类似于对讲机)
单工:只能收或只能发
串行:一次在一根线上发数据
并行:一次可以在很多线上同时发送数据
物理接口:物理上接线方式,如串口的RX,TX引脚
通信协议:如RS232,ModBus
(Modbus协议,从字面理解它包括Mod和Bus两部分,首先它是一种bus,即总线协议,和I2C、SPI类似,总线就意味着有主机,有从机,这些设备在同一条总线上。)
(总线(Bus)是计算机各种功能部件之间传送信息的公共通信干线,它是由导线组成的传输线束, 按照计算机所传输的信息种类,计算机的总线可以划分为数据总线、地址总线和控制总线,分别用来传输数据、数据地址和控制信号。总线是一种内部结构,它是cpu、内存、输入、输出设备传递信息的公用通道,主机的各个部件通过总线相连接,外部设备通过相应的接口电路再与总线相连接,从而形成了计算机硬件系统。在计算机系统中,各个部件之间传送信息的公共通路叫总线,微型计算机是以总线结构来连接各个功能部件的。)->通信用的通道,如古代驿站,可以划分为不同的功能,,数据总线,地址总线,控制总线。
IIC简介
IIC是IIC Bus简称,所以中文应该叫 集成电路总线
通信协议简介:IIC(Inter-Integrated Ciruit)是由PHILIPS(飞利浦)公司开发的两线式串行总线,用来连接微控制器(MCU)及外围设备了,它是由数据线SDA和时钟线SCL构成的串行总线,优点:简单性,有效性。由于接口直接在组件上,因此IIC总线占用的空间非常小,所用引脚少,降低了互联成本。总线长度可达25英尺(1英尺0.3米),并且能够以10Kbps的最大传输速率支持40个组件。根据器件的不同,可利用 DMA 功能来减轻 CPU 的工作量。多主模式功能:同一接口既可用作主模式也可用作从模式。除了接收和发送数据之外,此接口还可以从串行格式转换为并行格式,反之亦然。
通信方式:串行同步半双工通信
物理接口:一根SDA,一根SCL
通信速度:
发送字节格式:
通信时序:
起始、终止、应答、信号时序图:
IIC总线应答时序图:
起始信号(SCL为高电平时,SDA由高到低)产生后,每个周期的上升沿采样,下降沿允许数据改变。每次发完八个位(1字节)的数据之后,等待应答信号(接收端控制SDA为低电平)。
数据帧格式为:开始条件+设备地址+W/R+应答+数据+应答+ ...+停止位
程序示例代码
IIC初始化
//IIC初始化
void IIC3_Pin_Init(void)
{
//PA8----SCL---推挽输出
//PC9----SDA---开漏输出
RCC->AHB1ENR |=0x01<<0|0x01<<2;//端口时钟使能
GPIOA->MODER &=~(0x03<<16);
GPIOC->MODER &=~(0x03<<18);
GPIOA->MODER |=(0x01<<16);
GPIOC->MODER |=(0x01<<18);
GPIOA->OTYPER &=~(0x03<<8);//PB8推挽输出
GPIOC->OTYPER |=(0x01<<9);//PB9开漏输出
//总线在空闲状态
IIC3_SCL=1;
IIC3_SDA_OUT=1;
}
起始条件
void IIC3_Start(void)
{
IIC3_SCL=1;
IIC3_SDA_OUT=1;
Delay_us(1);//延时---起始条件的建立时间
IIC3_SDA_OUT=0;//---产生起始条件
Delay_us(1);//延时---起始条件的保持时间
IIC3_SCL=0; //---结束起始条件
}
停止条件
void IIC3_Stop(void)
{
IIC3_SDA_OUT=0;
IIC3_SCL=1;
Delay_us(1);//延时---停止条件的建立时间
IIC3_SDA_OUT=1; //---产生了停止条件
Delay_us(1);//延时---本次通信结束到下次通信开始的时间
}
主机发送应答信号
void IIC3_Send_Ack(uint8_t ack)
{
IIC3_SCL=0;
if(ack)//(主机准备数据)
IIC3_SDA_OUT=1;
else
IIC3_SDA_OUT=0;
Delay_us(2);//延时(数据稳定在数据线上)
IIC3_SCL=1;//(从机在时钟线上升沿从SDA上采集数据)
Delay_us(1);//延时(给时间从机读取数据)
IIC3_SCL=0;//方便后续的操作;防止意外产生了停止条件
}
主机读取应答信号
uint8_t IIC3_Revice_Ack(void)
{
uint8_t ack=0;
IIC3_SCL=0;//(从机准备数据)
IIC3_SDA_OUT=1;//读模式-----让输出电路与管脚断开!!!!!!!!!!
Delay_us(2);//延时(给时间从机准备数据并且数据稳定在数据线上)
IIC3_SCL=1;
Delay_us(1);//延时 (给时间主机读取数据)
if(IIC3_SDA_IN)//主机读取SDA线上的数据
ack=1;
IIC3_SCL=0;//方便后续的操作;防止意外产生了停止条件
return ack;
}
主机发送一个字节并读取一次应答信号
uint8_t IIC3_Send_Byte(uint8_t data)
{
uint8_t i=0;
for(i=0; i<8; i++)
{
IIC3_SCL=0;
if((data<<i)&0x80)//(主机准备数据)
IIC3_SDA_OUT=1;
else
IIC3_SDA_OUT=0;
Delay_us(2);//延时(数据稳定在数据线上)
IIC3_SCL=1;//(从机在时钟线上升沿从SDA上采集数据)
Delay_us(1);//延时(给时间从机读取数据)
}
IIC3_SCL=0;//方便后续的操作;防止意外产生了停止条件
return IIC3_Revice_Ack( );
}
主机读取一个字节并读取一次应答信号
uint8_t IIC3_Revice_Byte(uint8_t ack)
{
uint8_t i=0;
uint8_t data=0;
for(i=0; i<8; i++)
{
IIC3_SCL=0;//(从机准备数据)
IIC3_SDA_OUT=1;//读模式-----让输出电路与管脚断开!!!!!!!!!!
Delay_us(2);//延时(给时间从机准备数据并且数据稳定在数据线上)
IIC3_SCL=1;
data<<=1;//空出最低位来存储本次读取的
if(IIC3_SDA_IN)//主机读取SDA线上的数据
data |=1;//数据线上电平为高
Delay_us(1);//延时 (给时间主机读取数据)
}
IIC3_SCL=0;//方便后续的操作;防止意外产生了停止条件
IIC3_Send_Ack(ack);
return data;
}
头文件声明与宏定义
#define IIC3_SCL PAout(8)//PA8输出,使用了地址映射
#define IIC3_SDA_OUT PCout(9)//PC9输出
#define IIC3_SDA_IN PCin(9)//PC9输入
void IIC3_Pin_Init(void);
void IIC3_Start(void);
void IIC3_Stop(void);
uint8_t IIC3_Send_Byte(uint8_t data);
uint8_t IIC3_Revice_Byte(uint8_t ack);