STM32内部集成了硬件I2C收发电路,可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能,减轻CPU的负担
支持多主机模型
支持7位/10位地址模式
支持不同的通讯速度,标准速度(高达100 kHz),快速(高达400 kHz)
支持DMA
兼容SMBus协议
STM32F103C8T6 硬件I2C资源:I2C1、I2C2
SDA 和 SCL:与 GPIO 口复用,或重映射(引脚定义表)
SMBALERT:SMABus 专用(普通 I2C 不需要)
DATA register:将保存待发送或接收到的数据
数据移位寄存器:按照高位先行,将数据移出
状态寄存器:记录数据发送和接收所产生的事件
控制寄存器:使能/失能,是否开启DMA/中断,I2C模式选择
EV5:起始条件已发送
EV6:地址已发送
EV7:已接收到数据(DR寄存器非空)
EV7_1:接收结束
EV8:正在发送数据(DR寄存器空,移位寄存器非空)
EV8_1:可写入DR寄存器(移位、DR寄存器空)
EV8_2:发送结束
void I2C_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
I2C_InitTypeDef I2C_InitStructure;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_ClockSpeed = 50000;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_OwnAddress1 = 0x00;
I2C_Init(I2C2, &I2C_InitStructure);
I2C_Cmd(I2C2, ENABLE);
}
/* I2C_send
* @ param1 从机地址
* @ param2 待发送数据
* @ retval None
*/
void I2C_send(unsigned char ADDRESS, unsigned char DATA)
{
int Timeout;
I2C_GenerateSTART(I2C2, ENABLE);
Timeout = 10000;
while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS) {//WAIT EV5
Timeout --;
if(Timeout == 0) {
return ;
}
}
I2C_Send7bitAddress(I2C2, ADDRESS, I2C_Direction_Transmitter);
while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS);//wait EV6
//第一个字节
I2C_SendData(I2C2, DATA);
while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);//wait EV8
//最后一个字节
I2C_SendData(I2C2, DATA);
while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS);//wait EV8_2
}
/* I2C_receive
* @ param1 从机地址
* @ param2 发送的指令
* @ retval 接收的数据
*/
unsigned char I2C_receive(unsigned char ADDRESS, unsigned char DATA)
{
int result = 0x00;
I2C_GenerateSTART(I2C2, ENABLE);
while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);//WAIT EV5
I2C_Send7bitAddress(I2C2, ADDRESS, I2C_Direction_Transmitter);
while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS);//wait EV6
//最后一个字节
I2C_SendData(I2C2, DATA);
while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS);//wait EV8_2
//开始接收
I2C_GenerateSTART(I2C2, ENABLE);
while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);//WAIT EV5
//地址
I2C_Send7bitAddress(I2C2, ADDRESS, I2C_Direction_Receiver);
while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS);//wait EV6
I2C_AcknowledgeConfig(I2C2, DISABLE);
I2C_GenerateSTOP(I2C2, ENABLE);
while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS);
result = I2C_ReceiveData(I2C2)
I2C_AcknowledgeConfig(I2C2, ENABLE);
return result;
}
/* I2C_GenerateSTART //生成终止条件
* @ param1 选择I2C通道
* @ param2 使能 / 失能
* @ retval None
*/
void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);
/* I2C_GenerateSTOP //生成起始条件
* @ param1 选择I2C通道
* @ param2 使能 / 失能
* @ retval None
*/
void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState);
/* I2C_SendData //发送一字节数据
* @ param1 选择I2C通道
* @ param2 待发送数据
* @ retval None
*/
void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);
/* I2C_ReceiveData //接收一字节数据
* @ param1 选择I2C通道
* @ retval 接收到的数据
*/
uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);
/* I2C_Send7bitAddress //发送地址
* @ param1 选择I2C通道
* @ param2 7位地址
* @ param2 接受地址 / 发送地址
* @ retval None
*/
void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction);
/* I2C_AcknowledgeConfig //ACK应答位设置
* @ param1 选择I2C通道
* @ param2 使能 / 失能
* @ retval None
*/
void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState);
/* I2C_CheckEvent
* @ param1 选择I2C通道
* @ param2 选择监视的事件
* @ retval None
*/
ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT);
+----------+ +----+
|时钟控制器 +---------------->|GPIO| SCL
一主多从模式 +----------+ | +------->
+----+
+---------------------------->+----+
+--|---------------+ |GPIO| SDA
| | | | |<------>
+----------+ | <<移位寄存器<< |<------------+----+
|数据控制器 +---->| | |
+----------+ | 数据寄存器DR |
CR | |
+------------------+
7位主发送:
+-+ +----+-+ +-----+-+-----+-+ +-----+-+ +-+
|S| |ADDR|A| |DATA1|A|DATA2|A| |DATAN|A| |P|
+-+---+----+-+---------+-----+-+---+-+-+--....---+-----+-+-----+-+
|EV5| |EV6|EV8_1| EV8 | |EV8| |EV8_2|
+---+ +---+-----+-----+ +---+ +-----+
7位主接收:
+-+ +----+-+ +-----+-+-----+-+ +-----+--+---+
|S| |ADDR|A| |DATA1|A|DATA2|A| |DATAN|NA| P |
+-+---+----+-+---+-----+-+---+-+-+---+ .... +-----+--+---+
|EV5| |EV6|EV6_1| |EV7| |EV7| |EV7_1| |EV7|
+---+ +---+-----+ +---+ +---+ +-----+ +---+
------ BY Flier
2023.9.3
Reference:江协科技、《stm32f10x用户手册》、《stm32库开发实战指南教程》