はじめに
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)
#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) 作成