智能车学习(十)——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(); } }