Davide Urbano
/
microSDreader
Working version. ADXL355 data saved to microSD.
adxl355.cpp
- Committer:
- DUR
- Date:
- 2017-09-29
- Revision:
- 0:e2579e8d9b13
File content as of revision 0:e2579e8d9b13:
/** ****************************************************************************** * @file adxl355.cpp * @author DUR * @version V1.0.0 * @date 01-Aug-2017 * @brief Library for adxl355 interface. * * @par Manual Reference Names: * 1. "Low Noise, Low Drift, Low Power, 3-Axis MEMS Accelerometers * ADXL354/ADXL355" * 9/2016—Revision 0: Initial Version * * @par Document History: * * Version: 1.0.0 (01/08/2017) * ---------------------------------------------------------------------------- * Author: DUR * First release. * ---------------------------------------------------------------------------- * @verbatim ================================================================================ ##### How to use this file ##### ================================================================================ Questa libreria è stata redatta per poter gestire ad alto livello il sensore di accelerazione ad uscita digitale a 20 bit della Analog Devices ADXL355, dotato di un bus SPI/I2C per la comunicazione, insieme ad un pin per la segnalazione di nuovi dati pronti e ben 2 pin di interrupt che sono configurabili per scattare a seguito di ben precisi eventi interni. Perché si possa utilizzare questa libreria su di una qualunque piattaforma hardware, la seguente funzione dovrà poi essere associata a quella di basso livello: (+) uint16_t adxl355_spi_transfer(uint8_t * rbuffer, uint32_t rlen) < trasferimento su bus SPI >; Nella presente versione della libreria, sono state fatte le seguenti scelte progettuali: (+) è stato scelto di utilizzare il bus SPI piuttosto che il bus I2C per la comunicazione da e verso l'host; (+) è stato scelto l'utilizzo della sincronizzazione interna (EXT_SYNC = 0x00). L'accelerometro viene configurato dall'utente, per mezzo di una struttura dati adxl355_handler, con la quale è possibile definire un setting di parametri applicativi in base alle differenti esigenze. Nel suo utilizzo è importante tenere a mente le seguenti osservzioni: (i) dopo avere lanciato il comando di reset software (adxl355_sw_reset) il sensore deve essere nuovamente inizializzato (adxl355_init); (i) per effettuare il self test, il sensore deve già essere in modalità di acquisizione; il camando adxl355_self_test(true) dovrà essere lanciato più volte perché ad ogni invocazione del metodo viene appicata una specifica accelerazione all'interno, e quella che si andrà a rilevare sarà proprio la differenza tra i valori in g rilevati tra due invocazioni successive, e che dovrà rispettare i valori imposti dal datasheet. @endverbatim ****************************************************************************** @attention <h2><center>© COPYRIGHT(c) 2014 TD Group</center></h2> The information contained herein is property of TD Group S.p.A. Licensees are granted free, non-transferable use of the information. NO WARRANTY of ANY KIND is provided. This heading must NOT be removed from the file. ****************************************************************************** */ #define ADXL355_VERSION 1 #define ADXL355_REVISION 0 #define ADXL355_PATCH 0 /* Includes ------------------------------------------------------------------*/ /** @brief Add ONLY the header of THIS source file and not others. */ #include "adxl355.h" /** @addtogroup FILE_FUNCTIONS * @{ */ /* Private function prototypes -----------------------------------------------*/ /* Ricava da una maschera di bit, la posizione del primo bit della maschera stessa */ static uint8_t adxl355_get_bit_position(uint8_t gbp_mask); /* Setting dei parametri */ static uint16_t adxl355_set_parameter(uint8_t sp_reg, uint8_t sp_mask_data, uint8_t sp_data); /* Lettura valore accelerazione lungo asse X, Y e Z */ static uint16_t adxl355_read_acc_value(adxl355_handler *adxl_acc); /* Lettura valore di temperatura */ static uint16_t adxl355_read_temp_value(adxl355_handler *adxl_temp); /* Private variables ---------------------------------------------------------*/ /* Definisce in ogni momento quali misure sono attive */ static adxl355_measure_enabled adxl_measure_on; /* Exported variables --------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ /** @defgroup Group1 Private_Functions * @brief Function used only in this file and NOT visible to the rest of the * code. * @{ */ /** * @brief Ricava da una maschera di bit, la posizione del primo bit della maschera * stessa. * @note No one. * @param gbp_mask maschera di bit * @retval uint8_t posizione del primo bit nella maschera * @todo Nothing. * @warning No one. */ static uint8_t adxl355_get_bit_position(uint8_t gbp_mask) { uint8_t gbp_index; for(gbp_index = 0; gbp_index < 8; gbp_index++) { if(((gbp_mask>>gbp_index) & 0x01) != 0) { break; }else{} } return gbp_index; } /** * @brief Funzione per la scrittura di un parametro su di un registro dell'accelerometro. * @note No one. * @param sp_reg indirizzo del registro da settare * @param sp_mask_data posizione del/i bit da settare sotto forma di maschera * @param sp_data valore del/i bit da settare * @retval uint16_t errore restituito dal metodo (se 0, tutto ok) * @todo Nothing. * @warning No one. */ static uint16_t adxl355_set_parameter(uint8_t sp_reg, uint8_t sp_mask_data, uint8_t sp_data) { uint16_t adxl_sp_error = 0u; uint8_t adxl_sp_data[2]; /* Lettura del registro */ adxl_sp_data[0] = (uint8_t)((sp_reg << 1) | ADXL355_READ_BYTE_MASK); adxl_sp_data[1] = 0x00; if(adxl355_spi_transfer((uint8_t*)&adxl_sp_data, 2) == 0) { adxl_sp_data[0] = (uint8_t)((sp_reg << 1) & ADXL355_WRITE_BYTE_MASK); adxl_sp_data[1] &= (uint8_t)~sp_mask_data; adxl_sp_data[1] |= (uint8_t)(sp_data << (adxl355_get_bit_position(sp_mask_data))); /* Scrittura del nuovo valore */ if(adxl355_spi_transfer((uint8_t*)&adxl_sp_data, 2) == 0) {} else { adxl_sp_error = (uint16_t)__LINE__;//ERRORE SCRITTURA REGISTRO } } else { adxl_sp_error = (uint16_t)__LINE__;//ERRORE LETTURA REGISTRO } return adxl_sp_error; } /** * @brief Funzione di lettura del dato grezzo di accelerazione lungo gli assi * X, Y e Z dell'accelerometro. * @note No one. * @param adxl_acc puntatore all'handler dell'accelerometro * @retval uint16_t errore restituito dal metodo (se 0, tutto ok) * @todo No one. * @warning No one. */ static uint16_t adxl355_read_acc_value(adxl355_handler *adxl_acc) { uint16_t adxl_read_acc_error = 0u; uint8_t adxl_read_acc_data[10]; /* Azzeramento buffer dati SPI */ memset(adxl_read_acc_data, 0x00, 10); adxl_read_acc_data[0u] = (uint8_t)((ADXL355_XDATA3<<1) | ADXL355_READ_BYTE_MASK); if(adxl355_spi_transfer((uint8_t*)&adxl_read_acc_data, 10) == 0) { adxl_acc->raw_acc_x_value = 0u; adxl_acc->raw_acc_x_value = (adxl_read_acc_data[1]<<16u) | (adxl_read_acc_data[2]<<8u) | (adxl_read_acc_data[3]); adxl_acc->raw_acc_x_value = (adxl_acc->raw_acc_x_value>>4u) & ADXL355_20_BIT_MASK; adxl_acc->raw_acc_y_value = 0u; adxl_acc->raw_acc_y_value = (adxl_read_acc_data[4]<<16u) | (adxl_read_acc_data[5]<<8u) | (adxl_read_acc_data[6]); adxl_acc->raw_acc_y_value = (adxl_acc->raw_acc_y_value>>4u) & ADXL355_20_BIT_MASK; adxl_acc->raw_acc_z_value = 0u; adxl_acc->raw_acc_z_value = (adxl_read_acc_data[7]<<16u) | (adxl_read_acc_data[8]<<8u) | (adxl_read_acc_data[9]); adxl_acc->raw_acc_z_value = (adxl_acc->raw_acc_z_value>>4u) & ADXL355_20_BIT_MASK; } else { adxl_read_acc_error = (uint16_t)__LINE__;//ERRORE LETTURA DATI ACCELERAZIONE } return adxl_read_acc_error; } /** * @brief Funzione di lettura del dato grezzo di temperatura fornito dall'accelerometro. * @note No one. * @param adxl_temp puntatore all'handler dell'accelerometro * @retval uint16_t errore restituito dal metodo (se 0, tutto ok) * @todo No one. * @warning No one. */ static uint16_t adxl355_read_temp_value(adxl355_handler *adxl_temp) { uint16_t adxl_read_temp_error = 0u; uint8_t adxl_read_temp_data[3]; /* Azzeramento buffer dati SPI */ memset(adxl_read_temp_data, 0x00, 3); adxl_read_temp_data[0u] = (uint8_t)((ADXL355_TEMP2<<1) | ADXL355_READ_BYTE_MASK); if(adxl355_spi_transfer((uint8_t*)&adxl_read_temp_data, 3) == 0) { adxl_temp->raw_temp_value = 0u; adxl_temp->raw_temp_value = (adxl_read_temp_data[1]<<8u) | adxl_read_temp_data[2]; adxl_temp->raw_temp_value &= ADXL355_12_BIT_MASK; } else { adxl_read_temp_error = (uint16_t)__LINE__;//ERRORE LETTURA DATI ACCELERAZIONE } return adxl_read_temp_error; } /** * @} */ /* Exported functions --------------------------------------------------------*/ /** @defgroup Group2 Exported_Functions * @brief Functions used in this file and also visible to the rest of the * code. * @{ */ /** * @brief Funzione che restituisce i parametri identificativi del driver. * @note No one. * @param adxl355_driver_version puntatore all'identificatore di versione del driver * @param adxl355_driver_revision puntatore all'identificatore di revisione del driver * @param adxl355_driver_patch puntatore all'identificatore di patch del driver * @retval No one. * @todo No one. * @warning No one. */ void adxl355_driver_info(uint8_t * adxl355_driver_version, uint8_t * adxl355_driver_revision, uint8_t * adxl355_driver_patch) { *adxl355_driver_version = ADXL355_VERSION; *adxl355_driver_revision = ADXL355_REVISION; *adxl355_driver_patch = ADXL355_PATCH; } /** * @brief Funzione che restituisce l'ID dell'accelerometro. * @note No one. * @param adxl355_device_id puntatore all'identificatore del device * @retval uint16_t errore restituito dal metodo (se 0, tutto ok) * @todo No one. * @warning No one. */ uint16_t adxl355_who_am_i(uint8_t * adxl355_device_id) { uint16_t adxl_whoami_error = 0u; uint8_t adxl_whoami_data[2]; /* Lettura del registro */ adxl_whoami_data[0] = (uint8_t)((ADXL355_PARTID << 1) | ADXL355_READ_BYTE_MASK); adxl_whoami_data[1] = 0x00; if(adxl355_spi_transfer((uint8_t*)&adxl_whoami_data, 2) == 0) { *adxl355_device_id = adxl_whoami_data[1]; } else { adxl_whoami_error = (uint16_t)__LINE__;//ERRORE LETTURA ID } return adxl_whoami_error; } /** * @brief Funzione di inizializzazione dell'accelerometro. * @note No one. * @param adxl_init_handler puntatore all'handler dell'accelerometro * @retval uint16_t errore restituito dal metodo (se 0, tutto ok) * @todo No one. * @warning No one. */ uint16_t adxl355_init(adxl355_handler *adxl_init_handler) { uint16_t adxl_init_error = 0u; uint8_t adxl_init_state = 0u; switch(adxl_init_state) { case 0:/* Configurazione range di misura */ if(0u == adxl355_set_parameter(ADXL355_RANGE, ADXL355_RANGE_MASK, (uint8_t)adxl_init_handler->measure_range)) {} else { adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING RANGE DI MISURA break; } case 1:/* Configurazione output data rate */ if(0u == adxl355_set_parameter(ADXL355_FILTER, ADXL355_ODR_MASK, (uint8_t)adxl_init_handler->out_data_rate)) {} else { adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING OUTPUT DATA RATE break; } case 2:/* Configurazione polarità interrupt */ if((adxl_init_handler->int1_pin == NULL) && (adxl_init_handler->int2_pin == NULL)){}//Se i pin non sono configurati, è inutile configurare la polarità degli interrupt else { if(0u == adxl355_set_parameter(ADXL355_RANGE, ADXL355_ODR_MASK, (adxl_init_handler->int_config.int_act_low==true) ? 0:1)) {} else { adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING POLARITA' INTERRUPT break; } } case 3:/* Configurazione interrupt 1 */ if(adxl_init_handler->int1_pin == NULL){}//Se il pin non è configurato, è inutile configurare il relativo interrupt else { if(0u == adxl355_set_parameter(ADXL355_INT_MAP, ADXL355_INT_1_MASK, (uint8_t)adxl_init_handler->int_config.int1_evt)) {} else { adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING EVENTO ASSOCIATO AD INTERRUPT 1 break; } } case 4:/* Configurazione interrupt 2 */ if(adxl_init_handler->int2_pin == NULL){}//Se il pin non è configurato, è inutile configurare il relativo interrupt else { if(0u == adxl355_set_parameter(ADXL355_INT_MAP, ADXL355_INT_2_MASK, (uint8_t)adxl_init_handler->int_config.int2_evt)) {} else { adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING EVENTO ASSOCIATO AD INTERRUPT 2 break; } } case 5:/* Stop di tutte le possibili misure */ if(0u == adxl355_start_acquisition(adxl355_none)) {} else { adxl_init_error = (uint16_t)__LINE__;//ERRORE SETTING STOP MISURE break; } case 6:/* Self-test disabilitato */ if(0u == adxl355_self_test(false)) {} else { adxl_init_error = (uint16_t)__LINE__;//ERRORE DISABILITAZIONE SELF-TEST break; } default: break; } return adxl_init_error; } /** * @brief Funzione di start/stop delle acquisizioni. * @note No one. * @param adxl_start misura/e da avviare * @retval uint16_t errore restituito dal metodo (se 0, tutto ok) * @todo No one. * @warning No one. */ uint16_t adxl355_start_acquisition(adxl355_measure_enabled adxl_start) { uint16_t adxl_start_error = 0u; uint8_t adxl_start_data; switch(adxl_start) { case 0://Solo accelerazione adxl_start_data = 0x02; break; case 1://Entrambe le misure (accelerazione e temperatura) adxl_start_data = 0x00; break; case 2://Nessuna misura (mette in standby il sensore) adxl_start_data = 0x03; break; default: break; } if(0u == adxl355_set_parameter(ADXL355_POWER_CTL, ADXL355_MEAS_MASK, adxl_start_data)) { adxl_measure_on = adxl_start; } else { adxl_start_error = (uint16_t)__LINE__;//ERRORE SETTING RANGE DI MISURA } return adxl_start_error; } /** * @brief Funzione per la lettura del/i dato/i acquisito/i. * @note No one. * @param adxl_data_handler puntatore all'handler dell'accelerometro * @retval uint16_t errore restituito dal metodo (se 0, tutto ok) * @todo No one. * @warning No one. */ uint16_t adxl355_get_data(adxl355_handler *adxl_data_handler) { uint16_t adxl_data_error = 0u; if((adxl_measure_on == adxl355_acc) || (adxl_measure_on == adxl355_both)) { /* Lettura accelerazione */ if(adxl355_read_acc_value(adxl_data_handler) == 0u) { if(adxl_measure_on == adxl355_both) { /* Lettura temperatura */ if(adxl355_read_temp_value(adxl_data_handler) == 0u) {} else { adxl_data_error = (uint16_t)__LINE__;//ERRORE LETTURA MISURA TEMPERATURA } } else{} } else { adxl_data_error = (uint16_t)__LINE__;//ERRORE LETTURA MISURA ACCELERAZIONE } }else{} return adxl_data_error; } /** * @brief Funzione che restituisce il valore grezzo di accelerazione lungo l'asse X. * @note No one. * @param adxl_xdata_handler puntatore all'handler dell'accelerometro * @retval uint32_t valore grezzo accelerazione * @todo No one. * @warning No one. */ uint32_t adxl355_raw_x_acc(adxl355_handler *adxl_xdata_handler) { return adxl_xdata_handler->raw_acc_x_value; } /** * @brief Funzione che restituisce il valore grezzo di accelerazione lungo l'asse Y. * @note No one. * @param adxl_ydata_handler puntatore all'handler dell'accelerometro * @retval uint32_t valore grezzo accelerazione * @todo No one. * @warning No one. */ uint32_t adxl355_raw_y_acc(adxl355_handler *adxl_ydata_handler) { return adxl_ydata_handler->raw_acc_y_value; } /** * @brief Funzione che restituisce il valore grezzo di accelerazione lungo l'asse Z. * @note No one. * @param adxl_zdata_handler puntatore all'handler dell'accelerometro * @retval uint32_t valore grezzo accelerazione * @todo No one. * @warning No one. */ uint32_t adxl355_raw_z_acc(adxl355_handler *adxl_zdata_handler) { return adxl_zdata_handler->raw_acc_z_value; } /** * @brief Funzione che restituisce il valore grezzo di temperatura. * @note No one. * @param adxl_tdata_handler puntatore all'handler dell'accelerometro * @retval uint16_t valore grezzo temperatura * @todo No one. * @warning No one. */ uint16_t adxl355_raw_temp(adxl355_handler *adxl_tdata_handler) { return adxl_tdata_handler->raw_temp_value; } /** * @brief Funzione per il reset sw. * @note No one. * @param No one. * @retval uint16_t errore restituito dal metodo (se 0, tutto ok) * @todo No one. * @warning No one. */ uint16_t adxl355_sw_reset(void) { uint16_t adxl_swres_error = 0u; uint8_t adxl_swres_data[2]; /* Lettura del registro */ adxl_swres_data[0] = (uint8_t)((ADXL355_RESET << 1) & ADXL355_WRITE_BYTE_MASK); adxl_swres_data[1] = ADXL355_RESET_CODE; if(adxl355_spi_transfer((uint8_t*)&adxl_swres_data, 2) == 0) {} else { adxl_swres_error = (uint16_t)__LINE__;//ERRORE RESET ACCELEROMETRO } return adxl_swres_error; } /** * @brief Funzione per il self-test. * @note Questo metodo va utilizzato lanciandolo ponendo a true adxl_start * ad acquisizione in corso; in questa modalità il metodo va lanciato * diverse volte in modo che si possa registrare la variazione di * accelerazione sui 3 assi che deve essere, secondo datasheet: * [X]: 0.3g * [Y]: 0.3g * [Z]: 1.5g * In modalità self-test, il sensore non registra alcuna accelerazione * esterna; ponendo a false adxl_start, il sensore termina il self-test * e ritorna in modalità normale di funzionamento. * @param adxl_start booleano per avviare/fermare il self test * @retval uint16_t errore restituito dal metodo (se 0, tutto ok) * @todo No one. * @warning No one. */ uint16_t adxl355_self_test(bool adxl_start) { uint16_t adxl_st_error = 0u; static uint8_t adxl_st2_val = 0u; if(adxl_start == true) { adxl_measure_on = adxl355_acc; if(0u == adxl355_set_parameter(ADXL355_SELF_TEST, ADXL355_SELF_TEST_MASK, (adxl_st2_val<<1)|ADXL355_SELF_TEST_ENABLE )) { if(adxl_st2_val == 0u) adxl_st2_val = 1u; else adxl_st2_val = 0u; } else { adxl_st_error = (uint16_t)__LINE__;//ERRORE AVVIO SELF-TEST } } else { if(0u == adxl355_set_parameter(ADXL355_SELF_TEST, ADXL355_SELF_TEST_MASK, ADXL355_SELF_TEST_DISABLE)) { adxl_st2_val = 0u; } else { adxl_st_error = (uint16_t)__LINE__;//ERRORE STOP SELF-TEST } } return adxl_st_error; } /** * @} */ /** * @} */ /************************ (C) COPYRIGHT TD Group *****END OF FILE**************/