欢迎光临散文网 会员登陆 & 注册

IIC通信(解决各传感器怎么接线的问题)

2022-07-12 19:11 作者:甘第  | 我要投稿

讲到IIC通讯就顺便讲讲串口通讯吧(以前上FPGA课程的资料)

  • 处理器和外部设备通讯的两种方式(并行通信和串行通信)

    并行通信

      是指数据的各个位用多条数据线同时进行传输,传输速度很快,但是引脚资源占用较多

并行通信

       串行通信

            将数据分为一位一位的形式在一条数据线上逐个传输,传输速度慢,引脚占用少



  串行通信
  • 串行通信的通信方式:同步通信和异步通信

    同步通讯

    带时钟同步信号的数据传输;发送设备和接收设备在同一时钟的控制下,进行 同步传输数据

同步通讯
  • 异步通信

    不带时钟同步信号的数据传输,发送设备和接收设备使用各自的时钟控制数据 的发送和接收过程。


异步通信

常见的串行通信接口:UART、SPI、IIC(三大串行总线协议)


三大串行总线协议

 UART:(Universal Asynchronous Receiver-Transmitter:通用异步收发器) 功能:在发送数据时将并行数据转换成串行数据来传输,在接收数据时将接收到的串行 数据转成成并行数据。 协议层:通信协议(包括数据格式、数据传输速率等...) 物理层:接口类型、电平标准等...

协议层:通信协议(数据格式)


 SPI:(Serial Peripheral Interface:串行外设接口)**此处以FPGA芯片为例

 IIC:(Inter-Integrated Circuit:集成电路总线):半双工**此处以FPGA芯片为例


IICInter-Integrated Circuit)又称I2C(习惯读“I方C”),是IICBus简称,中文名为集成电路总线,它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展。适用于IC间的短距离数据传输。

IIC是单片机最常用的通讯方式之一,如果单片机需要扩展EEPROM存储芯片,就会用到IIC通信来读写EEPROM的数据。

除此很多传感器(如温湿度传感器,加速度传感器等)、外设(如OLED屏幕、LCD显示板等)也会采用IIC与单片机进行数据的传输。


硬件IIC:我们知道,STM32外设丰富,包括硬件级的IIC通信,也就是在其内部集成有专门用于IIC通信的硬件模块,只要在程序中配置相关的参数,就能启用该模块,再通过官方已经做好的库函数,就能很容易的实现IIC通信了。

但是由于STM32的硬件IIC存在着应答信号卡死的问题,所以很多开发者更喜欢使用软件模拟IIC通信。另外,软件模拟IIC还有方便移植到其他设备的优点。

IC物理接口:IIC串行总线有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上,属于一主多从总线。主机一次只能跟一个从机通信,如果要跟多个从机传输数据,则需要采用轮询的方式。通常会给SDA和SCL外接上拉电阻,确保无数据传输时,总线处于闲置状态。但是不接也可以,可以使用STM32的片内上拉电阻。

这两根线中,SCL是时钟线,用来同步时钟信号;SDA是数据线,用来传输数据。

 但对于软件模拟IIC,就没有任何限制,可以定义任意两个IO口分别作为SCL与SDA。

定义SCL与SDA的引脚,以及两个引脚置高、置低的函数。

#define IIC_SCL_H() GPIO_SetBits(GPIOA,GPIO_Pin_1) //定义SCL置高为PA1置位 #define IIC_SCL_L() GPIO_ResetBits(GPIOA,GPIO_Pin_1) //定义SCL置低为PA1复位 #define IIC_SDA_H() GPIO_SetBits(GPIOA,GPIO_Pin_2) //定义SDA置高为PA2置位 #define IIC_SDA_L() GPIO_ResetBits(GPIOA,GPIO_Pin_2) //定义SDA置低为PA2复位

延时函数:

void Delay_us(int Time) 

int i=0;

while(Time--) 

i=8;

 while(i--);

return; 

}

由于SDA需要在输入输出模式之间切换(等待应答时需要将PA2切换成输入模式),所以还要定义这两个函数。输出模式用推挽输出即可,输入模式采用上拉输入模式(如果总线外接了上拉电阻,采用浮空输入也可以)。

void SDA_OUT(void) //SDA输出模式 

{

GPIO_InitTypeDef GPIO_InitStructure; 

GPIO_InitStructure.GPIO_Pin= GPIO_Pin_2; 

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出模式 GPIO_Init(GPIOA, &GPIO_InitStructure); 

void SDA_IN(void) //SDA输入模式

GPIO_InitTypeDef GPIO_InitStructure; 

GPIO_InitStructure.GPIO_Pin= GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; //上拉输入模式 

GPIO_Init(GPIOA, &GPIO_InitStructure); 

}

起始信号:

void IIC_Start(void)

SDA_OUT(); //SDA切换至输出模式 

IIC_SDA_H(); //SDA置高 

IIC_SCL_H(); //SCL置高 

Delay_us(1);

IIC_SDA_L(); //SDA置低 

Delay_us(1); 

}

停止信号:

void IIC_Stop(void)

IIC_SCL_H(); //SCL置高 

IIC_SDA_L(); //SDA置低

Delay_us(1); 

IIC_SDA_H(); //SDA置高 

Delay_us(1); 

}

数据帧:

void IIC_WriteByte(u8 data) //发送一个数据串,data为要发送的数据

{

u8 i; SDA_OUT(); //SDA设置为输出模式 

for(i=0;i<8;i++) //循环发送,每次循环发送1bit,循环8次就是1Byte

{

IIC_SCL_L(); //SCL置低 

if(data & 0x80) //如果Data的第八位是高电平 

IIC_SDA_H(); //SDA置高

else IIC_SDA_L(); //SDA置低 

IIC_SCL_H(); //SCL置高 

Delay_us(1); //延时 

data<<=1; //data左移一位 

}

应答信号:

u8 IIC_Wait_Ask(void) 

int count=0; 

IIC_SCL_L(); //SCL置低 

Delay_us(1); //延时 

IIC_SDA_H(); //SDA置高 

SDA_IN(); //SDA切换成输入模式 

IIC_SCL_H(); //SCL置高 

Delay_us(1); //延时,等待从机发出应答信号 

while(Read_IIC_SDA) //如果SDA为低电平 

count++; //开始计数 

if(count>250) //计数超过250,则认为数据发送失败,从机无响应 

IIC_Stop(); //发出停止信号 

return 1; //函数返回1 

IIC_SCL_L(); //如果SDA为高电平,则认为收到应答,

SCL置低 Delay_us(1); 

return 0; //函数返回0 

}

文章参考:https://blog.csdn.net/qq_55203246/article/details/123944252


IIC通信(解决各传感器怎么接线的问题)的评论 (共 条)

分享到微博请遵守国家法律