求助三轴加速度MMA8451的使用程序和使用方法?
我在做小车,用到三轴加速度MMA8451,但论坛没有MMA8451的使用程序和使用方法?求哪位大侠帮一下小弟! 也可以发我邮箱1216529013@qq.com,小弟感激不尽! void main(){
unsigned char x, y, z,v=0,tv;
char piancha=0;
uchar jiasudu=0;//
uchar jiao=0;
// float jiasudu=0.0001;//
// float jiao=0.0001;
init_12864();
clear();
// locate( 1, 1 );write_hz("偏离垂直方向角度");
delayms(10);
TMOD=0x21; //定时T1方式2,接P3.5C/T=0,M1=1,定时T0方式1, M0=1 接P3.4
SCON=0x60; //8 bitSM1=SM2=1,SM0=0, REN=0
TL1=0xfd; //9600
TH1=0xfd;
TR1=1;
ET0=1;
EA=1;
MMA845x_init(); //初始化MMA845x
MMA845x_readbyte( 0x08);
MMA845x_readbyte( 0x04);
MMA845x_readbyte( 0x02);
v= MMA845x_readbyte(WHO_AM_I_REG); //把读取的字节赋给v
if((v == MMA8451Q_ID)||(v == MMA8452Q_ID)||(v == MMA8453Q_ID))
{
send232byte('O');
send232byte('K');
send232byte('!');
}
else
{
send232byte('F');
send232byte('a');
send232byte('i');
send232byte('l');
send232byte('!');
}
while(1)
{ //读取重力信息
x = MMA845x_readbyte(OUT_X_MSB_REG); //x轴重力信息
y = MMA845x_readbyte(OUT_Y_MSB_REG); //y轴重力信息
z = MMA845x_readbyte(OUT_Z_MSB_REG); //z轴重力信息
send232byte(0x55);
send232byte(0xAA);
send232byte(x);
send232byte(y);
send232byte(z);
if(x>127)//读取8位数据只读取z轴的数据
{
tv=~x+1; //取反加一
send232byte('-');locate( 2, 1 ); write_hz("x=-");
}
else
{
send232byte('+'); locate( 2, 1 ); write_hz("x=+");
tv=x;
}
//
// // jiao=(atan(x/z)*180.0/3.1415926)*1000; //角度计算
// // jiao=((float)(acos(tv/63))*180/3.14)*1000; //角度计算
// // jiaodu=jiao%10000/1000;
// jiaodu=jiao%10000%1000/100;
// jiaodu=jiao%10000%1000%100/10;
// jiaodu=jiao%10000%1000%100%10;
// locate( 2, 3 );
// // write_number(jiaodu);
// write_number(jiaodu);
// write_number(jiaodu);
// write_number(jiaodu);
jiasudu=(((float)tv)/0x3f)*10000;//计算加速度值大小
//jiasud=jiasudu%10000/1000;
jiasud=jiasudu%10000%1000/100;
jiasud=jiasudu%10000%1000%100/10;
jiasud=jiasudu%10000%1000%100%10;
// jiasud=jiasudu%10000%1000%100/10;
locate( 2, 3 );
//write_number(jiasud);
write_number(jiasud);
write_number(jiasud);delayms(1);
write_number(jiasud);
if(y>127)//读取8位数据只读取z轴的数据
{
tv=~y+1; //取反加一
send232byte('-');locate( 3, 1 ); write_hz("y=-");
}
else
{
send232byte('+'); locate( 3, 1 ); write_hz("y=+");
tv=y;
}
// jiao=((float)(acos(tv/63))*180/3.14)*1000; //角度计算
// jiaodu=jiao%10000/1000;
// jiaodu=jiao%10000%1000/100;
// jiaodu=jiao%10000%1000%100/10;
// jiaodu=jiao%10000%1000%100%10;
// locate( 3, 3 );
// write_number(jiaodu);
// write_number(jiaodu);
// write_number(jiaodu);
// write_number(jiaodu);
jiasudu=(((float)tv)/0x3f)*10000;//计算加速度值大小
jiasud=jiasudu%10000/1000;
jiasud=jiasudu%10000%1000/100;
jiasud=jiasudu%10000%1000%100/10;
jiasud=jiasudu%10000%1000%100%10;
locate( 3, 3 );
// write_number(jiasud);
write_number(jiasud);
write_number(jiasud);delayms(1);
write_number(jiasud);
if(z>127)//读取8位数据只读取z轴的数据
{
tv=~z+1; //取反加一
send232byte('-');locate( 4, 1 ); write_hz("z=-");
}
else
{
send232byte('+'); locate( 4, 1 ); write_hz("z=+");
tv=z;
}
// jiao=((float)(acos(tv/63))*180/3.14)*1000; //角度计算
// jiaodu=jiao%10000/1000;
// jiaodu=jiao%10000%1000/100;
// jiaodu=jiao%10000%1000%100/10;
// jiaodu=jiao%10000%1000%100%10;
// locate( 4, 3 );
// write_number(jiaodu);
// write_number(jiaodu);
// write_number(jiaodu);
// write_number(jiaodu);
// printf("偏离垂直方向角度=%f",jiao);
jiasudu=(((float)tv)/0x3f)*10000;//计算加速度值大小
//jiasud=jiasudu%10000/1000;
jiasud=jiasudu%1000/100;
jiasud=jiasudu%100/10;
jiasud=jiasudu%100%10;
locate( 4, 3 );
// write_number(jiasud);
write_number(jiasud);
write_number(jiasud);delayms(1);
write_number(jiasud);
//getAll();
}
}
为啥我测不出角度值啊,!难道转换公式不对吗!请大侠 帮助 楼主,有关于MMA8451加速度传感器的资料吗?发我一份吧,wangyao19920204@qq.com 多谢! 楼主能发我一份三轴加速度传感器的资料吗??渴求 1249924451@qq.com 渴望资料1131038786@qq.com 我在弄,现在差不多了...
本帖最后由 viqomk 于 2013-3-31 14:51 编辑
uchar tem;
char AGL;
RD_IIC(0,OUT_X_MSB,tem,6);//连续读6单元数据,代表XYX值
OUT.X = tem;
OUT.X <<=8;
OUT.X |= tem;
OUT.Y = tem;
OUT.Y <<=8;
OUT.Y |= tem;
OUT.Z = tem;
OUT.Z <<=8;
OUT.Z |= tem;
if(tem > 0x7f)//负值
{OUT.X = ~(OUT.X>>2)+1;//求补码;移位,取反,加一
OUT.F_X = FALSE;//负数
}
else
{OUT.X >>= 2;//移位
OUT.F_X = TRUE;//正数
}
OUT.X &= 0x3fff;
//
if(tem > 0x7f)//负值
{OUT.Y = ~(OUTY>>2)+1;//求补码;移位,取反,加一
OUT.F_Y = FALSE;//负数
}
else
{OUT.Y >>= 2;//移位
OUT.F_Y = TRUE;//正数
}
OUT.Y &= 0x3fff;
//
if(tem > 0x7f)//负值
{OUT.Z = ~(OUT.Z>>2)+1;//求补码;移位,取反,加一
OUT.F_Z = FALSE;//负数
}
else
{OUT.Z >>= 2;//移位
OUT.F_Z = TRUE;//正数
}
OUT.Z &= 0x3fff; 这个玩意, 只能测"0 - 90 - 0"范围,当初以为能360度呢,有点失望.... 用 PIC的单片机,模拟IIC,我弄了几天{:sweat:}....第一次用PIC,感觉不太好用,还是AVR的好用
//***************************************
// GY-45 MMA8452 IIC测试程序
// 使用单片机STC89C51
// 晶振:11.0592M
// 显示:电脑串口波特率 9600
// 编译环境 Keil uVision4
// 参考宏晶网站24c04通信程序
// 时间:2013年3月16日
// QQ:1611182791
//****************************************
#include<REG52.H>
#include<math.h> //Keil library
#include<stdio.h> //Keil library
#include<INTRINS.H>
#define uchar unsigned char
#define uint unsigned int
sbit SCL=P1^0; //IIC时钟引脚定义
sbit SDA=P1^1; //IIC数据引脚定义
#define SlaveAddress 0x38 //定义器件在IIC总线中的从地址,根据SA0地址引脚不同修改
typedef unsigned charBYTE;
typedef unsigned short WORD;
BYTE BUF; //接收数据缓存区
uchar ge,shi,bai,qian,wan; //显示变量
intdis_datax,dis_datay,dis_dataz; //变量
int x,y,z;
float tempx,tempy,tempz;
float cos_phi_x,cos_phi_y,phi_x,phi_y;
void delay(unsigned int k);
void Init_MMA8452(void); //初始化MMA8452
void conversion(uint temp_data);
voidSingle_Write_MMA8452(uchar REG_Address,uchar REG_data); //单个写入数据
uchar Single_Read_MMA8452(uchar REG_Address); //单个读取内部寄存器数据
voidMultiple_Read_MMA8452(); //连续的读取内部寄存器数据
//------------------------------------
void Delay5us();
void Delay5ms();
void MMA8452_Start();
void MMA8452_Stop();
void MMA8452_SendACK(bit ack);
bitMMA8452_RecvACK();
void MMA8452_SendByte(BYTE dat);
BYTE MMA8452_RecvByte();
void MMA8452_ReadPage();
void MMA8452_WritePage();
ucharRX_DATA;
/*------------------------------------------------
函数声明
------------------------------------------------*/
void SendStr(unsigned char *s);
/*------------------------------------------------
串口初始化
------------------------------------------------*/
void InitUART(void)
{
SCON= 0x50; // SCON: 模式 1, 8-bit UART, 使能接收
TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit 重装
TH1 = 0xFD; // TH1:重装值 9600 波特率 晶振 11.0592MHz
TR1 = 1; // TR1:timer 1 打开
EA = 1; //打开总中断
ES = 1; //打开串口中断
}
/*------------------------------------------------
/*------------------------------------------------
发送一个字节
------------------------------------------------*/
void SendByte(unsigned char dat)
{
SBUF = dat;
Delay5ms();
//while(!TI);
if(TI==1)
TI = 0;
}
/*------------------------------------------------
发送一个字符串
------------------------------------------------*/
void SendStr(unsigned char *s)
{
while(*s!='\0')// \0 表示字符串结束标志,通过检测是否字符串末尾
{
SendByte(*s);
s++;
}
}
/*------------------------------------------------
串口中断程序
------------------------------------------------*/
void UART_SER (void) interrupt 4 //串行中断服务程序
{
// unsigned char RX_DATA; //定义临时变量
if(RI) //判断是接收中断产生
{
RI=0; //标志位清零
RX_DATA=SBUF; //读入缓冲区的值
P2=RX_DATA; //把值输出到P1口,用于观察
SBUF=RX_DATA; //把接收到的值再发回电脑端
}
if(TI) //如果是发送标志位,清零
TI=0;
}
//*********************************************************
void conversion(uint temp_data)
{
wan=temp_data/10000+0x30 ;
temp_data=temp_data%10000; //取余运算
qian=temp_data/1000+0x30 ;
temp_data=temp_data%1000; //取余运算
bai=temp_data/100+0x30 ;
temp_data=temp_data%100; //取余运算
shi=temp_data/10+0x30 ;
temp_data=temp_data%10; //取余运算
ge=temp_data+0x30;
}
/*******************************/
void delay(unsigned int k)
{
unsigned int i,j;
for(i=0;i<k;i++)
{
for(j=0;j<121;j++)
{;}}
}
/**************************************
延时5微秒(STC90C52RC@12M)
不同的工作环境,需要调整此函数,注意时钟过快时需要修改
当改用1T的MCU时,请调整此延时函数
**************************************/
void Delay5us()
{
_nop_();_nop_();_nop_();_nop_();
_nop_();/*_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_(); */
}
/**************************************
延时5毫秒(STC90C52RC@12M)
不同的工作环境,需要调整此函数
当改用1T的MCU时,请调整此延时函数
**************************************/
void Delay5ms()
{
WORD n = 1000;
while (n--)
{
_nop_();_nop_();_nop_();_nop_();
};
}
/**************************************
起始信号
**************************************/
void MMA8452_Start()
{
SDA = 1; //拉高数据线
SCL = 1; //拉高时钟线
Delay5us(); //延时
SDA = 0; //产生下降沿
Delay5us(); //延时
SCL = 0; //拉低时钟线
}
/**************************************
停止信号
**************************************/
void MMA8452_Stop()
{
SDA = 0; //拉低数据线
SCL = 1; //拉高时钟线
Delay5us(); //延时
SDA = 1; //产生上升沿
Delay5us(); //延时
}
/**************************************
发送应答信号
入口参数:ack (0:ACK 1:NAK)
**************************************/
void MMA8452_SendACK(bit ack)
{
SDA = ack; //写应答信号
SCL = 1; //拉高时钟线
Delay5us(); //延时
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
/**************************************
接收应答信号
**************************************/
bit MMA8452_RecvACK()
{
SCL = 1; //拉高时钟线
Delay5us(); //延时
CY = SDA; //读应答信号
SCL = 0; //拉低时钟线
Delay5us(); //延时
return CY;
}
/**************************************
向IIC总线发送一个字节数据
**************************************/
void MMA8452_SendByte(BYTE dat)
{
BYTE i;
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1; //移出数据的最高位
SDA = CY; //送数据口
SCL = 1; //拉高时钟线
Delay5us(); //延时
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
MMA8452_RecvACK();
}
/**************************************
从IIC总线接收一个字节数据
**************************************/
BYTE MMA8452_RecvByte()
{
BYTE i;
BYTE dat = 0;
SDA = 1; //使能内部上拉,准备读取数据,
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1;
SCL = 1; //拉高时钟线
Delay5us(); //延时
dat |= SDA; //读数据
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
return dat;
}
//******单字节写入*******************************************
void Single_Write_MMA8452(uchar REG_Address,uchar REG_data)
{
MMA8452_Start(); //起始信号
MMA8452_SendByte(SlaveAddress); //发送设备地址+写信号
MMA8452_SendByte(REG_Address); //内部寄存器地址
MMA8452_SendByte(REG_data); //内部寄存器数据
MMA8452_Stop(); //发送停止信号
}
//********单字节读取*****************************************
/*
uchar Single_Read_MMA8452(uchar REG_Address)
{uchar REG_data;
MMA8452_Start(); //起始信号
MMA8452_SendByte(SlaveAddress); //发送设备地址+写信号
MMA8452_SendByte(REG_Address); //发送存储单元地址,从0开始
MMA8452_Start(); //起始信号
MMA8452_SendByte(SlaveAddress+1); //发送设备地址+读信号
REG_data=MMA8452_RecvByte(); //读出寄存器数据
MMA8452_SendACK(1);
MMA8452_Stop(); //停止信号
return REG_data;
}
*/
//*********************************************************
//
//连续读出MMA8452内部加速度数据,地址范围0x01~0x06
//
//*********************************************************
void Multiple_read_MMA8452(void)
{ uchar i;
MMA8452_Start(); //起始信号
MMA8452_SendByte(SlaveAddress); //发送设备地址+写信号
MMA8452_SendByte(0x01); //发送存储单元地址,从0x01开始
MMA8452_Start(); //起始信号
MMA8452_SendByte(SlaveAddress+1); //发送设备地址+读信号
for (i=0; i<6; i++) //连续读取6个地址数据,存储中BUF
{
BUF = MMA8452_RecvByte(); //BUF存储0x32地址中的数据
if (i == 5)
{
MMA8452_SendACK(1); //最后一个数据需要回NOACK
}
else
{
MMA8452_SendACK(0); //回应ACK
}
}
MMA8452_Stop(); //停止信号
Delay5ms();
}
//*****************************************************************
//初始化MMA8452,根据需要请参考pdf进行修改************************
void Init_MMA8452()
{
Single_Write_MMA8452(0x2A,0x01); //
Single_Write_MMA8452(0x2B,0x02); //
}
//***********************************************************************
//显示x轴
void display_x()
{ //float tempx;
SendByte('X');
dis_datax=(BUF<<8)|BUF;//合成数据
dis_datax>>=4;
x=dis_datax;
if(dis_datax<0)
{
dis_datax=-dis_datax;
SendByte('-');
}
else SendByte('+');
tempx=(float)dis_datax; //计算数据和显示
conversion(tempx); //转换出显示需要的数据
SendByte(':');
SendByte(qian);
SendByte('.');
SendByte(bai);
SendByte(shi);
SendByte(' ');
}
//***********************************************************************
//显示y轴
void display_y()
{ //float tempy;
SendByte('Y');
dis_datay=(BUF<<8)|BUF;//合成数据
dis_datay>>=4;
//for (dis_data = 0x00;dis_data <= 0xfff;dis_data++)
//{
y=dis_datay;
if(dis_datay<0)
{
dis_datay=-dis_datay;
SendByte('-');
}
else SendByte('+');
tempy=(float)dis_datay; //计算数据和显示
conversion(tempy); //转换出显示需要的数据
SendByte(':');
SendByte(qian);
SendByte('.');
SendByte(bai);
SendByte(shi);
SendByte(' ');
// }
}
//***********************************************************************
//显示z轴
void display_z()
{ //float tempz;
SendByte('Z');
dis_dataz=(BUF<<8)|BUF; //合成数据
dis_dataz>>=4;
z=dis_dataz;
if(dis_dataz<0)
{
dis_dataz=-dis_dataz;
SendByte('-');
}
else SendByte('+');
tempz=(float)dis_dataz; //计算数据和显示
conversion(tempz); //转换出显示需要的数据
SendByte(':');
SendByte(qian);
SendByte('.');
SendByte(bai);
SendByte(shi);
SendByte(' ');
}
//***********************************************************************
//显示角度轴
void display_phix()
{
float temp;
temp=phi_x; //计算数据和显示
conversion(temp); //转换出显示需要的数据
SendByte(':');
SendByte(qian);
SendByte('.');
SendByte(bai);
SendByte(shi);
SendByte(13);
}
/****************************************************/
void display_phiy()
{
float temp;
temp=phi_y; //计算数据和显示
conversion(temp);//转换出显示需要的数据
SendByte(':');
SendByte(qian);
SendByte('.');
SendByte(bai);
SendByte(shi);
SendByte(13);
}
/*---------------------------------------------------------
偏转角度计算
---------------------------------------------------------*/
void jisuan()
{ float temp,temp0,temp1,temp2,temp3;
temp3=(float)((0-tempy*tempy));
temp0=temp3;
temp=sqrt(temp0);
cos_phi_x=tempx/temp;//((float)(acos(tv/63))*180/3.14)*1000; //角度计算
phi_x=(float)(acos(cos_phi_x))*1000;
temp1=tempx*tempx/1000.0;
temp2=sqrt(temp1);
cos_phi_y=10.0*tempy/temp2;
phi_y=cos_phi_y;
}
//*********************************************************
//******主程序*********************************************
//*********************************************************
void main()
{
delay(2); //上电延时
InitUART();
Init_MMA8452(); //初始化MMA8452
RX_DATA=0;
while(1) //循环
{
Multiple_Read_MMA8452(); //连续读出数据,存储在BUF中
SendByte(0x0f);
Delay5ms();
SendByte(0x0a);
display_x(); //---------显示X轴
display_y(); //---------显示Y轴
display_z(); //---------显示Z轴
jisuan();
display_phix();
display_phiy();
delay(50); //延时50ms
}
}
你参考参考吧,可是偏角计算部分还有点问题、、、、 mark下@@@ {:sad:}…… 1611182791 发表于 2013-4-5 14:34 static/image/common/back.gif
//***************************************
// GY-45 MMA8452 IIC测试程序
// 使用单片机STC89C51
请问你的“GY-45 MMA8452 IIC测试程序”跑的通吗?
可以的!但是还有一些问题,等一久再贴出来,最近有些忙、、、 好人还是多啊..谢谢分享. 1611182791 发表于 2013-4-19 23:03 static/image/common/back.gif
可以的!但是还有一些问题,等一久再贴出来,最近有些忙、、、
请教下哈,SA0如何接的,是随意接单片机口,还是直接给电平?
INT1,INT2是直接接单片机中断口的么。。
dengxbin 发表于 2013-4-30 17:35 static/image/common/back.gif
请教下哈,SA0如何接的,是随意接单片机口,还是直接给电平?
INT1,INT2是直接接单片机中断口的么。。
...
SAO接电源GND就可以了至于中断我是没有用它让它悬空,如果你要用的话你就接进去然后然后写对应的中断程序就可以了、、、、 1611182791 发表于 2013-5-1 16:51 static/image/common/back.gif
SAO接电源GND就可以了至于中断我是没有用它让它悬空,如果你要用的话你就接进去然后然后写对应的中断程序 ...
多谢啦,懂了~ 1611182791 发表于 2013-4-5 14:34 static/image/common/back.gif
//***************************************
// GY-45 MMA8452 IIC测试程序
// 使用单片机STC89C51
哈,谢谢分享,学习学习 到淘宝上找店主要一份不就得了 http://pan.baidu.com/share/link?shareid=457165&uk=2302102993
shadowxujing 发表于 2013-4-19 14:08 static/image/common/back.gif
请问你的“GY-45 MMA8452 IIC测试程序”跑的通吗?
嗯!可以的我直接在串口调试测到数据了,但是那个偏角计算呀那些地方你们不用它的,当然你也可以通过欧拉角计算出俯仰角和横滚角然后去控制你想要控制的东西,如果不是很精确的话直接利用就ok! 学习了 谢谢分享 学习了 学习学习{:victory:} MARK!~~`
MARK!‘~^~`
页:
[1]