基于msp430的mpu6050陀螺仪程序.docx
《基于msp430的mpu6050陀螺仪程序.docx》由会员分享,可在线阅读,更多相关《基于msp430的mpu6050陀螺仪程序.docx(19页珍藏版)》请在冰豆网上搜索。
基于msp430的mpu6050陀螺仪程序
//includes.h
#include
#include"LCD1602.h"
#include"mpu6050.h"
//main.c
#include"includes.h"
voidmain()
{
WDTCTL=WDTPW+WDTHOLD;
BCSCTL1&=~XT2OFF;
do
{
IFG1&=~OFIFG;
for(uinti=0xff;i>0;i--);
}while((IFG1&OFIFG));//等待时钟稳定
BCSCTL2|=SELM_2+SELS;//主、从系统时钟均为高频
DATA_DIR=0XFF;
DATA_OUT=0X00;
P6DIR=0XFF;
P6OUT=0X00;
init();
InitMPU6050();
while
(1)
{
Display10BitData(GetData(ACCEL_XOUT_H),2,0);//显示X轴加速度
Display10BitData(GetData(ACCEL_YOUT_H),7,0);//显示Y轴加速度
Display10BitData(GetData(ACCEL_ZOUT_H),12,0);//显示Z轴加速度
Display10BitData(GetData(GYRO_XOUT_H),2,1);//显示X轴角速度
Display10BitData(GetData(GYRO_YOUT_H),7,1);//显示Y轴角速度
Display10BitData(GetData(GYRO_ZOUT_H),12,1);
delayms(300);
}
}
//以下是传感器相关文件
//mpu6050.h
#defineCPU_F((double)8000000)
#definedelayus(x)__delay_cycles((long)(CPU_F*(double)x/1000000.0))//宏定义延时函数
#definedelayms(x)__delay_cycles((long)(CPU_F*(double)x/1000.0))
#defineSCL1P5OUT|=BIT0
#defineSCL0P5OUT&=~BIT0
#defineSCLOUTP5DIR|=BIT0;
#defineSDA1P5OUT|=BIT1//IIC数据引脚
#defineSDA0P5OUT&=~BIT1
#defineSDAINP5DIR&=~BIT1
#defineSDAOUTP5DIR|=BIT1
#defineSDADATA(P5IN&BIT1)
//****************************************
//定义MPU6050内部地址
//****************************************
#defineSMPLRT_DIV0x19//陀螺仪采样率,典型值:
0x07(125Hz)
#defineCONFIG0x1A//低通滤波频率,典型值:
0x06(5Hz)
#defineGYRO_CONFIG0x1B//陀螺仪自检及测量范围,典型值:
0x18(不自检,2000deg/s)
#defineACCEL_CONFIG0x1C//加速计自检、测量范围及高通滤波频率,典型值:
0x01(不自检,2G,5Hz)
#defineACCEL_XOUT_H0x3B
#defineACCEL_XOUT_L0x3C
#defineACCEL_YOUT_H0x3D
#defineACCEL_YOUT_L0x3E
#defineACCEL_ZOUT_H0x3F
#defineACCEL_ZOUT_L0x40
#defineTEMP_OUT_H0x41
#defineTEMP_OUT_L0x42
#defineGYRO_XOUT_H0x43
#defineGYRO_XOUT_L0x44
#defineGYRO_YOUT_H0x45
#defineGYRO_YOUT_L0x46
#defineGYRO_ZOUT_H0x47
#defineGYRO_ZOUT_L0x48
#definePWR_MGMT_10x6B//电源管理,典型值:
0x00(正常启用)
#defineWHO_AM_I0x75//IIC地址寄存器(默认数值0x68,只读)
#defineSlaveAddress0xD0//IIC写入时的地址字节数据,+1为读取
//显示数字(-511至512)的字符数组
voidI2C_Start();
voidI2C_Stop();
voidI2C_SendACK(ucharack);
ucharI2C_RecvACK();
voidI2C_SendByte(uchardat);
ucharI2C_RecvByte();
voidSingle_WriteI2C(ucharREG_Address,ucharREG_data);
ucharSingle_ReadI2C(ucharREG_Address);
voidInitMPU6050();
voidlcd_printf(uchar*s,inttemp_data);
voidDisplayListChar(ucharX,ucharY,uchar*DData,ucharL);
intGetData(ucharREG_Address);
voidDisplay10BitData(intvalue,ucharx,uchary);
//mpu6050.c
#include"includes.h"
uchardis[4];
intdis_data;
//**************************************
//I2C起始信号
//**************************************
voidI2C_Start()
{
SDAOUT;
SDA1;//拉高数据线
SCLOUT;
SCL1;//拉高时钟线
delayus(5);//延时
SDA0;//产生下降沿
delayus(5);//延时
SCL0;//拉低时钟线
}
//**************************************
//I2C停止信号
//**************************************
voidI2C_Stop()
{
SDAOUT;
SDA0;//拉低数据线
SCLOUT;
SCL1;//拉高时钟线
delayus(5);//延时
SDA1;//产生上升沿
delayus(5);//延时
}
//**************************************
//I2C发送应答信号
//入口参数:
ack(0:
ACK1:
NAK)
//**************************************
voidI2C_SendACK(ucharack)
{
SDAOUT;
SCLOUT;
if(ack)SDA1;
elseSDA0;
//SDA=ack;//写应答信号
SCL1;//拉高时钟线
delayus(5);//延时
SCL0;//拉低时钟线
delayus(5);//延时
}
//**************************************
//I2C接收应答信号
//**************************************
ucharI2C_RecvACK()
{
ucharcy;
SCLOUT;
SCL1;//拉高时钟线
SDAIN;
delayus(5);//延时
if(SDADATA)
{
cy=1;
}
else
{
cy=0;
}
//cy=SDA;//读应答信号
SCL0;//拉低时钟线
delayus(5);//延时
SDAOUT;
returncy;
}
//**************************************
//向I2C总线发送一个字节数据
//**************************************
voidI2C_SendByte(uchardat)
{
uchari;
SDAOUT;
for(i=0;i<8;i++)//8位计数器
{
if((dat<
{
SDA1;
}
else
{
SDA0;
}
//SDA=cy;//送数据口
SCLOUT;
SCL1;//拉高时钟线
delayus(5);//延时
SCL0;//拉低时钟线
delayus(5);//延时
}
I2C_RecvACK();
}
//**************************************
//从I2C总线接收一个字节数据
//**************************************
ucharI2C_RecvByte()
{
uchari;
uchardat=0,cy;
SDAOUT;
SCLOUT;
SDA1;//使能内部上拉,准备读取数据,
SDAIN;
for(i=0;i<8;i++)//8位计数器
{
dat<<=1;
SCL1;//拉高时钟线
delayus(5);//延时
if(SDADATA)
{
cy=1;
}
else
{
cy=0;
}
dat|=cy;//读数据
SCL0;//拉低时钟线
delayus(5);//延时
}
SDAOUT;
returndat;
}
//**************************************
//向I2C设备写入一个字节数据
//**************************************
voidSingle_WriteI2C(ucharREG_Address,ucharREG_data)
{
I2C_Start();//起始信号
I2C_SendByte(SlaveAddress);//发送设备地址+写信号
I2C_SendByte(REG_Address);//内部寄存器地址,
I2C_SendByte(REG_data);//内部寄存器数据,
I2C_Stop();//发送停止信号
}
//**************************************
//从I2C设备读取一个字节数据
//**************************************
ucharSingle_ReadI2C(ucharREG_Address)
{
ucharREG_data;
I2C_Start();//起始信号
I2C_SendByte(SlaveAddress);//发送设备地址+写信号
I2C_SendByte(REG_Address);//发送存储单元地址,从0开始
I2C_Start();//起始信号
I2C_SendByte(SlaveAddress+1);//发送设备地址+读信号
REG_data=I2C_RecvByte();//读出寄存器数据
I2C_SendACK
(1);//接收应答信号
I2C_Stop();//停止信号
returnREG_data;
}
//**************************************
//初始化MPU6050
//**************************************
voidInitMPU6050()
{
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);
}
voidlcd_printf(uchar*s,inttemp_data)
{
if(temp_data<0)
{
temp_data=-temp_data;
*s='-';
}
else*s='';
*++s=temp_data/100+0x30;
temp_data=temp_data%100;//取余运算
*++s=temp_data/10+0x30;
temp_data=temp_data%10;//取余运算
*++s=temp_data+0x30;
}
//****************************************
//LCD1602显示字符串
//****************************************
voidDisplayListChar(ucharX,ucharY,uchar*DData,ucharL)
{
ucharListLength=0;
Y&=0x1;
X&=0xF;
while(L--)
{
Disp1Char(X,Y,DData[ListLength]);
ListLength++;
X++;
}
}
//**************************************
//合成数据
//**************************************
intGetData(ucharREG_Address)
{
charH,L;
H=Single_ReadI2C(REG_Address);
L=Single_ReadI2C(REG_Address+1);
return(H<<8)+L;//合成数据
}
//**************************************
//在1602上显示10位数据
//**************************************
voidDisplay10BitData(intvalue,ucharx,uchary)
{
value/=64;//转换为10位数据
lcd_printf(dis,value);//转换数据显示
DisplayListChar(x,y,dis,4);//启始列,行,显示数组,显示长度
}
//以下是LCD1602相关文件
#defineucharunsignedchar
#defineuintunsignedint
#defineDATA_DIRP2DIR
#defineDATA_OUTP2OUT
#defineCLR_RSP6OUT&=~BIT3;//RS=0;
#defineSET_RSP6OUT|=BIT3;//RS=1;
#defineCLR_RWP6OUT&=~BIT4;//RW=0;
#defineSET_RWP6OUT|=BIT4;//RW=1;
#defineCLR_ENP6OUT&=~BIT5;//EN=0;
#defineSET_ENP6OUT|=BIT5;//EN=1;
voiddelay1(uintz);
voidwrite_com(ucharcom);
voidwrite_data(uchardat);
voidinit();
voiddisplay(void);
voidLocateXY(ucharx,uchary);
voidDisp1Char(ucharx,uchary,ucharDataByte);
voidDispStr(ucharx,uchary,uchar*ptr);
voidDispNChar(ucharx,uchary,ucharn,uchar*ptr);
#include"includes.h"
voiddelay1(uintz)
{
uintt,y;
for(t=z;t>0;t--)
for(y=110;y>0;y--);
}
/////////////////写命令///////////////
voidwrite_com(ucharcom)
{
CLR_RS;
CLR_RW;
CLR_EN;
DATA_OUT=com;
delay1(20);
SET_EN;
delay1(20);
CLR_EN;
delay1(20);
}
////////////////写数据///////////////
voidwrite_data(uchardat)
{
SET_RS;
CLR_RW;
CLR_EN;
DATA_OUT=dat;
delay1(20);
SET_EN;
delay1(20);
CLR_EN;
delay1(20);
}
/////////////////液晶初始化/////////////
voidinit()
{
delay1(30);
write_com(0x38);
delay1(10);
write_com(0x38);
delay1(10);
write_com(0x38);
write_com(0x38);
write_com(0x08);
write_com(0x01);
write_com(0x06);
write_com(0x0c);
}
voiddisplay(void)
{
write_com(0x80+0x40);
write_data(0x31);
}
/*******************************************
131函数名称:
LocateXY
132功能:
向液晶输入显示字符位置的坐标信息
133参数:
x--位置的列坐标0-15
134y--位置的行坐标0-1
135返回值:
无
136********************************************/
voidLocateXY(ucharx,uchary)
{
uchartemp;
temp=x&0x0f;
y&=0x01;
if(y)temp|=0x40;//如果在第2行
temp|=0x80;//第一行为0x80,第二行为0x80+0x40
write_com(temp);
}
/*******************************************
149函数名称:
Disp1Char
150功能:
在某个位置显示一个字符
151参数:
x--位置的列坐标0-15
152y--位置的行坐标0-1
153data--显示的字符数据
154返回值:
无
155********************************************/
voidDisp1Char(ucharx,uchary,ucharDataByte)
{
LocateXY(x,y);
write_data(DataByte);
}
/***********************************************
2函数名称:
DispStr
63功能:
让液晶从某个位置起连续显示一个字符串
64参数:
x--位置的列坐标0-15
65y--位置的行坐标0-1
166ptr--指向字符串存放位置的指针
167返回值:
无
168***********************************************/
voidDispStr(ucharx,uchary,uchar*ptr)
{
uchar*temp;
uchari,n=0;
temp=ptr;
while(*ptr++!
='\0')n++;//计算字符串有效字符的个数
for(i=0;i{
Disp1Char(x++,y,temp[i]);
if(x==0x0f)
{
x=0;
y^=1;//异或操作,换行
}
}
}
/*******************************************
188函数名称:
DispNchar
189功能:
让液晶从某个位置起连续显示N个字符
190参数:
x--位置的列坐标0-15
191y--位置的行坐标0-1
192n--字符个数
193ptr--指向字符存放位置的指针
194返回值:
无
195********************************************/
voidDispNChar(ucharx,uchary,ucharn,uchar*ptr)
{
uchari;
for(i=0;i{
Disp1Char(x++,y,ptr[i]);
if(x==0x0f)
{
x=0;
y^=1;
}
}
}