去年電賽備賽期間,學(xué)的STM32標(biāo)準(zhǔn)庫,那一整個(gè)繁瑣直接給我勸退了,當(dāng)時(shí)學(xué)習(xí)MPU6050時(shí)就非常痛苦,代碼也看不懂,無非抄來抄去,然后就是編譯,改錯(cuò),編譯無窮盡也。最近參考野火的MPU6050代碼,將其移植到了MSP430f5529之上,今天分享出來。
1.重要性
MPU6050模塊對(duì)于不論平衡車還是四旋翼無人機(jī)的開發(fā)都是非常重要的一個(gè)模塊,除此之外,對(duì)于四輪小車的轉(zhuǎn)彎閉環(huán)控制也是至關(guān)重要的,因此備戰(zhàn)電賽控制類這是一個(gè)不可避開的模塊。該模塊包含陀螺儀和加速度傳感器,可以解算出其x,y,z三個(gè)方向的角度和各個(gè)方向的角速度,使用十分方便,此次并未采用官方的DMP庫。
2.代碼
廢話不多說,直接上代碼,調(diào)用即可。文章來源:http://www.zghlxwxcb.cn/news/detail-576754.html
/*
* MPU6050.c
*
* Created on: 2022年7月17日
* Author: S10
*/
#include "driverlib.h"
#include "mpu6050.h"
void ByteWrite6050(unsigned char REG_Address,unsigned char REG_data);
unsigned char ByteRead6050(unsigned char REG_Address);
int Get6050Data(unsigned char REG_Address);
void InitMPU6050();
float Mpu6050AccelAngle(char dir);
float Mpu6050GyroAngle(char dir);
///開啟信號(hào)
void IIC_start()
{
SDA_OUT;
SCL_OUT;
SCL_HIGH;
SDA_HIGH;
__delay_cycles(10);
SDA_LOW;
__delay_cycles(10);
SCL_LOW;
}
///停止信號(hào)
void IIC_stop()
{
SDA_OUT;
SCL_OUT;
SDA_LOW;
SCL_HIGH;
__delay_cycles(10);
SDA_HIGH;
__delay_cycles(10);
}
//發(fā)送應(yīng)答信號(hào)(MCU=>||)
void SendACK(unsigned char ack)
{
SDA_OUT;
SCL_OUT;
if(ack==1)
{
SDA_HIGH;
}
else if(ack==0)
{
SDA_LOW;
}
else
return;
SCL_HIGH;
__delay_cycles(10);
SCL_LOW;
__delay_cycles(10);
}
接收應(yīng)答信號(hào)(||=>MCU)
unsigned char IIC_testACK()
{
unsigned char a;
SCL_OUT;
SDA_IN;
//GPIO_setAsInputPinWithPullUpResistor (GPIO_PORT_P8, GPIO_PIN2);
SCL_HIGH;
__delay_cycles(10);
if(GPIO_getInputPinValue (GPIO_PORT_P8, GPIO_PIN2)==1)
{
a=1;
}
else
{
a=0;
}
SCL_LOW;
__delay_cycles(10);
SDA_OUT;
return a;
}
///向IIC總線發(fā)送數(shù)據(jù)(MCU=>||)
void IIC_writebyte(unsigned char IIC_byte)
{
unsigned char i;
SDA_OUT;
SCL_OUT;
// SCL_LOW;
for (i=0; i<8; i++) //8位計(jì)數(shù)器
{
if((IIC_byte<<i)&0x80)
{
SDA_HIGH;
}
else
{
SDA_LOW;
}
__delay_cycles(10);
SCL_HIGH;
__delay_cycles(10);
SCL_LOW;
// __delay_cycles(10);
// IIC_byte<<=1;
}
IIC_testACK();
}
IIC接收一個(gè)字節(jié)(||——>MCU)
unsigned char IIC_readebyte(void)
{
unsigned char i,k=0;
SDA_IN;
GPIO_setAsInputPinWithPullUpResistor (GPIO_PORT_P8, GPIO_PIN2);
SCL_OUT;
SCL_LOW;
__delay_cycles(100);
for(i=0;i<8;i++)
{
SCL_HIGH;
k=k<<1;
if(SDA)
k|=1;
SCL_LOW;
__delay_cycles(100);
}
SDA_OUT;
__delay_cycles(100);
return k;
}
//**************************************
//向I2C設(shè)備寫入一個(gè)字節(jié)數(shù)據(jù)
//**************************************
void ByteWrite6050(unsigned char REG_Address,unsigned char REG_data)
{
IIC_start(); //起始信號(hào)
IIC_writebyte(SlaveAddress); //發(fā)送設(shè)備地址+寫信號(hào)
IIC_writebyte(REG_Address); //內(nèi)部寄存器地址,
IIC_writebyte(REG_data); //內(nèi)部寄存器數(shù)據(jù),
IIC_stop(); //發(fā)送停止信號(hào)
}
//**************************************
//從I2C設(shè)備讀取一個(gè)字節(jié)數(shù)據(jù)
//**************************************
unsigned char ByteRead6050(unsigned char REG_Address)
{
unsigned char REG_data;
IIC_start(); //起始信號(hào)
IIC_writebyte(SlaveAddress); //發(fā)送設(shè)備地址+寫信號(hào)
IIC_writebyte(REG_Address); //發(fā)送存儲(chǔ)單元地址,從0開始
IIC_start(); //起始信號(hào)
IIC_writebyte(SlaveAddress+1); //發(fā)送設(shè)備地址+讀信號(hào)
REG_data=IIC_readebyte(); //讀出寄存器數(shù)據(jù)
SendACK(1); //接收應(yīng)答信號(hào)
IIC_stop(); //停止信號(hào)
return REG_data;
}
//**************************************
//合成數(shù)據(jù)
//**************************************
int Get6050Data(unsigned char REG_Address)
{
char H,L;
H=ByteRead6050(REG_Address);
L=ByteRead6050(REG_Address+1);
return (H<<8)+L; //合成數(shù)據(jù)
}
//**************************************
//初始化MPU6050
//**************************************
void InitMPU6050()
{
ByteWrite6050(PWR_MGMT_1, 0x00); // 解除休眠狀態(tài)
ByteWrite6050(SMPLRT_DIV, 0x07); // 陀螺儀采樣率設(shè)置(125HZ)
ByteWrite6050(CONFIG, 0x06); // 低通濾波器設(shè)置(5HZ頻率)
ByteWrite6050(GYRO_CONFIG, 0x18); // 陀螺儀自檢及檢測(cè)范圍設(shè)置(不自檢,16.4LSB/DBS/S)
ByteWrite6050(ACCEL_CONFIG, 0x01); // 不自檢,量程2g
}
/*
**********************************************
**函數(shù)名 :float Mpu6050AccelAngle(int8 dir)
**函數(shù)功能:輸出加速度傳感器測(cè)量的傾角值
** 范圍為2g時(shí),換算關(guān)系:16384 LSB/g
** 角度較小時(shí),x=sinx得到角度(弧度), deg = rad*180/3.14
** 因?yàn)閤>=sinx,故乘以1.2適當(dāng)放大
**返回參數(shù):測(cè)量的傾角值
**傳入?yún)?shù):dir - 需要測(cè)量的方向
** ACCEL_XOUT - X方向
** ACCEL_YOUT - Y方向
** ACCEL_ZOUT - Z方向
**********************************************
*/
float Mpu6050AccelAngle(char dir)
{
float accel_agle; // 測(cè)量的傾角值
float result; // 測(cè)量值緩存變量
result = (float)Get6050Data(dir); // 測(cè)量當(dāng)前方向的加速度值,轉(zhuǎn)換為浮點(diǎn)數(shù)
accel_agle = (result + MPU6050_ZERO_ACCELL)/16384; // 去除零點(diǎn)偏移,計(jì)算得到角度(弧度)
accel_agle = accel_agle*1.2*180/3.14; //弧度轉(zhuǎn)換為度
return accel_agle; // 返回測(cè)量值
}
/*
**********************************************
**函數(shù)名 :float Mpu6050GyroAngle(int8 dir)
**函數(shù)功能:輸出陀螺儀測(cè)量的傾角加速度
** 范圍為2000deg/s時(shí),換算關(guān)系:16.4 LSB/(deg/s)
**返回參數(shù):測(cè)量的傾角加速度值
**傳入?yún)?shù):dir - 需要測(cè)量的方向
** GYRO_XOUT - X軸方向
** GYRO_YOUT - Y軸方向
** GYRO_ZOUT - Z軸方向
**********************************************
*/
float Mpu6050GyroAngle(char dir)
{
float gyro_angle;
gyro_angle = (float)Get6050Data(dir); // 檢測(cè)陀螺儀的當(dāng)前值
gyro_angle = -(gyro_angle + MPU6050_ZERO_GYRO)/16.4; //去除零點(diǎn)偏移,計(jì)算角速度值,負(fù)號(hào)為方向處理
return gyro_angle; // 返回測(cè)量值
}
/*
* MPU6050.h
*
* Created on: 2022年7月17日
* Author: S10
*/
#ifndef MPU6050_H_
#define MPU6050_H_
//********Mpu6050的零點(diǎn)校準(zhǔn)值**************
#define MPU6050_ZERO_ACCELL 378
#define MPU6050_ZERO_GYRO 13
//*************定義MPU6050內(nèi)部地址*******************
#define SMPLRT_DIV 0x19 //輸出8位無符號(hào)位,輸出分頻,用來配置采樣頻率的寄存器。采樣率=陀螺儀的輸出率/(1+該寄存器值),低通濾波器使能時(shí)陀螺儀輸出為8k,反之1k。
#define CONFIG 0x1A //配置低通濾波器的寄存器
#define GYRO_CONFIG 0x1B //三個(gè)方向角度的自我測(cè)試和量程
#define ACCEL_CONFIG 0x1C //三個(gè)方向加速度的自我測(cè)試和量程
/***************加速度傳感器寄存器******************/
#define ACCEL_XOUT_H 0x3B
#define ACCEL_XOUT_L 0x3C
#define ACCEL_XOUT ACCEL_XOUT_H // X軸讀取地址,高位為起始位
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3E
#define ACCEL_YOUT ACCEL_YOUT_H // Y軸讀取地址,高位為起始位
#define ACCEL_ZOUT_H 0x3F
#define ACCEL_ZOUT_L 0x40
#define ACCEL_ZOUT ACCEL_ZOUT_H // Z軸讀取地址,高位為起始位
/*****************溫度傳感器寄存器****************/
#define TEMP_OUT_H 0x41
#define TEMP_OUT_L 0x42
#define TEMP_OUT TEMP_OUT_H // 溫度傳感器讀取地址,高位為起始位
//
/陀螺儀相關(guān)寄存器//
//
#define GYRO_XOUT_H 0x43
#define GYRO_XOUT_L 0x44
#define GYRO_XOUT GYRO_XOUT_H // 陀螺儀X軸讀取地址,高位為起始位
#define GYRO_YOUT_H 0x45
#define GYRO_YOUT_L 0x46
#define GYRO_YOUT GYRO_YOUT_H // 陀螺儀Y軸讀取地址,高位為起始位
#define GYRO_ZOUT_H 0x47
#define GYRO_ZOUT_L 0x48
#define GYRO_ZOUT GYRO_ZOUT_H // 陀螺儀Z軸讀取地址,高位為起始位
///
其它寄存器/
//
#define PWR_MGMT_1 0x6B //電源管理
#define WHO_AM_I 0x75 //6位iic地址,最后一位A0控制
//
///iic地址設(shè)置
/
#define SlaveAddress 0xD0 //A0接地,若接3.3v則0xD1
extern void ByteWrite6050(unsigned char REG_Address,unsigned char REG_data);
extern unsigned char ByteRead6050(unsigned char REG_Address);
extern int Get6050Data(unsigned char REG_Address);
extern void InitMPU6050();
extern float Mpu6050AccelAngle(char dir);
extern float Mpu6050GyroAngle(char dir);
#define SCL_HIGH P1OUT|=BIT2
#define SCL_LOW P1OUT&=~BIT2
#define SDA_HIGH P1OUT|=BIT3
#define SDA_LOW P1OUT&=~BIT3
#define SDA_OUT P1DIR|=BIT3
#define SDA_IN P1DIR&=~BIT3
#define SCL_OUT P1DIR|=BIT2
#define SDA P1IN&BIT3
void IIC_start();//開始
void IIC_stop();//停止
void SendACK(unsigned char ack);//向iic發(fā)送標(biāo)志
void IIC_writebyte(unsigned char IIC_byte);///接收iic標(biāo)志
unsigned char IIC_testACK();///發(fā)送數(shù)據(jù)
unsigned char IIC_readebyte();///接收數(shù)據(jù)
#endif /* MPU6050_H_ */
直接根據(jù)自己的需求更改模擬IIC的SCL和SDA引腳即可
需要注意的是IIC時(shí)序中的延時(shí),以上代碼是在主頻為16MHZ的條件下完成的。文章來源地址http://www.zghlxwxcb.cn/news/detail-576754.html
到了這里,關(guān)于模塊學(xué)習(xí)(二)——MPU6050的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!