赞
踩
目录
R/W:0写1读
十轴:3轴加速度,3轴角速度,3轴磁场强度和一个气压强度
MyI2C.c
- #include "stm32f10x.h" // Device header
- #include "Delay.h"
-
- /**
- * @brief 为I2C的SCL线写入数据
- * @param BitValue:要写入的数据
- * @retval 无
- */
- void MyI2C_W_SCL(uint8_t BitValue)
- {
- GPIO_WriteBit(GPIOB,GPIO_Pin_10,(BitAction)BitValue);
- Delay_us(10);//防止引脚反转速度过快,外设跟不上
- }
-
- /**
- * @brief 为I2C的SDA线写入数据
- * @param BitValue:要写入的数据
- * @retval 无
- */
- void MyI2C_W_SDA(uint8_t BitValue)
- {
- GPIO_WriteBit(GPIOB,GPIO_Pin_11,(BitAction)BitValue);
- Delay_us(10);//防止引脚反转速度过快,外设跟不上
- }
-
- /**
- * @brief 读取I2C的SDA线中的数据
- * @param 无
- * @retval SDA中的数据
- */
- uint8_t MyI2C_R_SDA(void)
- {
- uint8_t BitValue;
- BitValue = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);
- Delay_us(10);
- return BitValue;
- }
-
- /**
- * @brief 初始化GPIO引脚
- * @param 无
- * @retval 无
- */
- void MyI2C_Init(void)
- {
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
-
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//配置为开漏输出
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB,&GPIO_InitStructure);
-
- GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11);
- //将SCL与SDA初始置为高电平(空闲)
-
- }
-
- /**
- * @brief 开启I2C通信
- * @param 无
- * @retval 无
- */
- void MyI2C_Start(void)
- {
- MyI2C_W_SDA(1);
- MyI2C_W_SCL(1);
- //将两根线都置为高电平,准备开始时序
-
- MyI2C_W_SDA(0);
- MyI2C_W_SCL(0);
- //先将SDA拉低,再将SCL拉低形成起始条件
- }
-
- /**
- * @brief 终止I2C通信
- * @param 无
- * @retval 无
- */
- void MyI2C_Stop(void)
- {
- MyI2C_W_SDA(0);
- //确保SDA能产生上升沿,先进行拉低
-
- MyI2C_W_SCL(1);
- MyI2C_W_SDA(1);
- //在SCL处于高电平时,SDA产生上升沿形成终止条件
- }
-
- /**
- * @brief 使用I2C发送一个字节
- * @param Byte:发送的字节数据
- * @retval 无
- */
- void MyI2C_SendByte(uint8_t Byte)
- {
- uint8_t i;
- for(i = 0;i<8;i++)
- {
- MyI2C_W_SDA(Byte & (0x80 >> i));//取出最高位
- //即使进行运算后结果为0x80,写入的还是只有1
-
- MyI2C_W_SCL(1);//释放SCL进行发送
- MyI2C_W_SCL(0);//结束一次发送
- }
- }
-
- /**
- * @brief 使用I2C接收一个字节
- * @param 无
- * @retval 接收到的字节数据
- */
- uint8_t MyI2C_ReceiveByte(void)
- {
- uint8_t i,Byte = 0x00;
- MyI2C_W_SDA(1);//接收前需要先释放SDA
-
- for(i = 0;i < 8;i ++)
- {
- MyI2C_W_SCL(1);//SCL为高电平主机进行读取SDA上的数据
- if(MyI2C_R_SDA() == 1)//此时接收为1
- {
- Byte |= (0x80 >> i);//读到数据存入Byte
- }
- MyI2C_W_SCL(0);//拉低SCL完成一次读取
- }
- return Byte;
- }
-
- /**
- * @brief 主机接收完一个字节后发送应答
- * @param AckBit:应答位,0为应答,1为不应答
- * @retval 无
- */
- void MyI2C_SendAck(uint8_t AckBit)
- {
- //接收完成时SCL为低电平
- MyI2C_W_SDA(AckBit);
- MyI2C_W_SCL(1);//释放SCL进行发送
- MyI2C_W_SCL(0);//结束一次发送
- }
-
- /**
- * @brief 从机发送完一个字节后接收主机应答
- * @param 无
- * @retval 从机的应答值
- */
- uint8_t MyI2C_ReceiveAck(void)
- {
- //发送完成时SCL为低电平
- uint8_t AckBit;
- MyI2C_W_SDA(1);//接收前先释放SDA
- //这里主机输出1,并不是强制SDA为高电平,而是释放SDA
- //进行通信时,主机释放SDA,从机会暂时获得控制权
- MyI2C_W_SCL(1);//释放SCL进行接收
- AckBit = MyI2C_R_SDA();//进行读取SDA
- MyI2C_W_SCL(0);//结束一次接收
- return AckBit;
- }
MPU6050.c
- #include "stm32f10x.h" // Device header
- #include "MyI2C.h"
- #include "MPU6050_Reg.h"
-
- #define MPU6050_ADDRESS 0xD0
-
- /**
- * @brief MPU6050指定地址写数据进寄存器
- * @param RegAddress:写入寄存器位置
- * @param Data:写入寄存器数据
- * @retval 无
- */
- void MPU6050_WriteReg(uint8_t RegAddress,uint8_t Data)//指定地址写寄存器
- {
- MyI2C_Start();//开启I2C时序
- MyI2C_SendByte(MPU6050_ADDRESS);//从机地址加R(1)/W(0)
- MyI2C_ReceiveAck();//接收应答
- MyI2C_SendByte(RegAddress);//这个字节会存在MPU6050的当前地址指针中
- MyI2C_ReceiveAck();//接收应答
- MyI2C_SendByte(Data);//发送数据
- MyI2C_ReceiveAck();//接收应答
- MyI2C_Stop();//结束I2C时序
- }
-
- /**
- * @brief MPU6050指定地址读寄存器数据
- * @param RegAddress:寄存器位置
- * @retval 寄存器中存的数据
- */
- uint8_t MPU6050_ReadReg(uint8_t RegAddress)
- {
- uint8_t Data;
- //写的时序
- MyI2C_Start();//开启I2C时序
- MyI2C_SendByte(MPU6050_ADDRESS);//从机地址加R(1)/W(0)
- MyI2C_ReceiveAck();//接收应答
- MyI2C_SendByte(RegAddress);//这个字节会存在MPU6050的当前地址指针中
- MyI2C_ReceiveAck();//接收应答
-
- //读的时序
- MyI2C_Start();//再次开启I2C时序
- MyI2C_SendByte(MPU6050_ADDRESS | 0x01);//从机地址+读
- MyI2C_ReceiveAck();//接收应答
-
- //此时控制权由从机控制(主机接收一个字节数据)
- Data = MyI2C_ReceiveByte();//主机接收一个字节数据
- MyI2C_SendAck(1);//发送应答(如果需要接收多个字节应答就给0,结束则给1)
- //主机收回总线控制权
- MyI2C_Stop();
-
- return Data;
- }
-
- /**
- * @brief 初始化MPU6050
- * @param 无
- * @retval 无
- */
- void MPU6050_Init(void)
- {
- MyI2C_Init();
-
- MPU6050_WriteReg(MPU6050_PWR_MGMT_1,0x01);//配置电源管理寄存器1
- //解除睡眠模式,并选择使用X轴陀螺仪时钟
- MPU6050_WriteReg(MPU6050_PWR_MGMT_2,0x00);//配置电源管理寄存器2
- //六个轴均不待机
- MPU6050_WriteReg(MPU6050_SMPLRT_DIV,0x09);//配置分频寄存器(值越小越快)
- //十分频
- MPU6050_WriteReg(MPU6050_CONFIG,0x06);//配置寄存器,(外部同步+数字低通滤波器)
- MPU6050_WriteReg(MPU6050_GYRO_CONFIG,0x18);//陀螺仪配置寄存器(自测使能+满量程选择)
- MPU6050_WriteReg(MPU6050_ACCEL_CONFIG,0x18);//加速度计配置寄存器(自测+满量程配置+高通滤波器)
- }
-
- /**
- * @brief 获得芯片ID号
- * @param 无
- * @retval 芯片ID
- */
- uint8_t MPU6050_GetID(void)
- {
- return MPU6050_ReadReg(MPU6050_WHO_AM_I);//读取芯片ID号
- }
-
- /**
- * @brief 读取加速度以及角速度数据
- * @param AccX:X轴方向加速度
- * @param AccY:Y轴方向加速度
- * @param AccZ:Z轴方向加速度
- * @param GyroX:X轴方向角速度
- * @param GyroY:Y轴方向角速度
- * @param GyroZ:Z轴方向角速度
- * @retval 无
- */
- 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);//加速度X轴高八位
- DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);//低八位
- *AccX = (DataH << 8) | DataL;
-
- DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);//加速度Y轴高八位
- DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);//低八位
- *AccY = (DataH << 8) | DataL;
-
- DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);//加速度Z轴高八位
- DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);//低八位
- *AccZ = (DataH << 8) | DataL;
-
- DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);//加速度Z轴高八位
- DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);//低八位
- *GyroX = (DataH << 8) | DataL;
-
- DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);//加速度Z轴高八位
- DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);//低八位
- *GyroY = (DataH << 8) | DataL;
-
- DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);//加速度Z轴高八位
- DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);//低八位
- *GyroZ = (DataH << 8) | DataL;
- }
MPU6050_Reg.h(寄存器)
- #ifndef __MPU6050_REG_H
- #define __MPU6050_REG_H
-
- #define MPU6050_SMPLRT_DIV 0x19
- #define MPU6050_CONFIG 0x1A
- #define MPU6050_GYRO_CONFIG 0x1B
- #define MPU6050_ACCEL_CONFIG 0x1C
-
- #define MPU6050_ACCEL_XOUT_H 0x3B
- #define MPU6050_ACCEL_XOUT_L 0x3C
- #define MPU6050_ACCEL_YOUT_H 0x3D
- #define MPU6050_ACCEL_YOUT_L 0x3E
- #define MPU6050_ACCEL_ZOUT_H 0x3F
- #define MPU6050_ACCEL_ZOUT_L 0x40
- #define MPU6050_TEMP_OUT_H 0x41
- #define MPU6050_TEMP_OUT_L 0x42
- #define MPU6050_GYRO_XOUT_H 0x43
- #define MPU6050_GYRO_XOUT_L 0x44
- #define MPU6050_GYRO_YOUT_H 0x45
- #define MPU6050_GYRO_YOUT_L 0x46
- #define MPU6050_GYRO_ZOUT_H 0x47
- #define MPU6050_GYRO_ZOUT_L 0x48
-
- #define MPU6050_PWR_MGMT_1 0x6B
- #define MPU6050_PWR_MGMT_2 0x6C
- #define MPU6050_WHO_AM_I 0x75
-
- #endif
main.c
- #include "stm32f10x.h" // Device header
- #include "Delay.h"
- #include "OLED.h"
- #include "MPU6050.h"
-
- uint8_t KeyNum;
-
- int16_t AX,AY,AZ,GX,GY,GZ;
-
- int main(void)
- {
- OLED_Init();
-
- MPU6050_Init();
-
- OLED_ShowString(1,1,"ID:");
- OLED_ShowHexNum(1,4,MPU6050_GetID(),3);
-
- while(1)
- {
- MPU6050_GetData(&AX,&AY,&AZ,&GX,&GY,&GZ);
- OLED_ShowSignedNum(2,1,AX,5);
- OLED_ShowSignedNum(3,1,AY,5);
- OLED_ShowSignedNum(4,1,AZ,5);
- OLED_ShowSignedNum(2,8,GX,5);
- OLED_ShowSignedNum(3,8,GY,5);
- OLED_ShowSignedNum(4,8,GZ,5);
- }
-
- }
-
GPIO口需要配置为复用开漏输出模式。复用:就是GPIO的状态是交由片上外设来控制的,开漏输出,是I2C所规定的。
MPU6050.c
- #include "stm32f10x.h" // Device header
- #include "MPU6050_Reg.h"
-
- #define MPU6050_ADDRESS 0xD0
-
- /**
- * @brief 监控事件完成并延时退出
- * @param I2Cx:选择的I2C资源
- * @param I2C_EVENT:等待I2C完成的事件
- * @retval 无
- */
- void MPU6050_WaitEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
- {
- uint32_t TimeOut;
- TimeOut = 10000;
- while(I2C_CheckEvent(I2C2,I2C_EVENT) != SUCCESS)//等待Ev5事件完成
- {
- TimeOut -- ;
- if(TimeOut == 0)
- {
- break;
- }
- }
- }
-
- /**
- * @brief MPU6050指定地址写数据进寄存器
- * @param RegAddress:写入寄存器位置
- * @param Data:写入寄存器数据
- * @retval 无
- */
- 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);
- }
-
- /**
- * @brief MPU6050指定地址读寄存器数据
- * @param RegAddress:寄存器位置
- * @retval 寄存器中存的数据
- */
- uint8_t MPU6050_ReadReg(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_TRANSMITTED);//等待Ev8事件完成
-
- //读的时序
- I2C_GenerateSTART(I2C2,ENABLE);//生成重复起始条件
- MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT);//等待发送Ev5事件完成
- I2C_Send7bitAddress(I2C2,MPU6050_ADDRESS,I2C_Direction_Receiver);//发送从机地址并改为接收方向(自带接收应答)
- MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);//等待发送Ev6事件完成(接收)
-
- //清除响应和停止条件的产生位(在最后一个数据之前就要将Ack置零以及设置Stop终止条件)
- I2C_AcknowledgeConfig(I2C2,DISABLE);//设置Ack = 0,不给应答
- I2C_GenerateSTOP(I2C2,ENABLE);//配置停止位
- MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED);//等待发送Ev7事件完成
- //此时一个字节的数据以及存在DR中
-
- //读取DR即可获得字节
- Data = I2C_ReceiveData(I2C2);
-
- I2C_AcknowledgeConfig(I2C2,ENABLE);//方便接收多个字节
-
- return Data;
- }
-
- /**
- * @brief 初始化MPU6050
- * @param 无
- * @retval 无
- */
- void MPU6050_Init(void)
- {
- //开启对应时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,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 I2CInitStructure;
- I2CInitStructure.I2C_Mode = I2C_Mode_I2C;//I2C模式
- I2CInitStructure.I2C_ClockSpeed = 50000;//时钟速度(标准100 kHz,快速400 kHz)
- I2CInitStructure.I2C_DutyCycle = I2C_DutyCycle_2;//时钟占空比(>100kHz才有用)
- I2CInitStructure.I2C_Ack = I2C_Ack_Enable;//配置Ack位
- I2CInitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//Stm32作为从机能响应几位地址
- I2CInitStructure.I2C_OwnAddress1 = 0x00;//指定stm32自身地址
- I2C_Init(I2C2,&I2CInitStructure);
-
- I2C_Cmd(I2C2,ENABLE);
-
- MPU6050_WriteReg(MPU6050_PWR_MGMT_1,0x01);//配置电源管理寄存器1
- //解除睡眠模式,并选择使用X轴陀螺仪时钟
- MPU6050_WriteReg(MPU6050_PWR_MGMT_2,0x00);//配置电源管理寄存器2
- //六个轴均不待机
- MPU6050_WriteReg(MPU6050_SMPLRT_DIV,0x09);//配置分频寄存器(值越小越快)
- //十分频
- MPU6050_WriteReg(MPU6050_CONFIG,0x06);//配置寄存器,(外部同步+数字低通滤波器)
- MPU6050_WriteReg(MPU6050_GYRO_CONFIG,0x18);//陀螺仪配置寄存器(自测使能+满量程选择)
- MPU6050_WriteReg(MPU6050_ACCEL_CONFIG,0x18);//加速度计配置寄存器(自测+满量程配置+高通滤波器)
- }
-
- /**
- * @brief 获得芯片ID号
- * @param 无
- * @retval 芯片ID
- */
- uint8_t MPU6050_GetID(void)
- {
- return MPU6050_ReadReg(MPU6050_WHO_AM_I);//读取芯片ID号
- }
-
- /**
- * @brief 读取加速度以及角速度数据
- * @param AccX:X轴方向加速度
- * @param AccY:Y轴方向加速度
- * @param AccZ:Z轴方向加速度
- * @param GyroX:X轴方向角速度
- * @param GyroY:Y轴方向角速度
- * @param GyroZ:Z轴方向角速度
- * @retval 无
- */
- 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);//加速度X轴高八位
- DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);//低八位
- *AccX = (DataH << 8) | DataL;
-
- DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);//加速度Y轴高八位
- DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);//低八位
- *AccY = (DataH << 8) | DataL;
-
- DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);//加速度Z轴高八位
- DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);//低八位
- *AccZ = (DataH << 8) | DataL;
-
- DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);//加速度Z轴高八位
- DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);//低八位
- *GyroX = (DataH << 8) | DataL;
-
- DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);//加速度Z轴高八位
- DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);//低八位
- *GyroY = (DataH << 8) | DataL;
-
- DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);//加速度Z轴高八位
- DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);//低八位
- *GyroZ = (DataH << 8) | DataL;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。