for(j=0;j<120;j++);
}
/********检测忙位**********/
voidCheck_Busy(void)
{
DDRA=0x00;//置总线为读入
asm(nop);
asm(nop);
RS=0;
RW=1;
EN=1;
while((DataPort&0x80)==0x80);//忙则等待
EN=0;
DDRA=0xFF;//置总线为输出
}
/********写命令**********/
voidwrite_(unsignedcharCmd)
{
Check_Busy();
RS=0;
RW=0;
DataPort=Cmd;
delay
(1);
EN=1;
delay
(1);
EN=0;
}
/********写数据**********/
voidwrite_date(unsignedcharData)
{
Check_Busy();
delay
(1);
RS=1;
RW=0;
DataPort=Data;
delay
(1);
EN=1;
delay
(1);
EN=0;
}
/******液晶屏初始化******/
voidLCD_init(void)
{
PSB=1;
write_(0x34);//选择基本指令集
delay
(1);//大于40MS的延时程序
write_(0x30);//选择8bit数据流
delay
(1);
write_(0x0c);//开显示(无游标、不反白)
delay
(1);//延时大于100us
write_(0x01);//清除显示,并且设定地址指针为00H
delay
(1);//延时大于10ms
}
voidlcd_pos(ucharX,ucharY)
{
ucharpos;
if(X==0)
{X=0x80;}
elseif(X==1)
{X=0x90;}
elseif(X==2)
{X=0x88;}
elseif(X==3)
{X=0x98;}
pos=X+Y;
write_(pos);//显示地址
}
ucharqu_mo(ucharz)
{
switch(z)
{
case0:
return0x30;
case1:
return0x31;
case2:
return0x32;
case3:
return0x33;
case4:
return0x34;
case5:
return0x35;
case6:
return0x36;
case7:
return0x37;
case8:
return0x38;
case9:
return0x39;
default:
return0x2e;
}
}
voidshuzu0(unsignedchary0,unsignedcharx0)//显示高度
{
lcd_pos(y0,x0);
write_date(qu_mo(a[0]));
write_date(qu_mo(a[1]));
write_date(qu_mo(a[2]));
write_date(qu_mo(a[3]));
write_date(0x44);
lcd_pos(y0,x0);
delays
(1);
}
voidshuzu1(unsignedchary1,unsignedcharx1)//显示X
{
lcd_pos(y1,x1);
write_date(b[0]);
write_date(qu_mo(b[1]));
write_date(qu_mo(b[2]));
write_date(qu_mo(b[3]));
write_date(qu_mo(b[4]));
write_date(0x44);
lcd_pos(y1,x1);
delays
(1);
}
voidshuzu2(unsignedchary2,unsignedcharx2)//显示Y
{
lcd_pos(y2,x2);
write_date(c[0]);
write_date(qu_mo(c[1]));
write_date(qu_mo(c[2]));
write_date(qu_mo(c[3]));
write_date(qu_mo(c[4]));
write_date(0x44);
lcd_pos(y2,x2);
delays
(1);
}
voidshuzu3(unsignedchary3,unsignedcharx3)//显示Z
{
lcd_pos(y3,x3);
write_date(e[0]);
write_date(qu_mo(e[1]));
write_date(qu_mo(e[2]));
write_date(qu_mo(e[3]));
write_date(qu_mo(e[4]));
write_date(0x44);
lcd_pos(y3,x3);
delays
(1);
}
/***********************************************
显示字符串
x:
横坐标值,围0~8
y:
纵坐标值,围1~4
************************************************/
voidLCD_PutString(unsignedcharx,unsignedchary,unsignedchar*s)
{
lcd_pos(x,y);
while(*s>0)
{
write_date(*s);
s++;
delays
(1);
}
}
voidsda_high()//SDA高电平的产生
{
DDRB_DDRB4=1;
SDA=1;
_asm(nop);
_asm(nop);
_asm(nop);
_asm(nop);
return;
}
//**************************************
//SDA低电平的产生
//**************************************
voidsda_low()//SDA低电平的产生
{
DDRB_DDRB4=1;
SDA=0;
_asm(nop);
_asm(nop);
_asm(nop);
_asm(nop);
return;
}
//**************************************
//SCL高电平产生
//**************************************
voidscl_high()//SCL高电平产生
{
DDRB_DDRB5=1;;
SCL=1;
_asm(nop);
_asm(nop);
_asm(nop);
_asm(nop);
return;
}
//**************************************
//SCL低电平的产生
//**************************************
voidscl_low()//SCL低电平的产生
{
DDRB_DDRB5=1;;
SCL=0;
_asm(nop);
_asm(nop);
_asm(nop);
_asm(nop);
return;
}
//**************************************
//I2C起始信号
//**************************************
voidI2C_Start()
{
sda_high();//拉高数据线
scl_high();//拉高时钟线
delayM
(1);//延时
sda_low();//产生下降沿
delayM
(1);//延时
scl_low();//拉低时钟线
}
//**************************************
//I2C停止信号
//**************************************
voidI2C_Stop()
{
sda_low();//拉低数据线
scl_high();//拉高时钟线
delayM
(1);//延时
sda_high();//产生上升沿
delayM
(1);//延时
}
//**************************************
//I2C发送应答信号
//入口参数:
ack(0:
ACK1:
NAK)
//**************************************
voidI2C_SendACK(charack)
{
if(ack)
sda_high();
else
sda_low();//写应答信号
scl_high();//拉高时钟线
delayM
(1);//延时
scl_low();//拉低时钟线
delayM
(1);//延时
}
//**************************************
//I2C接收应答信号
//**************************************
ucharI2C_RecvACK()
{
DDRB_DDRB4=0;
scl_high();//拉高时钟线
DDRB_DDRB4=0;
delayM
(1);//延时
if(SDA==1)
{
cy=1;
}
else
{
cy=0;
}
//cy=SDA;//读应答信号
scl_low();//拉低时钟线
delayM
(1);//延时
DDRB_DDRB4=1;
returncy;
}
//**************************************
//向I2C总线发送一个字节数据
//**************************************
voidI2C_SendByte(uchardat)
{
uchari;
for(i=0;i<8;i++)//8位计数器
{
if((dat<
{
sda_high();
}
else
{
sda_low();
}
//SDA=cy;//送数据口
scl_high();//拉高时钟线
delayM
(1);//延时
scl_low();//拉低时钟线
delayM
(1);//延时
}
I2C_RecvACK();
}
//**************************************
//从I2C总线接收一个字节数据
//**************************************
ucharI2C_RecvByte()
{
uchari;
uchardat=0,cy;
sda_high();//使能部上拉,准备读取数据,
DDRB_DDRB4=0;
for(i=0;i<8;i++)//8位计数器
{
dat<<=1;
scl_high();//拉高时钟线
delayM
(1);//延时
if(SDA==1)
{
cy=1;
}
else
{
cy=0;
}
dat|=cy;//读数据
scl_low();//拉低时钟线
delayM
(1);//延时
}
DDRB_DDRB4=1;
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);
}
//**************************************
//合成数据
//**************************************
intGetData(ucharREG_Address)
{
ucharH,L;
H=Single_ReadI2C(REG_Address);
L=Single_ReadI2C(REG_Address+1);
return(H<<8)+L;//合成数据
}
shortMPU6050_Get_Angle(floatx,floaty,floatz,uchardir)
{
floattemp;
floatres=0;
switch(dir)
{
case0:
//与自然Z轴的角度
temp=sqrt((x*x+y*y))/z;
res=atan(temp);
break;
case1:
//与自然X轴的角度
temp=x/sqrt((y*y+z*z));
res=atan(temp);
break;
case2:
//与自然Y轴的角度
temp=y/sqrt((x*x+z*z));
res=atan(temp);
break;
}
returnres*.0/3.1415926;//把弧度转换成角度
}
voidmain(void)
{
DisableInterrupts;
PLL_Init();
//PIT_Init();
delay(300);//上电延时
InitMPU6050();//初始化MPU6050
LCD_init();
EnableInterrupts;
while
(1)
{
x1=GetData(ACCEL_XOUT_H);//X轴输出值,待转化为角度
y1=GetData(ACCEL_YOUT_H);//
z1=GetData(ACCEL_ZOUT_H);//
X=MPU6050_Get_Angle(x1,y1,z1,0)*10.0;//把得到的角度扩大十倍
Y=MPU6050_Get_Angle(x1,y1,z1,1)*10.0;
Z=MPU6050_Get_Angle(x1,y1,z1,2)*10.0;
//显示角度
if(X>=0)
b[0]=0x2b;