以I2C2为例子
硬件I2C不需要我们手动去翻转电平
首先配置I2C:配置GPIO,配置复用功能I2C,配置复用开漏,使能I2C。
I2C起始条件函数
/* * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: ENABLE or DISABLE.
*/
void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);
停止条件函数
/* * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: ENABLE or DISABLE.
*/
void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState);
收一个字节后,是否给从机应答
/* * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: ENABLE or DISABLE.
*/
void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState);
发数据函数,将数据写入dr寄存器中。
/* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param Data: Byte to be transmitted.
*/
void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);
接收数据函数,读取DR寄存器的数据,作为返回值,(移位寄存器传入数据寄存器)
/* * @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @retval The value of the received data.
*/
uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);
发送7位地址函数,原理和发送数据相同,都是将数据写入到DR寄存器中,不同的是它给出了一位读写位
/*1:接收,0:传送*/
void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction);
状态监控函数:用于确保某些操作是否完成
初始化:
/*初始化*/
//开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
//配置GPIO
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
I2C_InitTypeDef I2C_InitStructure;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//配置位i2c功能
I2C_InitStructure.I2C_ClockSpeed = 50000;//时钟速率,随便给,不超过阈值即可,数值越大,传输越快,《=400kHz
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;//时钟占空比,小于100khz,都是1:1
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//给应答
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//STM32作为从机的地址长度
I2C_InitStructure.I2C_OwnAddress1 = 0x00;//STM32作为从机的地址
I2C_Init(I2C2, &I2C_InitStructure);
//使能I2C
I2C_Cmd(I2C2, ENABLE);
写一个数据
void I2C_WaitEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
{
uint32_t Timeout;
Timeout = 10000;
while (I2C_CheckEvent(I2Cx, I2C_EVENT) != SUCCESS)
{
Timeout --;
if (Timeout == 0)
{
break;
}
}
}
void I3C_WriteReg(uint8_t RegAddress, uint8_t Data)
{
I2C_GenerateSTART(I2C2, ENABLE);//生成起始条件
MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);/*检测EV5事件发生
EV5事件:发送起始条件完成,其余的event事件均是同理*/
I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter);//发送七位地址
MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
I2C_SendData(I2C2, RegAddress);//发送寄存器地址
MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING);
I2C_SendData(I2C2, Data);//发送写入寄存器的数据
MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
I2C_GenerateSTOP(I2C2, ENABLE);//停止信号
}
读一个数据:
/*先写一个寄存器的地址,在读寄存器的数据 */
uint8_t I2C_ReadReg(uint8_t RegAddress)
{
uint8_t Data;
I2C_GenerateSTART(I2C2, ENABLE);
MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);
I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter);
MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
I2C_SendData(I2C2, RegAddress);
MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
I2C_GenerateSTART(I2C2, ENABLE);
MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);
I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Receiver);
MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);
I2C_AcknowledgeConfig(I2C2, DISABLE);
I2C_GenerateSTOP(I2C2, ENABLE);
MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED);
Data = I2C_ReceiveData(I2C2);
I2C_AcknowledgeConfig(I2C2, ENABLE);
return Data;
}