一、驱动说明:
就是使用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();
}
}