目录
1、I2C协议简介
2、IIC的结构
2.1、外部结构
2.2、stm32——IIC的内部结构(寄存器以及时钟等)
3、IIC的时序
编辑
4、stm32作为主机发送器的时序图(重点)
5、附上代码(还有不理解的可以评论)
I2C 通讯协议(Inter-Integrated Circuit)是由 Phiilps 公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要 USART、CAN 等通讯协议的外部收发设备(那些电平转化芯片),现在被广泛地使用在系统内多个集成电路(IC)间的通讯。
I2C只有一跟数据总线 SDA(Serial Data Line),串行数据总线,只能一位一位的发送数据,属于串行通信,采用半双工通信
半双工通信:可以实现双向的通信,但不能在两个方向上同时进行,必须轮流交替进行,其实也可以理解成一种可以切换方向的单工通信,同一时刻必须只能一个方向传输,只需一根数据线.
对于I2C通讯协议把它分为物理层和协议层物理层规定通讯系统中具有机械、电子功能部分的特性(硬件部分),确保原始数据在物理媒体的传输。协议层主要规定通讯逻辑,统一收发双方的数据打包、解包标准(软件层面)
摘采自博主:rivencode 原文链接:https://blog.csdn.net/k666499436/article/details/124686559
还是继续看这个图
主从机制:
区别:主机可以控制SCL(时钟线),也可以收发数据
从机也可以收发数据、但是只能读取SCL(时钟线)
原因:首先一些模块在使用的过程中,他并不需要在意自己什么时候收发数据,只需要
机械的进行收发数据操作,所以从机的出现就可以不用在意从机的时钟线
-------------------------------原因仅代表个人观点;个人看来应该是从设备以及控制方面来考虑的结果
怎么说呢,这个其实没什么好讲的,stm32芯片手册已经讲的很清楚的,我只是强调一下这个结构图的重要性而已;而且呢只有看明白这个图了,才会明白为什么要这样配置(ADC之类的这种结构体更重要)
IIC作为标准时序;标准的含义便是通用的,都知道的,固定的对吧??所以IIC的时序呢是不需要我们自己去设计也不能自己设计的;我们需要的是明白IIC的时序,在不同的状态SCL代表什么SDA怎么传输数据的
首先
咱们结合上面讲的IIC时序来理解stm32定义的IIC主发送器的序列图
首先 序列是发送的,事件均在stm32内部
s:起始条件
EV5:一个事件,代表要开始发送数据了
地址:从机的地址(准确来说应该是7位的从机地址加读写位(这个好像也没讲,就是代表你是接
收的还是发送的))
A:ACK应答位
EV6:地址发送完毕,而且应答了ACK
EV8_1:数据开始发送(不用我们捕获)
EV8:数据正在发送
p:停止条件
#include "stm32f10x.h" // Device header
#include "my_iic.h"
#define I2C_ADDRESS 0x78//我自己的设备地址
//发送一个数据
void my_send1(u8 addr, u8 data)
{
I2C_GenerateSTART(I2C2,ENABLE);
while(SUCCESS != I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C2,I2C_ADDRESS,I2C_Direction_Transmitter);
while(SUCCESS != I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(I2C2,addr);
while(SUCCESS != I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTING))
I2C_SendData(I2C2,data);
while(SUCCESS != I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C2,ENABLE);
}
void My_IIC_Init(void)
{
// 1. 时钟使能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); // 使能I2C2时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 使能GPIOB时钟
// 2. GPIO配置 (SCL在PB10,SDA在PB11)
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 开漏输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 3. I2C初始化
I2C_InitTypeDef I2C_InitStructure;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; // 标准模式
I2C_InitStructure.I2C_OwnAddress1 = 0x00; // 自己的I2C地址 (可根据需要修改)
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 50000; // 50kHz
I2C_Init(I2C1, &I2C_InitStructure);
// 4. I2C使能
I2C_Cmd(I2C1, ENABLE);
}