位移传感器MPU6050的使用

MPU6050为3轴加速度3轴陀螺仪传感器,可以测量三方向位置信息以及加速度信息。但MPU6050采用IIC总线传输,于是操作起来比其他的位移传感器复杂了不少。

此篇以89C51单片机为主,实现MPU6050的应用。

89C51+LCD1602+IIC

1.LCD1602液晶显示屏。

由名称可知,此种显示屏有2行,每行可显示16个字符。

对于LCD1602液晶显示屏的详细操作请参考有关文档及程序,这里不再赘述。

为了使代码简介清晰,我对LCD1602的代码进行了封装,方便调用。下面贴出LCD1602.H:

sbit RS = P1^0;   //定义端口 
sbit RW = P1^1;
sbit EN = P2^5;
sbit DU = P2^0;
sbit WE = P2^1;

#define RS_CLR RS=0 
#define RS_SET RS=1
#define RW_CLR RW=0 
#define RW_SET RW=1 
#define EN_CLR EN=0
#define EN_SET EN=1
#define DataPort P0
//****************************************
//整数转字符串
//转换结果保存在uchar型的字符数组里
//函数只是负责转换三位数的整数,要是实现更多位的转换可以修改代码
//****************************************
void lcd_printf(uchar *s,int temp_data)
{
	if(temp_data<0)
	{
		temp_data=-temp_data; //temp_data为负数则转化为正数运算
		*s='-';					 //此时字符串应该由‘-’负号开始
	}
	else *s=' ';				 //正数的话由空白字符开始  此时s[0]='-'或者‘ ’
	*++s =temp_data/100+0x30;	  //百位数字转为ASCII码形式	 s[1]为千位数字的ASCII码
	temp_data=temp_data%100;     //取余运算
	*++s =temp_data/10+0x30;	  //同样,此处得到十位数字的ASCII码,赋给s[2]
	temp_data=temp_data%10;      //取余运算
	*++s =temp_data+0x30; 		   //得到个位数字的ASCII码,赋给s[3]
}


void cmg88()//关数码管,点阵函数
{
DU=1;  
P0=0X00;
DU=0;
}
/*------------------------------------------------
 uS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 长度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{   
 while(--t);
}
/*------------------------------------------------
 mS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{
     
 while(t--)
 {
     //大致延时1mS
     DelayUs2x(245);
	 DelayUs2x(245);
 }
}
/*------------------------------------------------
              判忙函数
------------------------------------------------*/
 bit LCD_Check_Busy(void) 
 { 
 DataPort= 0xFF; 
 RS_CLR; 
 RW_SET; 
 EN_CLR; 
 _nop_(); 
 EN_SET;
 return (bit)(DataPort & 0x80);
 }
/*------------------------------------------------
              写入命令函数
------------------------------------------------*/
 void LCD_Write_Com(unsigned char com) 
 {  
 while(LCD_Check_Busy()); //忙则等待
 RS_CLR; 
 RW_CLR; 
 EN_SET; 
 DataPort= com; 
 _nop_(); 
 EN_CLR;
 }
/*------------------------------------------------
              写入数据函数
------------------------------------------------*/
 void LCD_Write_Data(unsigned char Data) 
 { 
 while(LCD_Check_Busy()); //忙则等待
 RS_SET; 
 RW_CLR; 
 EN_SET; 
 DataPort= Data; 
 _nop_();
 EN_CLR;
 }

/*------------------------------------------------
                清屏函数
------------------------------------------------*/
 void LCD_Clear(void) 
 { 
 LCD_Write_Com(0x01); 
 DelayMs(5);
 }
/*------------------------------------------------
              写入字符串函数
------------------------------------------------*/
 void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) 
 {     
 if (y == 0) 
 	{     
	 LCD_Write_Com(0x80 + x);     //表示第一行
 	}
 else 
 	{      
 	LCD_Write_Com(0xC0 + x);      //表示第二行
 	}        
 while (*s) 
 	{     
 LCD_Write_Data( *s);     
 s ++;     
 	}
 }
/*------------------------------------------------
              写入字符函数
------------------------------------------------*/
 void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) 
 {     
 if (y == 0) 
 	{     
 	LCD_Write_Com(0x80 + x);     
 	}    
 else 
 	{     
 	LCD_Write_Com(0xC0 + x);     
 	}        
 LCD_Write_Data( Data);  
 }
/*------------------------------------------------
              初始化函数
------------------------------------------------*/
 void LCD_Init(void) 
 {
   LCD_Write_Com(0x38);    /*显示模式设置*/ 
   DelayMs(5); 
   LCD_Write_Com(0x38); 
   DelayMs(5); 
   LCD_Write_Com(0x38); 
   DelayMs(5); 
   LCD_Write_Com(0x38);  
   LCD_Write_Com(0x08);    /*显示关闭*/ 
   LCD_Write_Com(0x01);    /*显示清屏*/ 
   LCD_Write_Com(0x06);    /*显示光标移动设置*/ 
   DelayMs(5); 
   LCD_Write_Com(0x0C);    /*显示开及光标设置*/
   }

该头文件使用时需要

cmg88();//关数码管,

LCD_Init();//液晶初始化

LCD_Clear();//清屏

之后就可以利用LCD_Write_Char函数写一个字符,或者利用LCD_Write_String写一个字符串。


2.IIC总线

常见总线有IIC总线,SPI总线等。IIC采用双线控制,接入设备简单,SPI采用4线(3线也可以),全双工工作。

有关IIC的知识可以参考上篇文章:http://blog.csdn.net/yibu_refresh/article/details/23354245

这里也贴出IIC.H

/*********************************************
*IIC总线程序
		void init()初始化
		void write_add(uchar address,uchar date)写
		uchar read_add(uchar address) 读
***********************************************/
#define uchar unsigned char
sbit sda=P2^0;
sbit scl=P2^1;
uchar a;
void delay1()
{ ;; }
void start()  //开始信号
{	
	sda=1;
	delay1();
	scl=1;
	delay1();
	sda=0;
	delay1();
}

void stop()   //停止
{
	sda=0;
	delay1();
	scl=1;
	delay1();
	sda=1;
	delay1();
}

void respons()  //应答
{
	uchar i;
	scl=1;
	delay1();
	while((sda==1)&&(i<250))i++;
	scl=0;
	delay1();
}

void init()
{
	sda=1;
	delay1();
	scl=1;
	delay1();
}

void write_byte(uchar date)
{
	uchar i,temp;
	temp=date;


	for(i=0;i<8;i++)
	{
		temp=temp<<1;
		scl=0;
	    delay1();
		sda=CY;
		delay1();
		scl=1;
		delay1();
	//	scl=0;
     //   delay();
	}
	scl=0;
	delay1();
	sda=1;
	delay1();
}

uchar read_byte()
{
	uchar i,k;
	scl=0;
	delay1();
	sda=1;
	delay1();
	for(i=0;i<8;i++)
	{
		scl=1;
		delay1();	
		k=(k<<1)|sda;
		scl=0;
		delay1();	
	}
	return k;
}

void write_add(uchar address,uchar date)
{
	start();
	write_byte(0xa0);
	respons();
	write_byte(address);
	respons();
	write_byte(date);
	respons();
	stop();
}

uchar read_add(uchar address)
{
	uchar date;
	start();
	write_byte(0xa0);
	respons();
	write_byte(address);
	respons();
	start();
	write_byte(0xa1);
	respons();
	date=read_byte();
	stop();
	return date;
}

3.MPU6050某些参数定义:

MPU6050.H:

//****************************************
// 定义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
#define	ACCEL_XOUT_L	0x3C     //x轴加速度
#define	ACCEL_YOUT_H	0x3D
#define	ACCEL_YOUT_L	0x3E	 //y轴加速度
#define	ACCEL_ZOUT_H	0x3F
#define	ACCEL_ZOUT_L	0x40	 //z轴加速度
#define	TEMP_OUT_H		0x41
#define	TEMP_OUT_L		0x42
#define	GYRO_XOUT_H		0x43
#define	GYRO_XOUT_L		0x44	//x轴角速度
#define	GYRO_YOUT_H		0x45
#define	GYRO_YOUT_L		0x46	 //y轴角速度
#define	GYRO_ZOUT_H		0x47
#define	GYRO_ZOUT_L		0x48	 //z轴角速度
#define	PWR_MGMT_1		0x6B	//电源管理,典型值:0x00(正常启用)
#define	WHO_AM_I		0x75	//IIC地址寄存器(默认数值0x68,只读)
//**************************************
//初始化MPU6050
//**************************************
void InitMPU6050()
{
	write_add(PWR_MGMT_1, 0x00);	//解除休眠状态
	write_add(SMPLRT_DIV, 0x07);
	write_add(CONFIG, 0x06);
	write_add(GYRO_CONFIG, 0x18);
	write_add(ACCEL_CONFIG, 0x01);
}


4.主程序:

/*
 * MPU6050模块测试程序
 * MCU: STC89C52 
 * OSCILLATOR:11.0592M
 * LCD:LCD1602
 *
 */
#include <REG52.H>	
#include <math.h>  
#include <stdio.h>
#include <INTRINS.H>
#include "IIC.h"
#include "LCD1602.h"
#include "MPU6050.h"

//****************************************
//定义类型及变量
//****************************************
uchar dis[4];							//显示数字(-511至512)的字符数组
//**************************************
//合成数据:从IIC总线上读取两次,合成16位数据
//**************************************
int GetData(uchar REG_Address)
{
	char H,L;
	H=read_add(REG_Address);
	L=read_add(REG_Address+1);
	return (H<<8)+L;   //合成数据
}
//**************************************
//在1602上显示10位数据
//**************************************
void Display10BitData(int value,uchar x,uchar y)
{
	value/=64;							//转换为10位数据 
	lcd_printf(dis, value);				//转换数据显示
	LCD_Write_String(x,y,dis);			//启始列,行,显示数组,显示长度
}
//*********************************************************
//主程序
//*********************************************************
void delay(uchar x)
{
	uchar i,j;
	for(i=x;i>0;i--)
	for(j=110;j>0;j--);
}
void main()
{ 
	delay(500);		//上电延时		
	LCD_Init();		//液晶初始化
	init();         //IIC总线初始化
	InitMPU6050();	//初始化MPU6050
	delay(150);
	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);	//显示Z轴角速度
		delay(500);
	}
}
这样程序看起来就简单了许多,也方便了很多。

  • 4
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值