前言
上一节掌握了使用pwm驱动电机,接下来介绍如何使用msp432读取mpu6050数据
正文
首先我们得知道mpu6050通信方式,由于mpu6050只能用i2c通信,所以学会使用msp432的i2c,msp432的i2c驱动可以调用driverlib库来使用msp432的硬件i2c,但是i2c库方法复杂使用起来会比较麻烦,
这里我选择偷个懒,用软件方式模拟i2c驱动。
I2C
建立一个my_i2c.h
/*
* my_i2c.h
*
* Created on: 2021年7月29日
* Author: Administrator
*/
#ifndef MY_I2C_H_
#define MY_I2C_H_
#include #include #define SDA_IN() GPIO_setAsInputPin(GPIO_PORT_P6,GPIO_PIN4) #define SDA_OUT() GPIO_setAsOutputPin(GPIO_PORT_P6,GPIO_PIN4) #define IIC_SCL_High() GPIO_setOutputHighOnPin(GPIO_PORT_P6,GPIO_PIN5) //SCL_High #define IIC_SCL_Low() GPIO_setOutputLowOnPin(GPIO_PORT_P6,GPIO_PIN5) //SCL_Low #define IIC_SDA_High() GPIO_setOutputHighOnPin(GPIO_PORT_P6,GPIO_PIN4) //SDA_High #define IIC_SDA_Low() GPIO_setOutputLowOnPin(GPIO_PORT_P6,GPIO_PIN4) //SDA_Low #define READ_SDA GPIO_getInputPinValue(GPIO_PORT_P6,GPIO_PIN4) //输入SDA void IIC_Init(void); //初始化IIC的IO口 void IIC_Start(void); //发送IIC开始信号 void IIC_Stop(void); //发送IIC停止信号 void IIC_Send_Byte(uint8_t txd); //IIC发送一个字节 uint8_t IIC_Read_Byte(unsigned char ack);//IIC读取一个字节 uint8_t IIC_Wait_Ack(void); //IIC等待ACK信号 void IIC_Ack(void); //IIC发送ACK信号 void IIC_NAck(void); //IIC不发送ACK信号 #endif /* MY_I2C_H_ */ my_i2c.c /* * my_i2c.c * * Created on: 2021年7月29日 * Author: Administrator */ #include void IIC_Init (void){ GPIO_setAsOutputPin(GPIO_PORT_P6,GPIO_PIN5 ); //CLK GPIO_setAsOutputPin(GPIO_PORT_P6,GPIO_PIN4);//DIN IIC_SCL_High(); IIC_SDA_High(); } void IIC_Start(void)//SDA 10 SCL 010 { SDA_OUT(); //sda线输出 IIC_SCL_High(); IIC_SDA_High(); delay_us(4); IIC_SDA_Low();//START:when CLK is high,DATA change form high to low delay_us(4); IIC_SCL_Low();//钳住I2C总线,准备发送或接收数据 } void IIC_Stop(void)//SDA 01 SCL 01 { SDA_OUT();//sda线输出 IIC_SCL_Low();//STOP:when CLK is high DATA change form low to high IIC_SDA_Low(); delay_us(4); IIC_SCL_High(); IIC_SDA_High();//发送I2C总线结束信号 delay_us(4); } //等待应答信号到来 //返回值:1,接收应答失败 // 0,接收应答成功 uint8_t IIC_Wait_Ack(void)// { uint8_t cy; SDA_IN(); //SDA设置为输入 IIC_SCL_High();delay_us(10); IIC_SDA_High();delay_us(10); if(READ_SDA) { cy=1; IIC_SCL_Low(); return cy; } else { cy=0; } IIC_SCL_Low();//时钟输出0 return cy; } //产生ACK应答 void IIC_Ack(void) { IIC_SCL_Low(); SDA_OUT(); IIC_SDA_Low(); delay_us(2); IIC_SCL_High(); delay_us(2); IIC_SCL_Low(); } //不产生ACK应答 void IIC_NAck(void) { IIC_SCL_Low(); SDA_OUT(); IIC_SDA_High(); delay_us(2); IIC_SCL_High(); delay_us(2); IIC_SCL_Low(); } //IIC发送一个字节 //返回从机有无应答 //1,有应答 //0,无应答 void IIC_Send_Byte(uint8_t txd) { uint8_t t; SDA_OUT(); IIC_SCL_Low();//拉低时钟开始数据传输 delay_us(2); for(t=0;t<8;t++) { if(txd&0x80) { IIC_SDA_High();delay_us(2); } else { IIC_SDA_Low();delay_us(2); } txd<<=1; IIC_SCL_High(); delay_us(4); IIC_SCL_Low(); delay_us(2); } delay_us(2); } //读1个字节,ack=1时,发送ACK,ack=0,发送nACK uint8_t IIC_Read_Byte(unsigned char ack) { unsigned char i,receive=0; SDA_IN();//SDA设置为输入 for(i=0;i<8;i++ ) { IIC_SCL_Low(); delay_us(2); IIC_SCL_High(); receive<<=1; if(READ_SDA) receive++; delay_us(2); } if (!ack) IIC_NAck();//发送nACK else IIC_Ack(); //发送ACK return receive; } 好了到这里i2c驱动有了,就可以继续下一步了 MPU6050 mpu6050.h /* * MPU6050.H * * Created on: 2021年7月29日 * Author: Administrator */ #ifndef MPU6050_H_ #define MPU6050_H_ #include #include #include #include #include #include #include #define MPU6050_ADDR 0x68 #define MPU6050_SMPLRT_DIV 0x19 #define MPU6050_CONFIG 0x1a #define MPU6050_GYRO_CONFIG 0x1b #define MPU6050_ACCEL_CONFIG 0x1c #define MPU6050_WHO_AM_I 0x75 #define MPU6050_PWR_MGMT_1 0x6b #define MPU6050_PWR_MGMT_2 0x6c #define MPU_ACCEL_XOUTH_REG 0x3b #define MPU_GYRO_XOUTH_REG 0x43 #define MPU6050_TEMP_H 0x41 #define MPU6050_TEMP_L 0x42 #define MPU_DEVICE_ID_REG 0x75 typedef uint8_t u8; typedef uint16_t u16; #define PI 3.1415926535897932384626433832795 extern int16_t rawAccX, rawAccY, rawAccZ,rawGyroX, rawGyroY, rawGyroZ; extern float gyroXoffset, gyroYoffset, gyroZoffset; extern float temp, accX, accY, accZ, gyroX, gyroY, gyroZ; extern float angleGyroX, angleGyroY, angleGyroZ,angleAccX, angleAccY, angleAccZ; extern float angleX, angleY, angleZ; extern uint32_t timer; extern float accCoef; extern float gyroCoef; u8 MPU_Init(void); void calcGyroOffsets(void); void mpu_update(void); u8 MPU_Set_Gyro_Fsr(u8 fsr); u8 MPU_Set_Accel_Fsr(u8 fsr); u8 MPU_Set_LPF(u16 lpf); u8 MPU_Set_Rate(u16 rate); short MPU_Get_Temperature(); u8 MPU_Get_Gyroscope(int16_t *gx,int16_t *gy,int16_t *gz); u8 MPU_Get_Accelerometer(int16_t *ax,int16_t *ay,int16_t *az); u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf); u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf); u8 MPU_Write_Byte(u8 reg,u8 data); u8 MPU_Read_Byte(u8 reg); #endif /* MPU6050_H_ */ mpu6050.c /* * MPU6050.C * * Created on: 2021年7月29日 * Author: Administrator */ #include int16_t rawAccX, rawAccY, rawAccZ,rawGyroX, rawGyroY, rawGyroZ; float gyroXoffset, gyroYoffset, gyroZoffset; float temp, accX, accY, accZ, gyroX, gyroY, gyroZ; float angleGyroX, angleGyroY, angleGyroZ,angleAccX, angleAccY, angleAccZ; float angleX, angleY, angleZ; float gyroCoef,accCoef; uint32_t timer,preInterval; float interval; u8 MPU_Init(void) { accCoef = 0.02; gyroCoef = 0.98; IIC_Init(); MPU_Write_Byte(MPU6050_SMPLRT_DIV, 0x00); MPU_Write_Byte(MPU6050_CONFIG, 0x00); MPU_Write_Byte(MPU6050_GYRO_CONFIG, 0x08); MPU_Write_Byte(MPU6050_ACCEL_CONFIG, 0x00); MPU_Write_Byte(MPU6050_PWR_MGMT_1,0X01); mpu_update(); angleGyroX = 0; angleGyroY = 0; preInterval = timer; return 0; } void calcGyroOffsets(void){ float x = 0, y = 0, z = 0; int16_t rx, ry, rz; int i; for(i =0; i < 1000; i++){ MPU_Get_Gyroscope(&rx,&ry,&rz); x += ((float)rx) / 65.5; y += ((float)ry) / 65.5; z += ((float)rz) / 65.5; } gyroXoffset = x / 1000; gyroYoffset = y / 1000; gyroZoffset = z / 1000; } void mpu_update(void){ MPU_Get_Accelerometer(&rawAccX, &rawAccY, &rawAccZ); temp = MPU_Get_Temperature(); MPU_Get_Gyroscope(&rawGyroX,&rawGyroY,&rawGyroZ); accX = ((float)rawAccX) / 16384.0; accY = ((float)rawAccY) / 16384.0; accZ = ((float)rawAccZ) / 16384.0; angleAccX = atan2(accY, accZ + abs(accX)) * 360 / 2.0 / PI; angleAccY = atan2(accX, accZ + abs(accY)) * 360 / -2.0 / PI; gyroX = ((float)rawGyroX) / 65.5; gyroY = ((float)rawGyroY) / 65.5; gyroZ = ((float)rawGyroZ) / 65.5; gyroX -= gyroXoffset; gyroY -= gyroYoffset; gyroZ -= gyroZoffset; angleGyroX += gyroX * interval; angleGyroY += gyroY * interval; angleGyroZ += gyroZ * interval; interval = (timer - preInterval) * 0.001; angleX = (gyroCoef * (angleX + gyroX * interval)) + (accCoef * angleAccX); angleY = (gyroCoef * (angleY + gyroY * interval)) + (accCoef * angleAccY); angleZ = angleGyroZ; preInterval = timer ; } //设置MPU6050陀螺仪传感器满量程范围 //fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps //返回值:0,设置成功 // 其他,设置失败 u8 MPU_Set_Gyro_Fsr(u8 fsr) { return MPU_Write_Byte(MPU6050_GYRO_CONFIG,fsr<<3);//设置陀螺仪满量程范围 } //设置MPU6050加速度传感器满量程范围
相关文章