智能车学习(十)——MMA8451加速度计的使用

一、驱动说明:

     就是使用I2C的通信方式驱动这款加速度计就行了,代码的话选择使用51单片机的代码进行移植。

二、代码分享:

1、头文件:

#ifndef MMA8451_H
#define MMA8451_H


/***********函数声明***********/

void MMA8451_Init(void);
void Read_Gray(void);

/*****************************/


/***********全局变量声明***********/
extern int delay_time;

extern double Gray_X ;
extern double Gray_Y ;
extern double Gray_Z ;

/*****************************/


#endif

2、源文件:

#include "include.h"
#include "common.h"
#include "i2c.h"
#include "MMA8451.h"
#include "port.h"
#include "gpio.h"
#include "lptmr.h"

double Gray_X ;
double Gray_Y ;
double Gray_Z ;

//管脚定义
#define MMA_S_I2C_SDA       (PTA16)//(PTB3)//(PTE0) //(PTE22)//(PTC1)//                     
#define MMA_S_I2C_SCL       (PTA14)//(PTB2)//(PTE1)//(PTE20)//(PTC0)//    

//IO方向设置
#define MMA_I2C_SDA_IN()   DDRA16 = 0//输入模式
#define MMA_I2C_SDA_OUT()  DDRA16 = 1//输出模式


//IO操作函数     
#define MMA_I2C_SCL        PTA14_OUT //SCL
#define MMA_I2C_SDA        PTA16_OUT //SDA     
#define MMA_I2C_READ_SDA   PTA16_IN  //输入SDA 

//**********MMA8451内部寄存器地址*********
#define WHO_AM_I    0x0D
#define CTRL_REG1   0x2A
#define CTRL_REG2   0x2B
#define CTRL_REG3   0x2C
#define CTRL_REG4   0x2D
#define CTRL_REG5   0x2E
//#define REFERENCE 0x25
//#define OUT_TEMP 0x26
#define STATUS_REG 0x00
#define OUT_X_H      0x01
#define OUT_X_L      0x02
#define OUT_Y_H      0x03
#define OUT_Y_L      0x04
#define OUT_Z_H      0x05
#define OUT_Z_L      0x06
#define XYZ_DATA_CFG 0x0E

#define    SlaveAddress   0x38      //定义器件在I2C总线中的从地址,根据ALT  ADDRESS地址引脚不同修改
#define    SlaveAddfire   0x69      //定义器件在I2C总线中的从地址,根据ALT  ADDRESS地址引脚不同修改


//============================================================================
//函数名称:void MMA_I2C_Config(__RAMFUNC  void)
//函数返回:无
//参数说明:无
//功能概要:初始化I2C
//============================================================================
void MMA_I2C_Config(void)
{
  //MMA_I2C_SDA_OUT();
  gpio_init(MMA_S_I2C_SDA,GPO,1);
  gpio_init(MMA_S_I2C_SCL,GPO,1);
  
  MMA_I2C_SCL=1;
  MMA_I2C_SDA=1;
}


//============================================================================
//函数名称:void MMA_I2C_Start(__RAMFUNC  void)
//函数返回:无
//参数说明:无
//功能概要:I2C通信开始
//============================================================================
void MMA_I2C_Start(void)
{
  MMA_I2C_SDA_OUT();
  
  MMA_I2C_SDA = 1;
  MMA_I2C_SCL = 1;
  lptmr_delay_us(1);
  
  MMA_I2C_SDA = 0;      
  lptmr_delay_us(1);
  MMA_I2C_SCL = 0;   
}

//============================================================================
//函数名称:void MMA_I2C_Stop(void)
//函数返回:无
//参数说明:无
//功能概要:I2C通信结束
//============================================================================
void MMA_I2C_Stop(void)
{
  MMA_I2C_SDA_OUT();
  MMA_I2C_SDA = 0;
  MMA_I2C_SCL = 1;
  
  lptmr_delay_us(1);                       
  MMA_I2C_SDA = 1;
  lptmr_delay_us(1);                                           
  MMA_I2C_SCL = 0;
}



void MMA_I2C_Mack(void)
{ 
  MMA_I2C_SDA_OUT();
  
  MMA_I2C_SDA=0;
  MMA_I2C_SCL=1;
  
  lptmr_delay_us(1); 
  
  MMA_I2C_SCL=0;
  MMA_I2C_SDA=1;
}

void MMA_I2C_Mnack(void)
{
  MMA_I2C_SDA_OUT();
  MMA_I2C_SDA=1;    
  lptmr_delay_us(1); 
  MMA_I2C_SCL=1;
  lptmr_delay_us(1); 
  MMA_I2C_SCL=0;
  lptmr_delay_us(1); 
  //MMA_I2C_SDA=0;
}

uint8_t MMA_I2C_Cack(void)
{  
  MMA_I2C_SDA_IN();;
  MMA_I2C_SCL=0;
  lptmr_delay_us(1); 
  MMA_I2C_SCL=1;
  lptmr_delay_us(1); 
  
  if(MMA_I2C_READ_SDA)
  {
    //MMA_I2C_Stop();
    //return 0xff;
  }
  
  MMA_I2C_SCL=0;              
  MMA_I2C_SDA_OUT();  
  return 0;  
}

void MMA_I2C_WriteByte(unsigned char data)
{
  unsigned char i=8;
  MMA_I2C_SDA_OUT();
  
  while(i--)
  {
    lptmr_delay_us(1); 
    if(data & 0x80)  
      MMA_I2C_SDA=1;
    else
      MMA_I2C_SDA=0;
    
    lptmr_delay_us(1); 
    MMA_I2C_SCL=1; 
    lptmr_delay_us(1);  
    MMA_I2C_SCL=0;         
    data<<=1;            
  }
}

uint8_t MMA_I2C_ReadByte(void)
{
  unsigned char i;
  unsigned char data=0;
  char temp;         
  
  MMA_I2C_SDA_IN();      
  
  for(i=0;i<8;i++)            
  {  
    data<<=1;
    lptmr_delay_us(1); 
    MMA_I2C_SCL = 1; 
    temp = MMA_I2C_READ_SDA;
    if(temp)
      data++;
    lptmr_delay_us(1);   
    MMA_I2C_SCL = 0;            
  }
  return data;
}

uint8_t MMA_I2C_WR_REG(uint8_t dev_addr, uint8_t reg_addr, uint8_t writeData)
{
  MMA_I2C_Start(); 
  MMA_I2C_WriteByte(dev_addr); 
  MMA_I2C_Cack();
  MMA_I2C_WriteByte(reg_addr);
  MMA_I2C_Cack();
  MMA_I2C_WriteByte(writeData);
  
  MMA_I2C_Cack();
  MMA_I2C_Stop();
  
  return 0;
}

uint8_t MMA_I2C_RD_REG(uint8_t dev_addr, uint8_t reg_addr)
{
  uint8_t read_reg = 0;
  MMA_I2C_Start();
  MMA_I2C_WriteByte(dev_addr);
  MMA_I2C_Cack();
  MMA_I2C_WriteByte(reg_addr);
  MMA_I2C_Cack();
  MMA_I2C_Start();
  MMA_I2C_WriteByte(dev_addr + 1);
  MMA_I2C_Cack();
  read_reg=MMA_I2C_ReadByte();
  MMA_I2C_Mnack();
  MMA_I2C_Stop();
  
  return read_reg;
}

uint8_t MMA_I2C_RD_Buffer(uint8_t dev_addr, uint8_t reg_addr, uint8_t data_num, uint8_t *readBuffer)
{
  uint8_t i = 0;
  MMA_I2C_Start();
  MMA_I2C_WriteByte(dev_addr);
  MMA_I2C_Cack();
  MMA_I2C_WriteByte(reg_addr);
  MMA_I2C_Cack();
  MMA_I2C_Start();
  MMA_I2C_WriteByte(dev_addr + 1);
  MMA_I2C_Cack();
  
  for(i = 0; i < data_num; i++){
    *(readBuffer+i) = MMA_I2C_ReadByte();
    if(i == data_num - 1)
      MMA_I2C_Mnack();
    else
      MMA_I2C_Mack();
  }
  MMA_I2C_Stop();
  
  return 0;
}





/*----------------*加速度传感器初始化*----------------*/
void MMA8451_Init(void)//初始化为指定模式 
{    
  MMA_I2C_Config();
  MMA_I2C_WR_REG(SlaveAddress,CTRL_REG1,0x05);           //数据手册30  0xbf 400hz 20~110截止频率
  MMA_I2C_WR_REG(SlaveAddress,CTRL_REG2,0x02);        //前两位00,后两位高通滤波器模式选择,后四位截止频率  0x29
  MMA_I2C_WR_REG(SlaveAddress,XYZ_DATA_CFG,0x10);      
}


/*-------------*加速度传感器测量值读取接口*------------*/
uint8_t MMA_tmpBuffer[6] = {0};


void Read_Gray(void)
{
  MMA_I2C_RD_Buffer(SlaveAddress,0x81,6,MMA_tmpBuffer);
  
  int temp;
  
  temp = ((short)((MMA_tmpBuffer[0]<<8)|MMA_tmpBuffer[1]))>>4;//2;// 14位精度  1g数值为1024(原本为4096,但是右移了(无效位2位)(有效位14位)两位)
  Gray_X = (double)Gray_X*0.5+(double)temp*0.5;
  
  temp = ((short)((MMA_tmpBuffer[2]<<8)|MMA_tmpBuffer[3]))>>4;//2;// 14位精度
  Gray_Y = (double)Gray_Y*0.5+(double)temp*0.5;
  
  temp = ((short)((MMA_tmpBuffer[4]<<8)|MMA_tmpBuffer[5]))>>4;//2;// 14位精度   
  Gray_Z = (double)Gray_Z*0.5+(double)temp*0.5;
}

/*--------------------------------------------------------------------------------------
1.如何确定加速度计或者陀螺仪的IIC通信控制字,理解握手原理,掌握寻址的方法
2.软件调试,结合管脚图
3.数据通信速度匹配问题---如何确定延时的大小
----------------------------------------------------------------------------------------*/

三、使用方法:

#include "include.h"
#include "OLED.h"
#include "init.h"
#include "KeySquare.h"
#include "lptmr.h"
#include "Menu.h"
#include "flash.h"
#include "MMA8451.h"

void main()
{
    DISABLE_INTERRUPTS;                          //MPU上电,各模块功能初始化前需要关中断
    system_init();                               //各模块功能初始化
    ENABLE_INTERRUPTS;                           //开中断使能

    
    //加速度计初始化
    MMA8451_Init();
    
    //初始化
    OLED_Init();  
    flash_init();
    
    //屏幕刷屏
    OLED_Clear();
    

    
   
    
    while(1)
    {
       Read_Gray();
       OLED_Clear();
       OLED_Write_Float(0,0,Gray_X);
       OLED_Write_Float(2,0,Gray_Y);
       OLED_Write_Float(4,0,Gray_Z);
       lptmr_delay_ms(100);
       
       
      //Menu_Key_Detect();
    }
}
原文地址:https://www.cnblogs.com/BlueMountain-HaggenDazs/p/4918453.html