STM32 | 您所在的位置:网站首页 › stm32i2c从机 › STM32 |
目录 一丶I2C简介 二丶读写过程 (一)发送过程 (二)接收数据 三丶库函数 四丶代码部分及解析(使用了MPU6050观察实验现象) (一)I2C及MPU6050初始化部分 (二)主函数部分 一丶I2C简介 (1)由两条总线控制:一条双向串行数据线(SDA) ,一条串行时钟线 (SCL)。SDA用来发送数据,SCL用于数据收发同步。 (2)I2C总线上可挂在多个 I2C通讯的设备 (3)每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之间的访问。 (4)总线通过上拉电阻接到电源。当 I2C 设备空闲时,输出高阻态,而当所有设备都空闲,都输出高阻态,上拉电阻将总线拉成高电平。 (5)多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用总线。 (6)支持不同的通讯速度,标准速度(高达100 kHz),快速(高达400 kHz)支持DMA (7)同步,半双工 二丶读写过程 (1)发送过程(1)void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct); 初始化I2C (2)void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState); 使能I2C (3)void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState); void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState); 配合DMA使用 (4)void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState); void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState); 起始条件和终止条件 (5)void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState); 收到一个字节后是否给从机应答 (6)void I2C_OwnAddress2Config(I2C_TypeDef* I2Cx, uint8_t Address); 设置主机地址(STM32当从机使用时配置) (7)void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data); uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx); 发送数据和接收数据 (8)void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction); 发送从机地址(当然I2C_SendData也可以发送) (9)I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT); 检查应答位 四丶代码部分及解析(使用了MPU6050观察实验现象) (一)I2C及MPU6050初始化部分 #include "stm32f10x.h" // Device header #include "MPU6050_Reg.h" #define MPU6050_ADDRESS 0xD0 void MPU6050_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); //开启GPIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启I2C时钟 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); //初始化GPIO 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; //时钟占空比 I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //主机是否设置应答 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //主机地址位数 7位或10位 I2C_InitStructure.I2C_OwnAddress1 = 0x00; //主机地址(当STM32位从机时) I2C_Init(I2C2, &I2C_InitStructure); I2C_Cmd(I2C2, ENABLE); MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01); MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00); MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09); MPU6050_WriteReg(MPU6050_CONFIG, 0x06); MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18); MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18); } void MPU6050_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 MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data) { I2C_GenerateSTART(I2C2, ENABLE); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT); //检测EV5 I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter); //发送从机地址 MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //检测EV6(发送模式) I2C_SendData(I2C2, RegAddress); //发送从机寄存器地址 MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING); //检测EV8 I2C_SendData(I2C2, Data); //发送数据 MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED); //检测EV8_2 I2C_GenerateSTOP(I2C2, ENABLE); //停止发送 } uint8_t MPU6050_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); //检测EV6(接收模式) I2C_AcknowledgeConfig(I2C2, DISABLE); //主机给从机应答位A I2C_GenerateSTOP(I2C2, ENABLE); //接收数据时需要提前发送终止位 MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED); //检测EV7 Data = I2C_ReceiveData(I2C2); I2C_AcknowledgeConfig(I2C2, ENABLE); return Data; } uint8_t MPU6050_GetID(void) { return MPU6050_ReadReg(MPU6050_WHO_AM_I); } void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ) { uint8_t DataH, DataL; DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H); DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L); *AccX = (DataH |
CopyRight 2018-2019 实验室设备网 版权所有 |