I2C时序介绍
1.起始信号
I2C通信的开始标志,告诉从机开始通信。
当信号线(SCL)信号线维持高电平时,数据线(SDA)由高变低。
2.停止信号
I2C通信停止信号,告诉从机停止通信。
当信号线(SCL)维持为高电平时,数据线(SDA)有低变高。
3.数据传输(一次传输一个字节,由字节高位开始传输)
数据传输时,必须保证数据线(SCL)保持高电平,并且数据线(SDA)稳定,要变化数据时,需将时钟线拉低。
4.应答信号
在数据传输完成(8位,一个字节)后,第九个时钟时,将数据线设置为输入,从机会发送一个应答信号,如果为低电平,为有效应答–通信成功。为高电平,为无效应答–通信失败。
I2C写时序
1.发送起始信号(告诉从机开始通信)
2.发送一个字节,高7位为设备地址,I2C可以通信多个从机,每个从机有个设备地址,选中该设备,最后一位是读写位,1是读:读取从机的数据。0是写:往从机里面写数据。
3.应答信号,写完一个字节后等待从机答复,看是否通信成功。
4.重新发送起始信号
5.发送一个字节,要写的寄存器地址
6.应答信号,写完一个字节后等待从机答复,看是否通信成功。
7.发送写入寄存器的数据
8.应答信号,写完一个字节后等待从机答复,看是否通信成功。
9,.停止信号,告诉从机通信完成。
I2C读时序
1.主机发送起始信号,告诉从机开始通信
2.发送一个字节,高7位为从机设备地址,最后一位是写信号,因为是向I2C从机发送数据,所以是写信号
3.等待从机应答
4.重新发送起始信号
5.发送要读取的寄存器地址
6.从机发送应答信号
7.重新发送起始信号
8.发送一个字节,高7位为要读取的设备地址,最后一位是读信号
9.从机发送应答信号
10.读取从机里面的信号
11.主机发送NO_ACK信号,表示读取完成,不需要从机发送ACK信号
12.主机发送停止信号,停止通信。
STM32F103RCT6例程
源文件:
#include "i2c.h"
//I2C起始信号
void I2C_Start(void)
{
I2C_CLK_Set();//时钟线维持高电平
I2C_SDA_Set();//数据线维持高电平
I2C_SDA_Clr();//数据线由高变低
I2C_CLK_Clr();//时钟线拉低
}
//I2C停止信号
void I2C_Stop(void)
{
I2C_SDA_Clr();//数据线维持低电平
I2C_CLK_Set();//时钟线维持高电平
I2C_SDA_Set();//数据线有低变高
}
//等待I2C从机应答 //低电平:通信成功 高电平:同行失败
uint8_t I2C_WaitAck(void)
{
I2C_CLK_Set();//时钟线维持高电平
I2C_CLK_Clr();//时钟线拉低
if(I2C_Read_SDA_Data()) //高电平无效应答
{
return 1;
}
else//低电平有效应答
{
return 0;
}
}
//I2C写一个字节 由高位开始写入 并且等待应答信号
void Send_Byte(u8 data)
{
uint8_t i;
for(i=0;i<8;i++)
{
I2C_CLK_Clr();//拉低时钟线,允许数据变化
if(data & 0x80) //一次判断最高位
{
I2C_SDA_Set();//数据线拉高
}
else
{
I2C_SDA_Clr();//数据线拉低
}
I2C_CLK_Set();//置高时钟线,发送数据
I2C_CLK_Clr();//拉低时钟线
data <<= 1; //数据左移一位,由高位依次写入
}
I2C_WaitAck(); //等待从机应答
}
头文件
#ifndef __OLED_H
#define __OLED_H
#include "stm32f10x.h"
//I2C端口定义
#define I2C_CLK_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_12)//SCL
#define I2C_CLK_Set() GPIO_SetBits(GPIOB,GPIO_Pin_12)
#define I2C_SDA_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_13)//SDA
#define I2C_SDA_Set() GPIO_SetBits(GPIOB,GPIO_Pin_13)
//读取引脚电平
#define I2C_Read_SDA_Data() GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)
#define u8 unsigned char
#define u32 unsigned int
void I2C_Start(void);//开始信号
void I2C_Stop(void);//停止信号
uint8_t I2C_WaitAck(void); //等待应答
void Send_Byte(u8 data);//发送一个字节
#endif