Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API PinDetect mbed-src-bmd-200
MMA845x.cpp
00001 /** 00002 * @file MMA845x.cpp 00003 * @brief Device driver - MMA845X 3-axis accelerometer IC 00004 * @author sam grove 00005 * @version 1.0 00006 * @see http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8451Q.pdf 00007 * @see http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8452Q.pdf 00008 * @see http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8453Q.pdf 00009 * 00010 * Copyright (c) 2013 00011 * 00012 * Licensed under the Apache License, Version 2.0 (the "License"); 00013 * you may not use this file except in compliance with the License. 00014 * You may obtain a copy of the License at 00015 * 00016 * http://www.apache.org/licenses/LICENSE-2.0 00017 * 00018 * Unless required by applicable law or agreed to in writing, software 00019 * distributed under the License is distributed on an "AS IS" BASIS, 00020 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00021 * See the License for the specific language governing permissions and 00022 * limitations under the License. 00023 */ 00024 00025 #include "MMA845x.h" 00026 #include "mbed.h" 00027 00028 00029 void MMA845x::disable(void) 00030 { 00031 uint8_t reg_val = 0; 00032 // Reset all registers to POR values 00033 MMA845x::writeRegister(CTRL_REG2, 0xF0); //REG 0x2B 00034 wait(0.05); 00035 do{ 00036 // wait for the reset bit to clear 00037 reg_val = MMA845x::readRegister(CTRL_REG2) & 0x40; 00038 }while(reg_val); 00039 MMA845x::writeRegister(CTRL_REG1, 0x00); //REG 0x2A 0x98 = ASLP_RATE: 6.25hz Data Rate: 50hz 00040 } 00041 00042 void MMA845x::setIntMode(int intMode) 00043 { 00044 _intMode = intMode; 00045 } 00046 00047 void MMA845x::interrupt_1(void) 00048 { 00049 //_int1_waiting = true; 00050 00051 uint8_t reg_int_sts; 00052 uint8_t reg_sts; 00053 uint8_t reg_pulse_sts; 00054 uint8_t reg_motion_sts; 00055 char reg_data[3][2] = { 0 }; 00056 int16_t values[3] = { 0 }; 00057 float g_values[3] = { 0 }; 00058 reg_int_sts = MMA845x::readRegister(INT_SOURCE); //REG 0x0C 00059 if((reg_int_sts & 0x01)) //Mask register read with SRC_DRDY bit 00060 { 00061 printf("Int1:"); 00062 printf(" Data Ready"); 00063 reg_sts = MMA845x::readRegister(STATUS); //REG 0x00 00064 00065 reg_pulse_sts = MMA845x::readRegister(PULSE_SRC); //REG 0x22 00066 00067 reg_data[0][0] = MMA845x::readRegister(OUT_X_MSB); //REG 0x01 00068 reg_data[0][1] = MMA845x::readRegister(OUT_X_LSB); //REG 0x02 00069 reg_data[1][0] = MMA845x::readRegister(OUT_Y_MSB); //REG 0x03 00070 reg_data[1][1] = MMA845x::readRegister(OUT_Y_LSB); //REG 0x04 00071 reg_data[2][0] = MMA845x::readRegister(OUT_Z_MSB); //REG 0x05 00072 reg_data[2][1] = MMA845x::readRegister(OUT_Z_LSB); //REG 0x06 00073 //printf(" STATUS: 0x%02X X: %d %d Y: %d %d Z: %d %d\n\r", reg_sts, reg_data[0][0], reg_data[0][1], reg_data[1][0], reg_data[1][1], reg_data[2][0], reg_data[2][1]); 00074 00075 values[0] = ((reg_data[0][0] * 256) + ((unsigned short) reg_data[0][1])); 00076 values[1] = ((reg_data[1][0] * 256) + ((unsigned short) reg_data[1][1])); 00077 values[2] = ((reg_data[2][0] * 256) + ((unsigned short) reg_data[2][1])); 00078 00079 g_values[0] = ((float) values[0]) / 16384.0; 00080 g_values[1] = ((float) values[1]) / 16384.0; 00081 g_values[2] = ((float) values[2]) / 16384.0; 00082 00083 //printf(" STATUS: 0x%02X X: %d Y: %d Z: %d\n\r", reg_sts, values[0], values[1], values[2]); 00084 00085 if (_intMode == 1) 00086 { 00087 printf(" STATUS: 0x%02X X: %.3f Y: %.3f Z: %.3f", reg_sts, g_values[0], g_values[1], g_values[2]); 00088 } 00089 else 00090 { 00091 int bars = abs( values[0] / 512 ); 00092 printf(" X: "); 00093 for( int i = 0; i < bars; i++ ) 00094 { 00095 printf(">"); 00096 } 00097 } 00098 00099 if (reg_pulse_sts & 0x10) 00100 { 00101 printf(" ***********************************************"); 00102 _callbackZAxisPulse.call(); 00103 if (reg_pulse_sts & 0x01) 00104 { 00105 printf("--------------"); 00106 } 00107 } 00108 printf("\n\r"); 00109 } 00110 if (reg_int_sts & 0x08) //Pulse interrupt 00111 { 00112 00113 reg_pulse_sts = MMA845x::readRegister(PULSE_SRC); //REG 0x22 00114 if (reg_pulse_sts & 0x40) //Z-axis event 00115 { 00116 00117 if (reg_pulse_sts & 0x08) //Pulse event was double pulse 00118 { 00119 00120 00121 } 00122 if (reg_pulse_sts & 0x04)//Z-axis pulse direction 00123 { 00124 00125 } 00126 _callbackZAxisPulse.call(); 00127 00128 } 00129 } 00130 if (reg_int_sts & 0x04) //Motion interrupt 00131 { 00132 00133 reg_motion_sts = MMA845x::readRegister(FF_MT_SRC); //REG 0x16 00134 if (reg_motion_sts & 0x02) // 00135 { 00136 /* 00137 if (reg_motion_sts & 0x08) // 00138 { 00139 00140 00141 } 00142 if (reg_motion_sts & 0x04)// 00143 { 00144 00145 } 00146 */ 00147 _callbackZAxisPulse.call(); 00148 00149 } 00150 } 00151 } 00152 00153 /* Call this function when a Z-axis pulse detected 00154 * @param function A C function pointer 00155 */ 00156 void MMA845x::attachZAxisPulse( void (*function)(void) ) 00157 { 00158 _callbackZAxisPulse.attach( function ); 00159 } 00160 00161 void MMA845x::interrupt_handler(void) 00162 { 00163 00164 uint8_t reg_int_sts; 00165 uint8_t reg_sts; 00166 int reg_data[3] = { 0x00, 0x00, 0x00 }; 00167 printf("Int1:"); 00168 reg_int_sts = MMA845x::readRegister(INT_SOURCE); //REG 0x0C 00169 if((reg_int_sts & 0x01)) //Mask register read with SRC_DRDY bit 00170 { 00171 printf(" Data Ready"); 00172 reg_sts = MMA845x::readRegister(STATUS); //REG 0x00 00173 reg_data[0] = MMA845x::readRegister(OUT_X_MSB); //REG 0x01 00174 reg_data[1] = MMA845x::readRegister(OUT_Y_MSB); //REG 0x03 00175 reg_data[2] = MMA845x::readRegister(OUT_Z_MSB); //REG 0x05 00176 printf(" STATUS: 0x%02X X: %d Y: %d Z: %d\n\r", reg_sts, reg_data[0], reg_data[1], reg_data[2]); 00177 } 00178 } 00179 00180 void MMA845x::init(void) const 00181 { 00182 uint8_t reg_val = 0; 00183 00184 _i2c->frequency(400000); 00185 00186 // Reset all registers to POR values 00187 MMA845x::writeRegister(CTRL_REG2, 0x40); //REG 0x2B 00188 do{ 00189 // wait for the reset bit to clear 00190 reg_val = MMA845x::readRegister(CTRL_REG2) & 0x40; 00191 }while(reg_val); 00192 00193 // setup the registers that are common among modes 00194 MMA845x::writeRegister(CTRL_REG1, 0xA0); //REG 0x2A 0x98 = ASLP_RATE: 6.25hz Data Rate: 50hz 00195 MMA845x::writeRegister(CTRL_REG2, 0x18); //REG 0x2B Setup for low-power, no auto-sleep 00196 MMA845x::writeRegister(CTRL_REG3, 0x00); //REG 0x2C No interrupts wake device, active low int, push-pull 00197 MMA845x::writeRegister(CTRL_REG4, 0x00); //REG 0x2D 00198 MMA845x::writeRegister(CTRL_REG5, 0xFD); //REG 0x2E All interrupt sources to INT1 00199 00200 MMA845x::writeRegister(XYZ_DATA_CFG, 0x11); //REG 0x0E HPF / scale +/-2,4,8g 00201 MMA845x::writeRegister(HP_FILTER_CUTOFF, 0x00); //REG 0x0F HPF settings 00202 00203 return; 00204 } 00205 00206 void MMA845x::enableDataReadyMode(void) const 00207 { 00208 MMA845x::init(); 00209 //MMA845x::writeRegister(SYSMOD, 0x01); //REG 0x0B This register is read only 00210 //MMA845x::writeRegister(INT_SOURCE, 0x01); //REG 0x0C This register is read only 00211 MMA845x::writeRegister(CTRL_REG4, 0x09); //REG 0x2D Enable data ready interrupt 00212 00213 00214 00215 //MMA845x::writeRegister(CTRL_REG1, 0xA3); //REG 0x2A 0xA3 = ASLP_RATE: 6.25hz Data Rate: 50hz, Fast Read, Active mode 00216 00217 MMA845x::writeRegister(XYZ_DATA_CFG, 0x11); //REG 0x0E HPF / scale +/-2,4,8g - Enable HPF 00218 MMA845x::writeRegister(HP_FILTER_CUTOFF, 0x10); //REG 0x0F HPF settings - HPF for pulse on, 0.25Hz cutoff for 12.5rate 00219 00220 00221 MMA845x::writeRegister(PULSE_CFG, 0x41); //REG 0x21 Setup single pulse in x axis 00222 MMA845x::writeRegister(PULSE_THSX, 0x09); //REG 0x21 Setup pulse threshold in x axis 00223 MMA845x::writeRegister(PULSE_TMLT, 0x14); //REG 0x21 Setup single pulse in x axis 00224 MMA845x::writeRegister(PULSE_LTCY, 0x04); //REG 0x21 Setup single latency in x axis 00225 00226 00227 MMA845x::writeRegister(CTRL_REG1, 0xA1); //REG 0x2A 0x98 = ASLP_RATE: 6.25hz Data Rate: 12.5hz, Normal Read, Active mode 00228 00229 } 00230 00231 void MMA845x::enableMotionMode(void) const 00232 { 00233 MMA845x::init(); 00234 00235 MMA845x::writeRegister(CTRL_REG4, 0x04); //REG 0x2D Enable pulse interrupt 00236 00237 MMA845x::writeRegister(XYZ_DATA_CFG, 0xF1); //REG 0x0E HPF / scale +/-4g, Enable HPF for output data 00238 MMA845x::writeRegister(HP_FILTER_CUTOFF, 0x00); //REG 0x0F HPF settings - HPF for pulse on, 4Hz cutoff for 100Hz rate 00239 00240 MMA845x::writeRegister(FF_MT_CFG, 0xC8); //REG 0x21 Setup 00241 MMA845x::writeRegister(FF_MT_THS, 0x01); //REG 0x21 Setup 00242 MMA845x::writeRegister(FF_MT_COUNT, 0x5); //REG 0x21 Setup 00243 00244 MMA845x::writeRegister(CTRL_REG2, 0x03); //REG 0x2B Setup for low power mode, no auto-sleep 00245 MMA845x::writeRegister(CTRL_REG1, 0xA1); //REG 0x2A 0x98 = ASLP_RATE: 6.25hz Data Rate: 12.5Hz, Normal Read, Active mode 00246 00247 } 00248 00249 void MMA845x::enablePulseMode(void) const 00250 { 00251 MMA845x::init(); 00252 00253 MMA845x::writeRegister(CTRL_REG4, 0x08); //REG 0x2D Enable pulse interrupt 00254 00255 MMA845x::writeRegister(XYZ_DATA_CFG, 0xF1); //REG 0x0E HPF / scale +/-2,4,8g - Enable HPF 00256 MMA845x::writeRegister(HP_FILTER_CUTOFF, 0x00); //REG 0x0F HPF settings - HPF for pulse on, 4Hz cutoff for 100Hz rate 00257 00258 MMA845x::writeRegister(PULSE_CFG, 0x50); //REG 0x21 Setup single pulse in z axis 00259 MMA845x::writeRegister(PULSE_THSX, 0x06); //REG 0x21 Setup pulse threshold in x axis 00260 MMA845x::writeRegister(PULSE_THSZ, 0x2F); //REG 0x21 Setup pulse threshold in z axis 00261 MMA845x::writeRegister(PULSE_TMLT, 0x28); //REG 0x21 Setup single pulse 00262 MMA845x::writeRegister(PULSE_LTCY, 0x0D); //REG 0x21 Setup single latency 00263 MMA845x::writeRegister(PULSE_WIND, 0x2D); //REG 0x21 Setup double pulse window 00264 00265 MMA845x::writeRegister(CTRL_REG2, 0x00); //REG 0x2B Setup for normal power mode, no auto-sleep 00266 MMA845x::writeRegister(CTRL_REG1, 0x99); //REG 0x2A 0x98 = ASLP_RATE: 6.25hz Data Rate: 100Hz, Normal Read, Active mode 00267 00268 } 00269 00270 void MMA845x::enableOrientationMode(void) const 00271 { 00272 uint16_t who_am_i = MMA845x::readRegister(WHO_AM_I); 00273 if(who_am_i != MMA8451 ) 00274 { 00275 error("%s %d: Feature not compatible with the connected device.\n", __FILE__, __LINE__); 00276 } 00277 00278 return; 00279 } 00280 00281 void MMA845x::enableTransitMode(void) const{} 00282 void MMA845x::enableAutoSleepMode(void) const{} 00283 00284 void MMA845x::enableFIFOMode(void) const 00285 { 00286 uint16_t who_am_i = MMA845x::readRegister(WHO_AM_I); 00287 if(who_am_i != MMA8451 ) 00288 { 00289 error("%s %d: Feature not compatible with the connected device.\n", __FILE__, __LINE__); 00290 } 00291 00292 //MMA845x::writeRegister( 00293 00294 return; 00295 } 00296 00297 uint16_t MMA845x::getX(void) const 00298 { 00299 return _data._x ; 00300 } 00301 00302 uint16_t MMA845x::getY(void) const 00303 { 00304 return _data._y ; 00305 } 00306 00307 uint16_t MMA845x::getZ(void) const 00308 { 00309 return _data._z ; 00310 } 00311 00312 MMA845x_DATA MMA845x::getXYZ(void) const 00313 { 00314 return _data; 00315 } 00316 00317 void MMA845x::writeRegister(uint8_t const reg, uint8_t const data) const 00318 { 00319 char buf[2] = {reg, data}; 00320 uint8_t result = 0; 00321 00322 /* 00323 __disable_irq(); // Tickers and other timebase events can jack up the I2C bus for some devices 00324 result = _i2c->write(_i2c_addr, buf, 2); 00325 __enable_irq(); // Just need to block during the transaction 00326 */ 00327 00328 result = _i2c->write(_i2c_addr, (const char *)&buf, 2, false); 00329 00330 if(0 != result) 00331 { 00332 error("%s %d: I2c write failed\n", __FILE__, __LINE__); 00333 } 00334 00335 return; 00336 } 00337 00338 uint8_t MMA845x::readRegister(uint8_t const reg) const 00339 { 00340 uint8_t result = 1, data = 0; 00341 /* 00342 __disable_irq(); // Tickers and other timebase events can jack up the I2C bus 00343 _i2c->start(); 00344 result &= _i2c->write(_i2c_addr); 00345 result &= _i2c->write(reg); 00346 // issue a repeated start... 00347 _i2c->start(); 00348 result &= _i2c->write(_i2c_addr | 0x01); 00349 // read with nak 00350 data = _i2c->read(0); 00351 _i2c->stop(); 00352 __enable_irq(); // Just need to block during the transaction 00353 */ 00354 00355 result &= _i2c->write(_i2c_addr, (const char *)®, 1, true); 00356 result &= _i2c->read(_i2c_addr, (char *)&data, 1); 00357 00358 if(1 != result) 00359 { 00360 //error("%s %d: I2C read failed\n", __FILE__, __LINE__); 00361 } 00362 00363 return data; 00364 } 00365 00366 void MMA845x::registerDump(void) const 00367 { 00368 uint8_t reg_val = 0; 00369 printf("Starting register dump...\n\r"); 00370 00371 for(int i=0; i<0x31; i++) 00372 { 00373 reg_val = MMA845x::readRegister(i); 00374 printf("Reg 0x%02x: 0x%02x \n\r", i, reg_val); 00375 } 00376 00377 return; 00378 } 00379
Generated on Wed Jul 20 2022 08:27:04 by
