LoginSignup
0
0

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-05-06

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


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

SPIを使用する時の注意点は、以下の通り
・SPI の mode設定は、mode3
・SPI の frequency を 8MHz以下のに設定
・CS(Chip Select) ピンを High にした後、nRF52を SPI設定を行う。

nRF52 のプログラム
nRF52480 で確認をした。ベースにしたプログラムは、SDKに収められている
SDK\examples\peripheral\spi をベースにした。

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

尚、ADXL345 と nRF52840 の接続は、以下の通り
[ADXL345] - - - - - - - - - - - - ---- [nRF52840]
CS(Chip Select) - - - - - - ------ SPI_SS_PIN (P0.31)
SDO(Serial Data Output) ----- SPI_MISO_PIN(P0.30)
SDA(Serial Data Input) - - - -- SPI_MOSI_PIN(P0.29)
SCL(Serial Comunication)----- SPI_SCK_PIN (P0.26)

main.c
#define SPI_INSTANCE  0 /**< SPI instance index. */
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */
static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */

#define TEST_STRING "012456789012345678901234567890"
static uint8_t       m_tx_buf[] = TEST_STRING;           /**< TX buffer. */
static uint8_t       m_rx_buf[sizeof(TEST_STRING) + 1];  /**< RX buffer. */
static const uint8_t m_length = sizeof(m_tx_buf);        /**< Transfer length. */

/*************************** REGISTER MAP ********************************/
#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
-- 省略 --

/*
 * Read & Write data from ADXL345 Register.
 */
static void adxl345_spi_transfer(uint8_t rw_mode, uint8_t length)
{
    ret_code_t err_code;
 
    spi_xfer_done = false;

    switch(rw_mode)
    {
      //Single Read
      case 1:
        m_tx_buf[0] = 0x80|m_tx_buf[0];
        break;

      //Multi Read
      case 2:
        m_tx_buf[0] = 0x80|0x40|m_tx_buf[0];
        break;

      //Single Write
      case 3:
        //m_tx_buf[0] = m_tx_buf[0];
        break;
       
      //Multi Write
      case 4:
        m_tx_buf[0] = 0x40|m_tx_buf[0];
        break;

      default:
        break;
    }

    err_code = nrf_drv_spi_transfer(&spi, m_tx_buf, length, m_rx_buf, length);
    APP_ERROR_CHECK(err_code);
    while (spi_xfer_done == false);
}

static void adxl345_read_acceler()
{
    // Read Write Mode
    // Single  Read:1
    // Multi   Read:2
    // Single Write:3
    // Multi  Write:4
    uint8_t   rw_mode;
    uint8_t   rw_length;

    memset(m_rx_buf, 0, m_length);
    memset(m_tx_buf, 0, m_length);

    m_tx_buf[0] = ADXL345_DATAX0;
    rw_length = 7;
    rw_mode   = 2; //Multi Read
    adxl345_spi_transfer(rw_mode, rw_length);
    nrf_delay_ms(10);
    NRF_LOG_INFO("Read Accelerometer:%02X%02X-%02X%02X-%02X%02X", m_rx_buf[0],m_rx_buf[1], m_rx_buf[2],m_rx_buf[3], m_rx_buf[4],m_rx_buf[5]);
}

int main(void)
{  
-- 省略 --
   /*
    * for ADXL345 First ALL Pin Clear
    */
    nrf_gpio_pin_clear(SPI_SS_PIN);
    nrf_gpio_pin_clear(SPI_MISO_PIN);
    nrf_gpio_pin_clear(SPI_MOSI_PIN);
    nrf_gpio_pin_clear(SPI_SCK_PIN);

    NRF_LOG_INFO("\n\rADXL345 Ready.......");
    NRF_LOG_FLUSH();
    nrf_delay_ms(2000);

   /*
    * for ADXL345
    * If power is applied to the ADXL345
    * before set MODE2 to nRF52 (the clock polarity and phase of the host processor are configured),
    * the CS pin should be brought high before set MODE2 to nRF52(changing the clock polarity and phase). 
    */
    nrf_gpio_pin_set(SPI_SS_PIN);
    nrf_delay_ms(1);

    /*
     *       [ADXL345]  ---------------- [nRF52840]
     *   CS(Chip Select) ------------ SPI_SS_PIN  (P0.31)
     *  SDO(Serial Data Output) ----- SPI_MISO_PIN(P0.30)
     *  SDA(Serial Data Input)  ----- SPI_MOSI_PIN(P0.29)
     *  SCL(Serial Comunication)----- SPI_SCK_PIN (P0.26)
     */
    nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
    spi_config.ss_pin    = SPI_SS_PIN;
    spi_config.miso_pin  = SPI_MISO_PIN;
    spi_config.mosi_pin  = SPI_MOSI_PIN;
    spi_config.sck_pin   = SPI_SCK_PIN;

    // for ADXL345
    spi_config.frequency = NRF_DRV_SPI_FREQ_8M;
    spi_config.mode      = NRF_DRV_SPI_MODE_3;

    APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));

   /*
    * Check ADXL345 Device ID=0xE5
    */
    while(m_rx_buf[1]!=0xE5)
    {
      memset(m_rx_buf, 0, m_length);
      memset(m_tx_buf, 0, m_length);

      m_tx_buf[0] = ADXL345_DEVID;
      rw_mode   = 1; //Single Read
      rw_length = 2;
      adxl345_spi_transfer(rw_mode, rw_length);
      NRF_LOG_INFO("ADXL345_DEVID:%02X-%02X", m_rx_buf[0], m_rx_buf[1]);
      nrf_delay_ms(10);
    }

   /*
    * Check All Register ADXL345
    */
    memset(m_rx_buf, 0, m_length);
    memset(m_tx_buf, 0, m_length);

    m_tx_buf[0] = ADXL345_THRESH_TAP;
    rw_mode   =  2; //Multi Read
    rw_length = 30;
    adxl345_spi_transfer(rw_mode, rw_length);
    NRF_LOG_INFO("ADXL345_BW_RATE   :%02X", m_rx_buf[16]);
    NRF_LOG_INFO("ADXL345_INT_SOURCE:%02X", m_rx_buf[20]);
    nrf_delay_ms(10);

    ///////////////////////////////////////
    // Write data to DATA FORMAT(0x31)
    // D1  D0  gRange
    //  0  0   ±2g
    //  0  1   ±4g
    //  1  0   ±8g
    //  1  1  ±16g
    ///////////////////////////////////////
    memset(m_rx_buf, 0, m_length);
    memset(m_tx_buf, 0, m_length);

    m_tx_buf[0] = ADXL345_DATA_FORMAT;
    m_tx_buf[1] = 0x0B;
    rw_length = 2;
    rw_mode   = 3; // Single Write
    adxl345_spi_transfer(rw_mode, rw_length);
    nrf_delay_ms(10);

#if 0
    ///////////////////////////////////////
    // Cheack data to DATA FORMAT(0x31)
    ///////////////////////////////////////
    memset(m_rx_buf, 0, m_length);
    memset(m_tx_buf, 0, m_length);

    m_tx_buf[0] = ADXL345_DATA_FORMAT;
    rw_length = 2;
    rw_mode   = 1; // Single Read
    adxl345_spi_transfer(rw_mode, rw_length);
    nrf_delay_ms(10);
#endif

    ///////////////////////////////////////
    // Write data to POWER CTL(0x2D)
    // D3:1 - measurement mode
    // D3:0 - standby mode 
    memset(m_rx_buf, 0, m_length);
    memset(m_tx_buf, 0, m_length);

    m_tx_buf[0] = ADXL345_POWER_CTL;
    m_tx_buf[1] = 0x08;
    rw_length = 2;
    rw_mode   = 3; //Single Write
    adxl345_spi_transfer(rw_mode, rw_length);
    nrf_delay_ms(10);

    while (1)
    {

      adxl345_read_acceler();

      while (!spi_xfer_done)
      {
        __WFE(); 
      }

      NRF_LOG_FLUSH();

      bsp_board_led_invert(BSP_BOARD_LED_0);
      nrf_delay_ms(200);
    }
}
-- 省略 --




☆2022年 4月19日(火) 午前8時55分 初版(Ver1.00) 作成

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0