一、驅動說明:
就是使用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(); } }
