求助三轴加速度MMA8451的使用程序和使用方法?

2020-01-23 14:49发布

我在做小车,用到三轴加速度MMA8451,但论坛没有MMA8451的使用程序和使用方法?求哪位大侠帮一下小弟!
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
28条回答
1611182791
2020-01-24 15:57
//***************************************
// 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 char  BYTE;
typedef unsigned short WORD;

BYTE BUF[8];                         //接收数据缓存区             
uchar ge,shi,bai,qian,wan;           //显示变量
int  dis_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);

void  Single_Write_MMA8452(uchar REG_Address,uchar REG_data);   //单个写入数据
uchar Single_Read_MMA8452(uchar REG_Address);                   //单个读取内部寄存器数据
void  Multiple_Read_MMA8452();                                  //连续的读取内部寄存器数据
//------------------------------------
void Delay5us();
void Delay5ms();
void MMA8452_Start();
void MMA8452_Stop();
void MMA8452_SendACK(bit ack);
bit  MMA8452_RecvACK();
void MMA8452_SendByte(BYTE dat);
BYTE MMA8452_RecvByte();
void MMA8452_ReadPage();
void MMA8452_WritePage();

uchar  RX_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!='')// 表示字符串结束标志,通过检测是否字符串末尾
  {
  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[i] = MMA8452_RecvByte();          //BUF[0]存储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[0]<<8)|BUF[1];  //合成数据   
        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[2]<<8)|BUF[3];  //合成数据   
        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[4]<<8)|BUF[5];    //合成数据  
    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      

  }
}

一周热门 更多>