|
输出的数据不停的跳变,为什么?希望有人指教一下。
#include<reg52.h>
#include<math.h>
#include<stdio.h>
#include<intrins.h>
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
//***********************************
// 单片机端口定义
//***********************************
sbit RS=P1^3; //寄存器
sbit CS=P1^2; //片选
sbit SCLK=P1^1; //串行时钟输入
sbit SID=P1^0; //串行数据输入
sbit SCL=P0^2; //I2C时钟引脚定义
sbit SDA=P0^3; //I2C数据引脚定义
//***********************************
// 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 //存储最近的X轴、Y轴、Z轴加速度感应器的测量值
#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 GYRO_XOUT_H 0X43 //存储最近的X轴、Y轴、Z轴陀螺仪感应器的测量值 */
#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为读取
//*************************************
// LCD缓存区分配
//*************************************
uchar xdata display_buf[32]=0x20;
//显示存贮器安排 第一行 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14,15
//
//显示值 A 0 0 0 - 0 0 0 - 0 0 0
//
// 第二行 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
//
//显示值 G - 0 0 0 - 0 0 0 0 0 0
#define ACCEL_XOUT 0 //按照上述显示缓存区定义的显示X轴加速度显示第一位位置
#define ACCEL_YOUT 7 //按照上述显示缓存区定义的显示Y轴加速度显示第一位位置
#define ACCEL_ZOUT 12 //按照上述显示缓存区定义的显示Z轴加速度显示第一位位置
#define GYRO_XOUT 16 //按照上述显示缓存区定义的显示X轴角速度显示第一位位置
#define GYRO_YOUT 23 //按照上述显示缓存区定义的显示Y轴角速度显示第一位位置
#define GYRO_ZOUT 29 //按照上述显示缓存区定义的显示Z轴角速度显示第一位位置
//********************延时子程序***********//
void delay(uint i)
{
uint j,k;
for(j=0;j<i;j++)
for(k=0;k<50;k++);
}
//**************************************
//延时5微秒(STC90C52RC@12M)
//不同的工作环境,需要调整此函数
//当改用1T的MCU时,请调整此延时函数
//**************************************
void Delay5us()
{
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
}
//**************************************
//I2C起始信号
//**************************************
void I2C_Start()
{
SDA = 1; //拉高数据线
SCL = 1; //拉高时钟线
Delay5us(); //延时
SDA = 0; //产生下降沿
Delay5us(); //延时
SCL = 0; //拉低时钟线
}
//**************************************
//I2C停止信号
//**************************************
void I2C_Stop()
{
SDA = 0; //拉低数据线
SCL = 1; //拉高时钟线
Delay5us(); //延时
SDA = 1; //产生上升沿
Delay5us(); //延时
}
//**************************************
//I2C发送应答信号
//入口参数:ack (0:ACK 1:NAK)
//**************************************
void I2C_SendACK(bit ack)
{
SDA = ack; //写应答信号 ACK=0表示应答 ACK=1表示不应答
SCL = 1; //拉高时钟线
Delay5us(); //延时
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
//**************************************
//I2C接收应答信号
//**************************************
bit I2C_RecvACK()
{
SCL = 1; //拉高时钟线
Delay5us(); //延时
CY = SDA; //读应答信号
SCL = 0; //拉低时钟线
Delay5us(); //延时
return CY;
}
//**************************************
//向I2C总线发送一个字节数据
//**************************************
void I2C_SendByte(uchar dat)
{
uchar i;
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1; //把当前最高位左移入PSW寄存器的CY位
SCL=0;
Delay5us();
SDA = CY; //把CY位内容发送到I2C总线
SCL = 1; //拉高时钟线
Delay5us(); //延时
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
I2C_RecvACK();
}
//**************************************
//从I2C总线接收一个字节数据
//**************************************
uchar I2C_RecvByte()
{
uchar i;
uchar dat = 0;
SDA = 1; //使能内部上拉,准备读取数据,
for (i=0; i<8; i++) //8位计数器
{
SCL = 1; //拉高时钟线
Delay5us(); //延时
dat=(dat<<1) |SDA; //读数据
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
return dat;
}
//**************************************
//向I2C设备写入一个字节数据
//**************************************
void Single_WriteI2C(uchar REG_Address,uchar REG_data)
{
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress); //写入地址字节数据
I2C_SendByte(REG_Address); //内部寄存器地址,
I2C_SendByte(REG_data); //内部寄存器数据,
I2C_Stop(); //发送停止信号
}
//**************************************
//从I2C设备读取一个字节数据
//**************************************
uchar Single_ReadI2C(uchar REG_Address)
{
uchar REG_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(); //停止信号
return REG_data;
}
//**************************************
//初始化MPU6050
//**************************************
void InitMPU6050()
{
Single_WriteI2C(PWR_MGMT_1, 0x00); //解除休眠状态
Single_WriteI2C(SMPLRT_DIV, 0x07); //陀螺仪采样率,典型值:0x07(125Hz)
Single_WriteI2C(CONFIG, 0x06); //低通滤波频率,典型值:0x06(5Hz)
Single_WriteI2C(GYRO_CONFIG, 0x18); //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
Single_WriteI2C(ACCEL_CONFIG, 0x01); //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
}
//**************************************
//合成数据
//**************************************
int GetData(uchar REG_Address)
{
char H,L;
H=Single_ReadI2C(REG_Address);
L=Single_ReadI2C(REG_Address+1);
return (H<<8)+L; //合成数据
}
//***************************************
// 加速度传感器值 X、Y、Z轴
//***************************************
void ACCEL()
{ uchar i,x,y,z;
uint t;
x=GetData(ACCEL_XOUT_H); //显示X轴加速度
i=x/100;
t=x%100;
display_buf[ACCEL_XOUT+3]=i+0x30; //取百位数
i=t/10;
t=t%10;
display_buf[ ACCEL_XOUT+4]=i+0x30; //取十位数
i=t%10;
display_buf[ ACCEL_XOUT+5]=i+0x30; //取个位数
display_buf[ ACCEL_XOUT+0]='A';
y=GetData(ACCEL_YOUT_H); //显示Y轴加速度
i=y/100;
t=y%100;
display_buf[ACCEL_YOUT+1]=i+0x30; //取百位数
i=t/10;
t=t%10;
display_buf[ACCEL_YOUT+2]=i+0x30; //取十位数
i=t%10;
display_buf[ACCEL_YOUT+3]=i+0X30; //取个位数
display_buf[ACCEL_YOUT+0]='-';
z=GetData(ACCEL_ZOUT_H); //显示Z轴加速
i=z/100;
t=z%100;
display_buf[ACCEL_ZOUT+1]=i+0x30; //取百位数
i=t/10;
t=t%10;
display_buf[ACCEL_ZOUT+2]=i+0x30; //取十位数
i=t%10;
display_buf[ACCEL_ZOUT+3]=i+0X30; //取个位数
display_buf[ACCEL_ZOUT+0]='-';
}
//***********************************************
// 陀螺仪
//***********************************************
void GYRO()
{
uchar i,x,y,z;
uint t;
x=GetData(GYRO_XOUT_H);
i=x/100;
t=x%100;
display_buf[GYRO_XOUT+3]=i+0x30;
i=t/10;
t=t%10;
display_buf[GYRO_XOUT+4]=i+0x30;
i=t%10;
display_buf[GYRO_XOUT+5]=i+0x30;
display_buf[GYRO_XOUT+2]='-';
display_buf[GYRO_XOUT+0]='G';
y=GetData(GYRO_YOUT_H);
i=y/100;
t=y%100;
display_buf[GYRO_YOUT+1]=i+0x30;
i=t/10;
t=t%10;
display_buf[GYRO_YOUT+2]=i+0x30;
i=t%10;
display_buf[GYRO_YOUT+3]=i+0x30;
display_buf[GYRO_YOUT+0]='-';
z=GetData(GYRO_ZOUT_H);
i=z/100;
t=z%100;
display_buf[GYRO_ZOUT+0]=i+0x30;
i=t/10;
t=t%10;
display_buf[GYRO_ZOUT+1]=i+0x30;
i=t%10;
display_buf[GYRO_ZOUT+2]=i+0x30;
}
//***************写指令到LCD模块***********//
void tranfser_command(int data1)
{
char i;
CS=0;
RS=0;
for(i=0;i<8;i++)
{
SCLK=0;
if(data1&0x80)
SID=1;
else SID=0;
delay(5);
SCLK=1;
delay(5);
data1=data1<<=1;
}
}
//****************写数据到LCD模块***********//
void tranfser_data(int data2)
{
char i;
CS=0;
RS=1;
for(i=0;i<8;i++)
{
SCLK=0;
if(data2&0x80) SID=1;
else SID=0;
delay(1);
SCLK=1;
delay(1);
data2=data2<<=1;
}
}
//*********LCD模块初始化***********//
void initial_lcd()
{
CS=0;
delay(10);
tranfser_command(0x38); //设置16X2显示,5X7点阵,8位数据接口
delay(10);
tranfser_command(0x0c); //显示模式设置:显示开,无光标,光标不闪烁
delay(10);
tranfser_command(0x01); //清屏幕指令,将以前的显示内容清除
delay(10);
tranfser_command(0x06); //显示模式设置:光标右移,字符不移
delay(10);
}
//*******在指定的列和位显示指定的字母、数字、符号****//
void disp_char()
{
uint i;
tranfser_command(0x80+0+0);
for(i=0;i<16;i++)
{
tranfser_data(display_buf[i]);
}
tranfser_command(0x80+0x40+0);
for(i=16;i<32;i++)
{
tranfser_data(display_buf[i]);
}
}
//*********LCD清屏******************//
void clr_screen()
{
uchar i;
for(i=0;i<32;i++) display_buf[i]=0x20;
disp_char();
}
void main()
{
delay(500);
initial_lcd(); //LCD屏初始化
clr_screen(); //LCD清屏
InitMPU6050();
delay(150);
while(1)
{ delay(10000);
ACCEL(); //加速度显示
GYRO(); //陀螺仪显示
}
} |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|