nRF52 シリーズでのADXL345(加速度センサー) をI2Cで動かす

---
***はじめに***
Nordic nRF5x シリーズで、ADXL345(加速度センサー) を動作させた時の覚書

---

***ADXL345(加速度センサー)について***
ANALOG DEVICES ADXL345(加速度センサー) に関する資料は、以下のページに置かれている
[https://www.analog.com/jp/products/adxl345.html](https://www.analog.com/jp/products/adxl345.html)

I2Cでの使用時 注意すべき点は、以下の通り
・プルアップ抵抗は、10KΩ
・CS ピンは、VDD I/O に接続
・ALT ADDRESSピンは、VDD I/O に接続(アドレス0x1D) または GNDに接続(アドレス0x53)

***nRF52 のプログラム***
nRF52480 で確認をした。ベースにしたプログラムは、[SDK](https://www.nordicsemi.com/Products/Development-software/nRF5-SDK/Download)に収められている
***SDK\examples\peripheral\twi_sensor*** をベースにした。

元にした main.c を下記の様に修正した。(一部を記載)

尚、nRF52840 側は、***SDA：P0.26 / SCL：P0.27*** の設定です。

~~~main.c
uint8_t read_buff[10]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
/*************************** REGISTER MAP ********************************/
#define ADXL345_ADDR            0x1DU       // Device Address
#define ADXL345_DEVID			0x00U		// Device ID
#define ADXL345_RESERVED1		0x01U		// Reserved. Do Not Access. 
#define ADXL345_THRESH_TAP		0x1DU		// Tap Threshold. 
#define ADXL345_OFSX			0x1EU		// X-Axis Offset. 
#define ADXL345_OFSY			0x1FU		// Y-Axis Offset.
#define ADXL345_OFSZ			0x20U		// Z- Axis Offset.
#define ADXL345_DUR		        0x21U		// Tap Duration.
#define ADXL345_LATENT			0x22U		// Tap Latency.
#define ADXL345_WINDOW			0x23U		// Tap Window.
#define ADXL345_THRESH_ACT		0x24U		// Activity Threshold
#define ADXL345_THRESH_INACT    0x25U		// Inactivity Threshold
#define ADXL345_TIME_INACT		0x26U		// Inactivity Time
#define ADXL345_ACT_INACT_CTL   0x27U		// Axis Enable Control for Activity and Inactivity Detection
#define ADXL345_THRESH_FF		0x28U		// Free-Fall Threshold.
#define ADXL345_TIME_FF			0x29U		// Free-Fall Time.
#define ADXL345_TAP_AXES		0x2AU		// Axis Control for Tap/Double Tap.
#define ADXL345_ACT_TAP_STATUS  0x2BU		// Source of Tap/Double Tap
#define ADXL345_BW_RATE			0x2CU		// Data Rate and Power mode Control
#define ADXL345_POWER_CTL		0x2DU		// Power-Saving Features Control
#define ADXL345_INT_ENABLE		0x2EU		// Interrupt Enable Control
#define ADXL345_INT_MAP			0x2FU		// Interrupt Mapping Control
#define ADXL345_INT_SOURCE		0x30U		// Source of Interrupts
#define ADXL345_DATA_FORMAT		0x31U		// Data Format Control
#define ADXL345_DATAX0			0x32U		// X-Axis Data 0
#define ADXL345_DATAX1			0x33U		// X-Axis Data 1
#define ADXL345_DATAY0			0x34U		// Y-Axis Data 0
#define ADXL345_DATAY1			0x35U		// Y-Axis Data 1
#define ADXL345_DATAZ0			0x36U		// Z-Axis Data 0
#define ADXL345_DATAZ1			0x37U		// Z-Axis Data 1
#define ADXL345_FIFO_CTL		0x38U		// FIFO Control
#define ADXL345_FIFO_STATUS		0x39U		// FIFO Status
-- 省略 --

/*
 * write data to ADXL345
 */
static void write_data_adxl345(uint8_t const *       p_data,
                              uint8_t               length)
{
    ret_code_t err_code;

    m_xfer_done = false;

    err_code = nrf_drv_twi_tx(&m_twi, ADXL345_ADDR, p_data, length, false);
    APP_ERROR_CHECK(err_code);

    while (m_xfer_done == false);
    nrf_delay_ms(1);
}

/*
 * Read data from ADXL345
 */
static void read_data_adxl345(uint8_t const *       p_data,
                              uint8_t               length)
{
    ret_code_t err_code;
    uint8_t address;

    m_xfer_done = false;

    // Write Register
    err_code = nrf_drv_twi_tx(&m_twi, ADXL345_ADDR, p_data, 1, true);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);

    nrf_delay_us(500);
    m_xfer_done = false;

    // Read Data from Register
    err_code = nrf_drv_twi_rx(&m_twi, ADXL345_ADDR, read_buff, length);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);
}

/**
 * @brief Function for reading data from temperature sensor.
 */
static void read_acceler_data()
{
      uint8_t write_data[1]={0x00};
      uint8_t   read_length;

      ///////////////////////////////////////
      // Read data 6byte from DATAX0(0x32)
      //                      DATAX1(0x33)
      //                      DATAY0(0x34)
      //                      DATAY1(0x35)
      //                      DATAZ0(0x36)
      //                      DATAZ1(0x37)
      write_data[0] = ADXL345_DATAX0;
      read_length = 6;
      read_data_adxl345(write_data, read_length);
      NRF_LOG_INFO("Read Address%02X-%02X-%02X-%02X-%02X-%02X", read_buff[0], read_buff[1], read_buff[2], read_buff[3], read_buff[4], read_buff[5]);
}

/**
 * @brief Function for main application entry.
 */
int main(void)
{
    ret_code_t err_code;
    uint8_t address;
    uint8_t write_data[5]={0x00, 0x00, 0x00, 0x00, 0x00};
    bool detected_device = false;
    uint8_t   rdat[1];
    uint8_t   read_length;

    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("*************************************");
    NRF_LOG_INFO("ADXL345(Digital Accelerometer tarted).");

    twi_init();

    while(read_buff[0]!=0xE5)
    {
      nrf_delay_ms(5);
      write_data[0] = ADXL345_DEVID;
      read_length = 1;
      read_data_adxl345(write_data, read_length);
    }
    NRF_LOG_INFO("Check Read ID:%02X", read_buff[0]);
    NRF_LOG_FLUSH();
    nrf_delay_ms(5);

    ///////////////////////////////////////
    // Write data to DATA FORMAT(0x31)
    // D1  D0  gRange
    //  0  0   ±2g
    //  0  1   ±4g
    //  1  0   ±8g
    //  1  1  ±16g
    ///////////////////////////////////////
    write_data[0] = ADXL345_DATA_FORMAT;
    write_data[1] = 0x0B;
    read_length = 2;
    write_data_adxl345(write_data, read_length);
    nrf_delay_ms(5);

    ///////////////////////////////////////
    // Write data to POWER CTL(0x2D)
    // D3:1 - measurement mode
    // D3:0 - standby mode 
    write_data[0] = ADXL345_POWER_CTL;
    write_data[1] = 0x08;
    read_length = 2;
    write_data_adxl345(write_data, read_length);
    nrf_delay_ms(5);

    while (true)
    {
        nrf_delay_ms(1);

        do
        {
            __WFE();
        }while (m_xfer_done == false);

        read_acceler_data();
        NRF_LOG_FLUSH();
    }
}
~~~
---
☆2022年 4月19日(火) 午前8時55分 初版(Ver1.00) 作成