网上少有STM32与MPC-6050通讯的介绍,可以用的代码就更少了。辛苦了几天,终于将其调通,共享出来与大家分享。
什么都不说了,直接上代码,大家看注释就行了:
i2c.h
- #ifndef __I2C_H
- #define __I2C_H
- #include "sys.h"
- //IO方向设置
- #define SDA_IN() {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=8<<12;}
- #define SDA_OUT() {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=3<<12;}
- //IO操作函数
- #define IIC_SCL PBout(10) //SCL
- #define IIC_SDA PBout(11) //SDA
- #define READ_SDA PBin(11) //输入SDA
- //IIC所有操作函数
- void IIC_Init(void); //初始化IIC的IO口
- void IIC_Start(void); //发送IIC开始信号
- void IIC_Stop(void); //发送IIC停止信号
- void IIC_Send_Byte(u8 txd); //IIC发送一个字节
- u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
- u8 IIC_Wait_Ack(void); //IIC等待ACK信号
- void IIC_Ack(void); //IIC发送ACK信号
- void IIC_NAck(void); //IIC不发送ACK信号
- void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
- u8 IIC_Read_One_Byte(u8 daddr,u8 addr);
- #endif
i2c.c
- #include "i2c.h"
- #include "delay.h"
- //初始化IIC
- void IIC_Init(void)
- {
- RCC->APB2ENR|=1<<3;//先使能外设IO PORTB时钟
- GPIOB->CRH&=0XFFFF00FF;//PB10/11 推挽输出
- GPIOB->CRH|=0X00003300;
- GPIOB->ODR|=3<<10; //PB10/11 输出高
- }
- //产生IIC起始信号
- void IIC_Start(void)
- {
- SDA_OUT(); //sda线输出
- IIC_SDA=1;
- IIC_SCL=1;
- delay_us(5);
- IIC_SDA=0;//START:when CLK is high,DATA change form high to low
- delay_us(5);
- IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
- }
- //产生IIC停止信号
- void IIC_Stop(void)
- {
- SDA_OUT();//sda线输出
- IIC_SCL=0;
- IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
- delay_us(5);
- IIC_SCL=1;
- IIC_SDA=1;//发送I2C总线结束信号
- delay_us(5);
- }
- //等待应答信号到来
- //返回值:1,接收应答失败
- // 0,接收应答成功
- u8 IIC_Wait_Ack(void)
- {
- u8 ucErrTime=0;
- SDA_IN(); //SDA设置为输入
- IIC_SDA=1;delay_us(5);
- IIC_SCL=1;delay_us(5);
- while(READ_SDA)
- {
- ucErrTime++;
- if(ucErrTime>250)
- {
- IIC_Stop();
- return 1;
- }
- }
- IIC_SCL=0;//时钟输出0
- return 0;
- }
- //产生ACK应答
- void IIC_Ack(void)
- {
- IIC_SCL=0;
- SDA_OUT();
- IIC_SDA=0;
- delay_us(5);
- IIC_SCL=1;
- delay_us(5);
- IIC_SCL=0;
- }
- //不产生ACK应答
- void IIC_NAck(void)
- {
- IIC_SCL=0;
- SDA_OUT();
- IIC_SDA=1;
- delay_us(5);
- IIC_SCL=1;
- delay_us(5);
- IIC_SCL=0;
- }
- //IIC发送一个字节
- //返回从机有无应答
- //1,有应答
- //0,无应答
- void IIC_Send_Byte(u8 txd)
- {
- u8 t;
- SDA_OUT();
- IIC_SCL=0;//拉低时钟开始数据传输
- for(t=0;t<8;t++)
- {
- IIC_SDA=(txd&0x80)>>7;
- txd<<=1;
- delay_us(5); //对TEA5767这三个延时都是必须的
- IIC_SCL=1;
- delay_us(5);
- IIC_SCL=0;
- delay_us(5);
- }
- }
- //读1个字节,ack=1时,发送ACK,ack=0,发送nACK
- u8 IIC_Read_Byte(unsigned char ack)
- {
- unsigned char i,receive=0;
- SDA_IN();//SDA设置为输入
- for(i=0;i<8;i++ )
- {
- IIC_SCL=0;
- delay_us(5);
- IIC_SCL=1;
- receive<<=1;
- if(READ_SDA)receive++;
- delay_us(5);
- }
- if (!ack)
- IIC_NAck();//发送nACK
- else
- IIC_Ack(); //发送ACK
- return receive;
- }
mpc6050.h
- #ifndef __MPU6050_H
- #define __MPU6050_H
- #include "sys.h"
- //****************************************
- // 定义MPU6050内部地址
- //****************************************
- #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为读取
- #define MPU_60X0_PWR_MGMT_1_REG_ADDR 0x6B
- #define MPU_60X0_USER_CTRL_REG_ADDR 0x6A
- #define MPU_60X0_SMPLRT_DIV_REG_ADDR 0x19
- #define MPU_60X0_CONFIG_REG_ADDR 0x1A
- #define MPU_60X0_GYRO_CONFIG_REG_ADDR 0x1B
- #define MPU_60X0_ACCEL_CONFIG_REG_ADDR 0x1C
- #define MPU_60X0_FIFO_EN_REG_ADDR 0x23
- #define MPU_60X0_RESET_REG_VALU 0x80
- #define MPU_60X0_PWR_MGMT_1_REG_VALU 0x09 // Disable temperature sensor, PLL with X axis gyroscope reference
- #define MPU_60X0_USER_CTRL_REG_VALU 0x45 // Enable FIFO. Reset FIFO and signal paths for all sensors
- #define MPU_60X0_SMPLRT_DIV_REG_VALU 0x00 // DLPF_CFG is 0x01, so Gyroscope Output Rate = 1kHz, divided by 1, still 1kHz
- #define MPU_60X0_CONFIG_REG_VALU 0x03 // 184Hz 2.0ms 188Hz 1.9ms 1kHz. So there will be 6x2 bytes new data in FIFO every 1ms
- #define MPU_60X0_GYRO_CONFIG_REG_VALU 0x08 // Gyroscope works at 500dps. If selftest is needed, REMEMBER to put this to 250dps
- #define MPU_60X0_ACCEL_CONFIG_REG_VALU 0x08 // Accelerometer works at 4g range. If selftest is needed, REMEMBER to put this to 8g range
- #define MPU_60X0_FIFO_EN_REG_VALU 0x78 // Only enable accel and gyro
- extern u16 delayTime;
- void Single_WriteI2C(u8 REG_Address,u8 REG_data);
- u8 Single_ReadI2C(u8 REG_Address);
- void InitMPU6050(void);
- u16 GetData(u8 REG_Address);
- void I2C1_WriteByte(u8 REG_Address,u8 REG_data);
- u8 I2C1_ReadByte(u8 DataAddr);
- void SetDelayTime(u16 delayMs);
- #endif
mpc6050.c
- #include "delay.h"
- #include "mpu6050.h"
- #include "i2c.h"
- u16 delayTime = 1000;
- //**************************************
- //向I2C设备写入一个字节数据
- //**************************************
- void Single_WriteI2C(u8 REG_Address,u8 REG_data)
- {
- IIC_Start(); //起始信号
- IIC_Send_Byte(SlaveAddress); //发送设备地址+写信号
- IIC_Wait_Ack();
- IIC_Send_Byte(REG_Address); //内部寄存器地址,
- IIC_Wait_Ack();
- IIC_Send_Byte(REG_data); //内部寄存器数据,
- IIC_Wait_Ack();
- IIC_Stop(); //发送停止信号
- }
- //**************************************
- //从I2C设备读取一个字节数据
- //**************************************
- u8 Single_ReadI2C(u8 REG_Address)
- {
- u8 REG_data;
- IIC_Start(); //起始信号
- IIC_Send_Byte(SlaveAddress); //发送设备地址+写信号
- IIC_Wait_Ack();
- IIC_Send_Byte(REG_Address); //发送存储单元地址,从0开始
- IIC_Wait_Ack();
- IIC_Start(); //起始信号
- IIC_Send_Byte(SlaveAddress+1); //发送设备地址+读信号
- IIC_Wait_Ack();
- REG_data=IIC_Read_Byte(0); //读出寄存器数据
- //IIC_SendAck(); //接收应答信号
- IIC_Stop(); //停止信号
- return REG_data;
- }
- //**************************************
- //初始化MPU6050
- //**************************************
- void InitMPU6050()
- {
- /*
- 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);
- */
- u32 i;
- Single_WriteI2C(MPU_60X0_PWR_MGMT_1_REG_ADDR, MPU_60X0_RESET_REG_VALU);
- for (i = 0; i < 20000; i++)
- {
- delay_us(5); //上电延时
- }
- Single_WriteI2C(MPU_60X0_PWR_MGMT_1_REG_ADDR, MPU_60X0_PWR_MGMT_1_REG_VALU);
- Single_WriteI2C(MPU_60X0_USER_CTRL_REG_ADDR, MPU_60X0_USER_CTRL_REG_VALU);
- Single_WriteI2C(MPU_60X0_SMPLRT_DIV_REG_ADDR, MPU_60X0_SMPLRT_DIV_REG_VALU);
- Single_WriteI2C(MPU_60X0_CONFIG_REG_ADDR, MPU_60X0_CONFIG_REG_VALU);
- Single_WriteI2C(MPU_60X0_GYRO_CONFIG_REG_ADDR, MPU_60X0_GYRO_CONFIG_REG_VALU);
- Single_WriteI2C(MPU_60X0_ACCEL_CONFIG_REG_ADDR, MPU_60X0_ACCEL_CONFIG_REG_VALU);
- Single_WriteI2C(MPU_60X0_FIFO_EN_REG_ADDR, MPU_60X0_FIFO_EN_REG_VALU);
- }
- //**************************************
- //合成数据
- //**************************************
- u16 GetData(u8 REG_Address)
- {
- u8 H,L;
- H=Single_ReadI2C(REG_Address);
- L=Single_ReadI2C(REG_Address+1);
- return (H<<8)+L; //合成数据
- }
- void SetDelayTime(u16 delayMs)
- {
- delayTime = delayMs;
- }