STM32自学笔记(三)——I2C

一、I2C通信模型

1、I2C总线之间的连接方式为:时钟线与时钟线连接,数据线与数据线连接;

2、在同一条I2C通信总线上,只存在且必须从在一个主机,可以存在多个从机,即为一对多的通信模式;

3、每个连接到总线的器件都可以通过唯一的地址器件和其它器件通信,主机/从机角色和地址可以配置,主机可以作为主机发送器或者主机接收器;

4、传输速率在标准模式下可达100kbps,快速模式下可达400kbps;

5、连接到总线的IC数量只受到总线的最大负载电容400pF限制;

6、在主机的SCL和SDA上都有一个上拉电阻,所以初始状态时两条线都是高电平;

7、在同一条I2C通信总线上,如果存在多个MCU/CPU,那么必须由程序员决定是哪一个MCU/CPU为主机,其他的都为从机,并且,在I2C总线上作为从机的MCU/CPU必须支持从模式I2C协议,这个问题特别在多机通信的系统中尤其注意;

8、I2C通信时,数据先发高位后低位。

二、I2C总线的特点

1、两条数据线,SDA(串行数据线)与SCL(串行时钟线);

2、7位或10位多位寻址模式;

3、每个连接到总线上的器件地址由芯片内部硬件电路和外部地址同时决定,避免了片选线的线连接方法,并建立简单的主从关系,主器件提供接收和发送所必须的时序;

4、I2C是真正的多主机总线,如果两个或更多主机同时请求总线,可通过冲突检测和仲裁防止总线数据被破坏;

5、同步时钟允许器件以不同的数据传输率进行通信。

三、I2C的协议层

(1)数据的有效性

        在时钟的高电平周期内,SDA线上的数据必须保持稳定,数据线仅可在时钟SCL为低电平时改变。

(2)起始和结束条件

        起始条件:当SCL线为高电平时,SDA线上由高到低的跳变被定义为起始条件;结束条件:当SCL线为高电平时,SDA线上由低到高的跳变被定义为停止条件。总线在起始条件之后被视为忙状态,在起始条件之后被视为空闲状态。

(3)应答

        每当主机向从机发送完一个字节的数据,主机总是需要等待从机给出一个应答信息以确认从机是否成功收到数据。从机应答主机所需要的时钟仍是主机提供的,应答出现在每一次主机完成8个数据位传输后紧跟着的时钟周期。

(4)带有7位地址的数据格式

        在典型的I2C传输数据流中,数据由最高位在SCL的驱动下依次传输。在起始条件后,第一个字节由长度为7位的传输地址信息和长度为1位数据方向位组成。数据方向位为1表示主机请求从机数据,为0则表示主机将向从机输出数据。在随后的9个周期内,主机将等待从机的应答。

(5)仲裁

        I2C是多主机总线,每个设备都可以访问总线上的主机,但任一时刻只能有一个主机。仲裁事件发生在至少有两个从机设备同时向总线传输起始条件、尝试成为主机的时刻。赢得仲裁的设备将成为主机,其余设备将退出仲裁保持在空闲状态,直至下一次总线空闲后才能再次申请控制总线。

四、I2C的时序

1、起始信号

在SCL高电平,SDA由高跳变到低电平时为起始条件。

2、停止信号

 在SCL低电平,SDA由低跳变到高电平时为起始条件。

3、应答信号ACK:0

(1)主机发送应答

(2)主机接收应答

4、非应答信号NACK:1

(1)主机发送非应答信号

(2)主机接收非应答信号

5、主机发送1Byte数据

例如:发送1010 0101B

6、主机读取1Byte数据

例如:读取0101 1101B

 五、代码实现

1、产生I2C起始信号

void IIC_Start(void)
{
	SDA_OUT();     //sda线输出
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	delay_us(4);
 	IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
}

2、产生I2C停止信号

void IIC_Stop(void)
{
	SDA_OUT();//sda线输出
	IIC_SCL=0;
	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL=1; 
	IIC_SDA=1;//发送I2C总线结束信号
	delay_us(4);							   	
}

3、等待应答信号

u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	SDA_IN();      //SDA设置为输入  
	IIC_SDA=1;delay_us(1);	   
	IIC_SCL=1;delay_us(1);	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL=0;//时钟输出0 	   
	return 0;  
} 

4、产生ACK应答

void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}

5、不产生ACK应答

void IIC_NAck(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}

6、I2C发送一个字节

void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	SDA_OUT(); 	    
    IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1; 	  
		delay_us(2);   //对TEA5767这三个延时都是必须的
		IIC_SCL=1;
		delay_us(2); 
		IIC_SCL=0;	
		delay_us(2);
    }	 
} 

7、I2C读一个字节

u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
	{
        IIC_SCL=0; 
        delay_us(2);
		IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
		delay_us(1); 
    }					 
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}

8、IO方向设置

#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}

如果对寄存器操作不了解,可以看下这个博客,解释得很清楚。https://blog.youkuaiyun.com/csdner_0/article/details/80231877?ops_request_misc=&request_id=&biz_id=102&utm_term=GPIOB-%3ECRL%7C=(u32)8%3C%3C28&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-80231877.nonecase&spm=1018.2226.3001.4187https://blog.youkuaiyun.com/csdner_0/article/details/80231877?ops_request_misc=&request_id=&biz_id=102&utm_term=GPIOB-%3ECRL%7C=(u32)8%3C%3C28&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-80231877.nonecase&spm=1018.2226.3001.4187

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值