新手上路
- 积分
- 33
- 金钱
- 33
- 注册时间
- 2020-3-13
- 在线时间
- 9 小时
|
4金钱
准备自己画板做个小四轴,先用原子的探索者(STM32F4)学学各个模块,自己接了MPU6050和oled,想着把MPU6050读出来的数据显示在oled上,但是一直读出来数据都是257或者771,不然就是65565和00000。不知道有没有遇到过相同问题的朋友,知不知道怎么解决,源码放下面
#ifndef __MPU_H
#define __MPU_H
#include "sys.h"
#include "stdlib.h"
#include "delay.h"
#define MPU_SCLK_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_4)//SCL
#define MPU_SCLK_Set() GPIO_SetBits(GPIOB,GPIO_Pin_4)
#define MPU_SDIN_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_5)//DIN
#define MPU_SDIN_Set() GPIO_SetBits(GPIOB,GPIO_Pin_5)
//****************************************
#define SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:0x07(125Hz)
#define CONFIG 0x1A //低通滤波频率,典型值:0x06(5Hz)
#define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
#define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
#define ACCEL_XOUT_H 0x3B
#define ACCEL_XOUT_L 0x3C
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3E
#define ACCEL_ZOUT_H 0x3F
#define ACCEL_ZOUT_L 0x40
#define TEMP_OUT_H 0x41
#define TEMP_OUT_L 0x42
#define GYRO_XOUT_H 0x43
#define GYRO_XOUT_L 0x44
#define GYRO_YOUT_H 0x45
#define GYRO_YOUT_L 0x46
#define GYRO_ZOUT_H 0x47
#define GYRO_ZOUT_L 0x48
#define PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用)
#define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x68,只读)
#define SlaveAddress 0xD0 //IIC写入时的地址字节数据,+1为读取
void MPU_Init(void);
void MPU_IN(void);
void MPU_OUT(void);
void I2C_Start(void);
void I2C_Stop(void);
void I2C_SendACK(u8 ack);
u8 I2C_RecvACK(void);
u8 IIC_Wait_Ack(void);
void I2C_SendByte(u8 dat);
u8 I2C_RecvByte(u8 ack);
u8 Single_WriteI2C(u8 REG_Address,u8 REG_data);
u8 Single_ReadI2C(u8 REG_Address);
void InitMPU6050(void);
int GetData(u8 REG_Address);
#endif
#include "mpu.h"
void MPU_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOF时钟
//GPIOB4,B5初始化设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
}
void MPU_IN()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOF时钟
//GPIOB4,B5初始化设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
}
void MPU_OUT()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOF时钟
//GPIOB4,B5初始化设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输入模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
}
//**************************************
//I2C起始信号
//**************************************
void I2C_Start()
{
MPU_SDIN_Set(); //拉高数据线
MPU_SCLK_Set(); //拉高时钟线
delay_us(5); //延时
MPU_SDIN_Clr(); //产生下降沿
delay_us(5); //延时
MPU_SCLK_Clr(); //拉低时钟线
}
//**************************************
//I2C停止信号
//**************************************
void I2C_Stop()
{
MPU_SCLK_Clr(); //拉低时钟线
MPU_SDIN_Clr(); //拉低数据线
delay_us(5); //延时
MPU_SCLK_Set(); //拉高时钟线
MPU_SDIN_Set(); //产生上升沿
delay_us(5); //延时
}
//**************************************
//I2C发送应答信号
//入口参数:ack (0:ACK 1:NAK)
//**************************************
void I2C_SendACK(u8 ack)
{
MPU_SCLK_Clr(); //拉低时钟线
if(ack)
MPU_SDIN_Set(); //写应答信号
else
MPU_SDIN_Clr();
delay_us(5); //延时
MPU_SCLK_Set(); //拉高时钟线
delay_us(5); //延时
MPU_SCLK_Clr(); //拉低时钟线
delay_us(5); //延时
}
//**************************************
//I2C接收应答信号
//**************************************
u8 I2C_RecvACK()
{
u8 CY;
MPU_IN();
MPU_SCLK_Set(); //拉高时钟线
delay_us(5); //延时
CY = PBin(5); //读应答信号
MPU_SCLK_Clr(); //拉低时钟线
delay_us(5); //延时
MPU_OUT();
return CY;
}
//**************************************************
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
//**************************************************
u8 IIC_Wait_Ack(void)
{
u16 ucErrTime=0;
MPU_SDIN_Set();delay_us(5);
MPU_SCLK_Set();delay_us(5);
MPU_IN(); //SDA设置为输入
delay_us(5);
while(PBin(5))
{
ucErrTime++;
if(ucErrTime>2500)
{
MPU_OUT();
I2C_Stop();
return 1;
}
}
MPU_SCLK_Clr();//时钟输出0
MPU_OUT();
return 0;
}
//**************************************
//向I2C总线发送一个字节数据
//**************************************
void I2C_SendByte(u8 dat)
{
u8 i;
MPU_SCLK_Clr(); //拉低时钟线
for (i=0; i<8; i++) //8位计数器
{
if(dat&0x80)
MPU_SDIN_Set(); //送数据口
else
MPU_SDIN_Clr();
dat <<= 1; //移出数据的最高位
delay_us(5);
MPU_SCLK_Set(); //拉高时钟线
delay_us(5); //延时
MPU_SCLK_Clr(); //拉低时钟线
delay_us(5); //延时
}
// I2C_RecvACK();
// IIC_Wait_Ack();
}
//**************************************
//从I2C总线接收一个字节数据
//**************************************
u8 I2C_RecvByte(u8 ack)
{
u8 i;
u8 dat = 0;
MPU_IN();
for (i=0; i<8; i++) //8位计数器
{
MPU_SCLK_Clr(); //拉低时钟线
delay_us(5); //延时
dat <<= 1;
MPU_SCLK_Set(); //拉高时钟线
delay_us(5); //延时
if(PBin(5))dat++;
// dat |= PBin(5); //读数据
delay_us(5); //延时
}
MPU_OUT();
I2C_SendACK(!ack);
return dat;
}
//**************************************
//向I2C设备写入一个字节数据
//**************************************
u8 Single_WriteI2C(u8 REG_Address,u8 REG_data)
{
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress); //发送设备地址+写信号
if(IIC_Wait_Ack()) //等待应答
{
// I2C_Stop();
return 1;
}
I2C_SendByte(REG_Address); //内部寄存器地址,
IIC_Wait_Ack();
I2C_SendByte(REG_data); //内部寄存器数据,
if(IIC_Wait_Ack()) //等待应答
{
// I2C_Stop();
return 1;
}
I2C_Stop(); //发送停止信号
return 0;
}
//**************************************
//从I2C设备读取一个字节数据
//**************************************
u8 Single_ReadI2C(u8 REG_Address)
{
u8 REG_data;
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress); //发送设备地址+写信号
IIC_Wait_Ack();
I2C_SendByte(REG_Address); //发送存储单元地址,从0开始
IIC_Wait_Ack();
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress+1); //发送设备地址+读信号
IIC_Wait_Ack();
REG_data=I2C_RecvByte(0); //读出寄存器数据
I2C_Stop(); //停止信号
return REG_data;
}
//**************************************
//初始化MPU6050
//**************************************
void InitMPU6050()
{
Single_WriteI2C(PWR_MGMT_1, 0x80); //复位
delay_ms(500);
Single_WriteI2C(PWR_MGMT_1, 0x00); //解除休眠状态
Single_WriteI2C(SMPLRT_DIV, 0x07);
Single_WriteI2C(CONFIG, 0x06);
Single_WriteI2C(GYRO_CONFIG, 0x18);
Single_WriteI2C(ACCEL_CONFIG, 0x01);
}
//**************************************
//合成数据
//**************************************
int GetData(u8 REG_Address)
{
char H,L;
H=Single_ReadI2C(REG_Address);
L=Single_ReadI2C(REG_Address+1);
return (H<<8)+L; //合成数据
}
|
|