This is a simple device driver for the 3 axis accelerometer MMA8452 that works with mbed.

Dependents:   MMA8452_test S05APP3_routeur

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MMA8452.cpp Source File

MMA8452.cpp

00001 // Author: Nicholas Herriot
00002 /* Copyright (c) 2013 Vodafone, MIT License
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00005  * and associated documentation files (the "Software"), to deal in the Software without restriction,
00006  * including without limitation the rights to use, copy, modify, merge, publish, distribute,
00007  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
00008  * furnished to do so, subject to the following conditions:
00009  *
00010  * The above copyright notice and this permission notice shall be included in all copies or
00011  * substantial portions of the Software.
00012  *
00013  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00014  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00015  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00016  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00017  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00018  */
00019 
00020 # include "MMA8452.h"
00021 
00022 
00023 
00024 
00025 
00026 
00027 // Connect module at I2C address using I2C port pins sda and scl
00028 Accelerometer_MMA8452::Accelerometer_MMA8452(PinName sda, PinName scl,int frequency) : m_i2c(sda, scl) , m_frequency(frequency)
00029 {
00030     //m_i2c.frequency(m_frequency);
00031 }
00032 
00033 
00034 // Destroys instance
00035 Accelerometer_MMA8452::~Accelerometer_MMA8452()
00036 {
00037 
00038 }
00039 
00040 // Setting the control register bit 1 to true to activate the MMA8452
00041 int Accelerometer_MMA8452::activate()
00042 {
00043     char mcu_address = (MMA8452_ADDRESS<<1);
00044     char init[2];
00045     init[0] = CTRL_REG_1;                 // control register 1
00046     init[1] = ACTIVE;                     // set to active
00047     
00048     if(m_i2c.write(mcu_address,init,2) == 0)
00049     {
00050          return 0;  // return 0 to indicate success
00051     }
00052     else
00053     {
00054         return 1;   // crumbs it failed!!!
00055     }
00056          
00057 }
00058 
00059 
00060 // Get 'Fast Read Mode' called F_READ. If bit 1 is set '1' then F_READ is active. Fast read will skip LSB when reading xyz
00061 // resisters from 0x01 to 0x06. When F_READ is '0' then all 6 registers will be read.
00062 
00063 int Accelerometer_MMA8452::get_CTRL_Reg1(int& CTRL_Reg)
00064 {
00065 {
00066     char mcu_address = (MMA8452_ADDRESS<<1);
00067     m_i2c.start();
00068     if( m_i2c.write( mcu_address & 0xFE) == 0)          // just good practice to force bit 1 to a '0' by ANDing with 0xFE
00069     {
00070         return 1;                                       // we failed to write the mcu address on the bus to initiate dialogue 
00071     }
00072     if( m_i2c.write( CTRL_REG_1) == 0) 
00073     {
00074         return 1;                                       // we failed to write 'status' to the chip
00075     }
00076     m_i2c.start();
00077     if( m_i2c.write( mcu_address | 0x01) == 0)          // this is asking to read the slave mcu address - even though it's a 'write' method!!! Crap API...
00078     {
00079         return 1;                                       // we failed to request a read from that mcu - this really is just writing the mcu vaule on the bus
00080     }
00081     CTRL_Reg  = m_i2c.read(0);
00082     m_i2c.stop();
00083     return 0;
00084     
00085 
00086 }
00087 
00088 
00089 
00090 
00091 }
00092 
00093 // Setting the control register bit 1 to true to activate the MMA8452
00094 int Accelerometer_MMA8452::standby()
00095 {
00096     char mcu_address = (MMA8452_ADDRESS<<1);
00097     char init[2];
00098     init[0] = CTRL_REG_1;                 // control register 1
00099     init[1] = STANDBY;                    // set to standby
00100     
00101     if(m_i2c.write(mcu_address,init,2) == 0)
00102     {
00103          // pc.printf("The initialisation worked");
00104          return 0;  // return 0 to indicate success
00105     }
00106     else
00107     {
00108         // pc.printf("The initialisation failed");
00109         return 1;   // crumbs it failed!!!
00110     }
00111          
00112 }
00113 
00114 
00115 
00116 // Device initialization
00117 void Accelerometer_MMA8452::init()
00118 {
00119     
00120     write_reg(INTSU_STATUS, 0x10);      // automatic interrupt after every measurement
00121     write_reg(SR_STATUS, 0x00);         // 120 Samples/Second
00122     write_reg(MODE_STATUS, 0x01);       // Active Mode
00123     
00124 }
00125 
00126 // Get real time status of device - it can be STANDBY, WAKE or SLEEP
00127 int Accelerometer_MMA8452::get_SystemMode(int& deviceSystemMode)
00128 {
00129     char mcu_address = (MMA8452_ADDRESS<<1);
00130     m_i2c.start();
00131     if( m_i2c.write( mcu_address & 0xFE) == 0)          // just good practice to force bit 1 to a '0' by ANDing with 0xFE
00132     {
00133         return 1;                                       // we failed to write the mcu address on the bus to initiate dialogue 
00134     }
00135     if( m_i2c.write( SYSMOD) == 0) 
00136     {
00137         return 1;                                       // we failed to write 'status' to the chip
00138     }
00139     m_i2c.start();
00140     if( m_i2c.write( mcu_address | 0x01) == 0)          // this is asking to read the slave mcu address - even though it's a 'write' method!!! Crap API...
00141     {
00142         return 1;                                       // we failed to request a read from that mcu - this really is just writing the mcu vaule on the bus
00143     }
00144     deviceSystemMode  = m_i2c.read(0);
00145     m_i2c.stop();
00146     return 0;
00147     
00148 
00149 }
00150 
00151 
00152 
00153 // Get real time status of device - it can be STANDBY, WAKE or SLEEP
00154 int Accelerometer_MMA8452::get_Status(int& deviceStatus)
00155 {
00156     char mcu_address = (MMA8452_ADDRESS<<1);
00157     m_i2c.start();
00158     if( m_i2c.write( mcu_address & 0xFE) == 0)          // just good practice to force bit 1 to a '0' by ANDing with 0xFE
00159     {
00160         return 1;                                       // we failed to write the mcu address on the bus to initiate dialogue 
00161     }
00162     if( m_i2c.write( STATUS) == 0) 
00163     {
00164         return 1;                                       // we failed to write 'status' to the chip
00165     }
00166     m_i2c.start();
00167     if( m_i2c.write( mcu_address | 0x01) == 0)          // this is asking to read the slave mcu address - even though it's a 'write' method!!! Crap API...
00168     {
00169         return 1;                                       // we failed to request a read from that mcu - this really is just writing the mcu vaule on the bus
00170     }
00171     deviceStatus  = m_i2c.read(0);
00172     m_i2c.stop();
00173     return 0;
00174     
00175 
00176 }
00177 
00178 
00179 // Get device ID 
00180 int Accelerometer_MMA8452::get_DeviceID(int& deviceID)
00181 {
00182     char mcu_address = (MMA8452_ADDRESS<<1);
00183     m_i2c.start();
00184     if( m_i2c.write( mcu_address & 0xFE) == 0)          // just good practice to force bit 1 to a '0' by ANDing with 0xFE
00185     {
00186         return 1;                                       // we failed to write the mcu address on the bus to initiate dialogue 
00187     }
00188     if( m_i2c.write( WHO_AM_I) == 0) 
00189     {
00190         return 1;                                       // we failed to write 'who am i' to the chip
00191     }
00192     m_i2c.start();
00193     if( m_i2c.write( mcu_address | 0x01) == 0)          // this is asking to read the slave mcu address - even though it's a 'write' method!!! Crap API...
00194     {
00195         return 1;                                       // we failed to request a read from that mcu - this really is just writing the mcu vaule on the bus
00196     }
00197     deviceID  = m_i2c.read(0);
00198     m_i2c.stop();
00199     return 0;
00200 
00201 }
00202 
00203 
00204 /*
00205 // Reads x data
00206 int Accelerometer_MMA8452::read_x(int& xaxisLSB)
00207 {
00208     char mcu_address = (MMA8452_ADDRESS<<1);
00209     m_i2c.start();
00210     if( m_i2c.write( mcu_address & 0xFE) == 0)          // just good practice to force bit 1 to a '0' by ANDing with 0xFE
00211     {
00212         return 1;                                       // we failed to write the mcu address on the bus to initiate dialogue 
00213     }
00214     if( m_i2c.write( OUT_X_MSB) == 0) 
00215     {
00216         return 1;                                       // we failed to write 'X axis LSB' to the chip
00217     }
00218     m_i2c.start();
00219     if( m_i2c.write( mcu_address | 0x01) == 0)          // this is asking to read the slave mcu address - even though it's a 'write' method!!! Crap API...
00220     {
00221         return 1;                                       // we failed to request a read from that mcu - this really is just writing the mcu vaule on the bus
00222     }
00223     xaxisLSB  = m_i2c.read(0);
00224     m_i2c.stop();
00225     return 0;
00226 }
00227 */
00228 
00229 
00230 // Reads x data. This method reads two registers containing the x-axis values from the accelerometer. 
00231 // It takes a 2 byte char array and copies the register values into the buffer. If it fails the char array
00232 // is set to '0'. It returns '0' success '1' fail. This method does nothing to the registers - just returns
00233 // the raw data.
00234 //int Accelerometer_MMA8452::read_x(int& xaxisLSB)
00235 int Accelerometer_MMA8452::read_x_raw(char *xaxis)
00236 {
00237     char mcu_address = (MMA8452_ADDRESS<<1);                // this is the slave address on the bus we want data from
00238     char xaxis_buffer[2];                                   // this will contain data from that register
00239     char xaxis_register[1];                     
00240     xaxis_register[0] = OUT_X_MSB;                          // this is the register we want to get data from
00241     //signed short s = 0;
00242     
00243     if(m_i2c.write(mcu_address,xaxis_register,1,true) == 0)
00244     {
00245         if(m_i2c.read(mcu_address,xaxis_buffer,2) == 0)
00246         {
00247             //strcpy(xaxis, xaxis_buffer);
00248             memcpy(xaxis, xaxis_buffer, 2);
00249             //xaxis[0] = 0x00;                        // make sure the array is set to zero
00250             //xaxis[1] = 0x00;
00251             //s = *reinterpret_cast<short*>(&xaxis);
00252             return 0;                               // great we got the two octets
00253         }
00254         else
00255         {
00256             xaxis[0] = 0x00;                        // make sure the array is set to zero
00257             xaxis[1] = 0x00;
00258             return 1;                               // failed to read the 12 bit x value
00259         }
00260     }
00261     else
00262     {
00263         xaxis[0] = 0x00;                            // make sure the array is set to zero
00264         xaxis[1] = 0x00;
00265         return 1;                                   // failed to write and request the OUT_X_MSB bit
00266     }    
00267 }
00268 
00269 
00270 // Reads y data. This method reads two registers containing the x-axis values from the accelerometer. 
00271 // It takes a 2 byte char array and copies the register values into the buffer. If it fails the char array
00272 // is set to '0'. It returns '0' success '1' fail. This method does nothing to the registers - just returns
00273 // the raw data.
00274 
00275 int Accelerometer_MMA8452::read_y_raw(char *yaxis)
00276 {
00277     char mcu_address = (MMA8452_ADDRESS<<1);                // this is the slave address on the bus we want data from
00278     char yaxis_buffer[2];                                   // this will contain data from that register
00279     char yaxis_register[1];                     
00280     yaxis_register[0] = OUT_Y_MSB;                          // this is the register we want to get data from
00281     //signed short s = 0;
00282     
00283     if(m_i2c.write(mcu_address,yaxis_register,1,true) == 0)
00284     {
00285         if(m_i2c.read(mcu_address,yaxis_buffer,2) == 0)
00286         {
00287             //strcpy(yaxis, yaxis_buffer);
00288             memcpy(yaxis, yaxis_buffer, 2);
00289             //yaxis[0] = 0x00;                        // make sure the array is set to zero
00290             //yaxis[1] = 0x00;
00291             //s = *reinterpret_cast<short*>(&xaxis);
00292             return 0;                               // great we got the two octets
00293         }
00294         else
00295         {
00296             yaxis[0] = 0x00;                        // make sure the array is set to zero
00297             yaxis[1] = 0x00;
00298             return 1;                               // failed to read the 12 bit y value
00299         }
00300     }
00301     else
00302     {
00303         yaxis[0] = 0x00;                            // make sure the array is set to zero
00304         yaxis[1] = 0x00;
00305         return 1;                                   // failed to write and request the OUT_Y_MSB bit
00306     }    
00307 }
00308 
00309 
00310 
00311 // Reads z data. This method reads two registers containing the x-axis values from the accelerometer. 
00312 // It takes a 2 byte char array and copies the register values into the buffer. If it fails the char array
00313 // is set to '0'. It returns '0' success '1' fail. This method does nothing to the registers - just returns
00314 // the raw data.
00315 
00316 int Accelerometer_MMA8452::read_z_raw(char *zaxis)
00317 {
00318     char mcu_address = (MMA8452_ADDRESS<<1);                // this is the slave address on the bus we want data from
00319     char zaxis_buffer[2];                                   // this will contain data from that register
00320     char zaxis_register[1];                     
00321     zaxis_register[0] = OUT_Z_MSB;                          // this is the register we want to get data from
00322     //signed short s = 0;
00323     
00324     if(m_i2c.write(mcu_address,zaxis_register,1,true) == 0)
00325     {
00326         //if(m_i2c.read(mcu_address,zaxis_buffer,2) == 0)
00327         if(m_i2c.read(mcu_address,zaxis,2) == 0)
00328         {
00329             //strcpy(yaxis, yaxis_buffer);
00330             //memcpy(zaxis, zaxis_buffer, 2);
00331             //yaxis[0] = 0x00;                        // make sure the array is set to zero
00332             //yaxis[1] = 0x00;
00333             //s = *reinterpret_cast<short*>(&xaxis);
00334             return 0;                               // great we got the two octets
00335         }
00336         else
00337         {
00338             zaxis[0] = 0x00;                        // make sure the array is set to zero
00339             zaxis[1] = 0x00;
00340             return 1;                               // failed to read the 12 bit y value
00341         }
00342     }
00343     else
00344     {
00345         zaxis[0] = 0x00;                            // make sure the array is set to zero
00346         zaxis[1] = 0x00;
00347         return 1;                                   // failed to write and request the OUT_Y_MSB bit
00348     }    
00349 }
00350 
00351 
00352 
00353 // Reads y data
00354 int Accelerometer_MMA8452::read_y()
00355 {
00356     char mcu_address = (MMA8452_ADDRESS <<1);
00357 
00358     m_i2c.start();                  // Start
00359     m_i2c.write(mcu_address);              // A write to device 0x98
00360     m_i2c.write(OUT_Y_MSB);             // Register to read
00361     m_i2c.start();                  
00362     m_i2c.write(mcu_address);              // Read from device 0x99
00363     int y = m_i2c.read(0);         // Read the data
00364     m_i2c.stop();
00365     
00366     return y; 
00367 
00368 }
00369 
00370 
00371 // Reads z data
00372 int Accelerometer_MMA8452::read_z()
00373 {
00374     char mcu_address = (MMA8452_ADDRESS <<1);
00375     
00376     m_i2c.start();                  // Start
00377     m_i2c.write(mcu_address);              // A write to device 0x98
00378     m_i2c.write(OUT_Z_MSB);             // Register to read
00379     m_i2c.start();                  
00380     m_i2c.write(mcu_address);              // Read from device 0x99
00381     int z = m_i2c.read(0);         // Read the data
00382     m_i2c.stop();
00383     
00384     return z;
00385 
00386 }
00387 
00388 
00389 // Reads xyz
00390 int Accelerometer_MMA8452::read_xyz(char *x, char *y, char *z) 
00391 {
00392     
00393     
00394     char mcu_address = (MMA8452_ADDRESS <<1);
00395     char register_buffer[6] ={0,0,0,0,0,0};
00396     const char Addr_X = OUT_X_MSB;
00397     m_i2c.write(mcu_address);              // A write to device 0x98
00398     m_i2c.write(MMA8452_ADDRESS, &Addr_X, 1);         // Pointer to the OUT_X_MSB register
00399     
00400     if(m_i2c.write(mcu_address,&Addr_X,1) == 0)
00401     {
00402         if(m_i2c.read(mcu_address,register_buffer,6) == 0)
00403         {
00404             *x = register_buffer[1];
00405             *y = register_buffer[3];
00406             *z = register_buffer[5];
00407             return 0;           // yahoooooo
00408         }
00409         else
00410         {
00411             return 1;           // failed oh nooo!
00412         }    
00413     }
00414     else
00415     {
00416         return 1;               // failed oh nooo!
00417     }
00418 
00419 }
00420 
00421         // Write register (The device must be placed in Standby Mode to change the value of the registers) 
00422 void Accelerometer_MMA8452::write_reg(char addr, char data)
00423 {
00424 
00425     char cmd[2] = {0, 0};
00426     
00427     cmd[0] = MODE_STATUS;
00428     cmd[1] = 0x00;                      // Standby Mode on
00429     m_i2c.write(MMA8452_ADDRESS, cmd, 2);
00430   
00431     cmd[0] = addr;
00432     cmd[1] = data;                      // New value of the register
00433     m_i2c.write(MMA8452_ADDRESS, cmd, 2); 
00434       
00435     cmd[0] = MODE_STATUS;
00436     cmd[1] = 0x01;                      // Active Mode on
00437     m_i2c.write(MMA8452_ADDRESS, cmd, 2);
00438                   
00439 }
00440 
00441 
00442 
00443         // Read from specified MMA7660FC register
00444 char Accelerometer_MMA8452::read_reg(char addr)
00445 {
00446     
00447     m_i2c.start();                  // Start
00448     m_i2c.write(0x98);              // A write to device 0x98
00449     m_i2c.write(addr);              // Register to read
00450     m_i2c.start();                  
00451     m_i2c.write(0x99);              // Read from device 0x99
00452     char c = m_i2c.read(0);         // Read the data
00453     m_i2c.stop();                   
00454  
00455     return c;
00456     
00457 }
00458 
00459 
00460 
00461 
00462 
00463