Help us understand the problem. What is going on with this article?

Nordic SDK でTWI(I2C)

More than 1 year has passed since last update.

「nRF52840 を Segger Embedded Studio 開発環境で First Try」
https://qiita.com/nanbuwks/items/dd20dc4619af1d994f2c
の流れで、TWI(I2C)を使った実験。

TWIって何?

よく言われるI2C。I2Cは登録商標なので IIC とか TWI と言い換えられている。

環境

  • Raytac の MDBT50Q–DB ボード
    • nRF52840 搭載
  • SEGGER Embedded Studio
    • Nordic SDK との組み合わせ

LSM6DS3

STMicroelectronics の6軸加速度センサ。
image

このブレークアウトボードを繋げてみました。
LSM6DS3 は I2C/SDIでつながりますが、今回は I2C の SDA と SDL として nRF52840 の 9 と 10 につなぎました。

バスをスキャンしてデバイスを検出する

SDKのサンプルプログラムを使って、デバイスを検出してみます。
examples/peripheral/twi_scanner
を使いました。

環境に合わせて以下を開きます。
examples/peripheral/twi_scanner/pca10056/blank/ses/twi_scanner_pca10056.emProject

サンプルプログラムはNordicの公式ボードであるPCA10056 (nRF52840 DK)を使うことになるのであれば配線が以下のようになることを前提としています。

SDA P0.26
SCL P0.27

今回は、SDAは9,SCLは10なので、プログラムに以下を書き加えることで違いに対処することにします。

#define ARDUINO_SCL_PIN 10
#define ARDUINO_SDA_PIN 9

(2019/2/18追記 上記9,10は Low Frequency I/O only 属性のピンでした。動くこともありますが不安定です。後に ARDUINO_SCL_PIN:30,: ARDUINO_SDA_PIN:31に変更したら安定しました。)

結果は、

       NRF_LOG_INFO("TWI device detected at address 0x%x.", address);

ここから出力されるので、シリアルでPCに接続していると以下のように出ます。

image

0x6B で認識しました

通信してみる

WHOAMIコマンドを使って、一番基本的な通信を行ってみます。

このセンサは TWI で 0x0Fのレジスタを読めば、固有コード 0x69 が返ってきます。

#include <stdio.h>
#include "boards.h"
#include "nrf_drv_twi.h"
#include "nrf_delay.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#define DEVICE_ADDR          0x6BU

static volatile bool m_xfer_done = false;

const nrf_drv_twi_t m_twi= NRF_DRV_TWI_INSTANCE(0);
static uint8_t m_sample;
#define ARDUINO_SCL_PIN 10
#define ARDUINO_SDA_PIN 9

/*
__STATIC_INLINE void data_handler(uint8_t data)
{
    NRF_LOG_INFO("Device Current Register Data: %d", data);
}
void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
    switch (p_event->type)
    {
        case NRF_DRV_TWI_EVT_DONE:
            if (p_event->xfer_desc.type == NRF_DRV_TWI_XFER_RX)
            {
                data_handler(m_sample);
            }
            m_xfer_done = true;
            break;
        default:
            break;
    }
}
*/

void twi_init (void)
{
    ret_code_t err_code;

    const nrf_drv_twi_config_t twi_lm75b_config = {
       .scl                = ARDUINO_SCL_PIN,
       .sda                = ARDUINO_SDA_PIN,
       .frequency          = NRF_DRV_TWI_FREQ_100K,
       .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
       .clear_bus_init     = false
    };
// non-blocking mode
//    err_code = nrf_drv_twi_init(&m_twi, &twi_lm75b_config, twi_handler, NULL);
// blocking mode
    err_code = nrf_drv_twi_init(&m_twi, &twi_lm75b_config, NULL, NULL);
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&m_twi);
}

ret_code_t read_register(nrf_drv_twi_t twi_instance, uint8_t device_addr, uint8_t register_addr, uint8_t *p_data, uint8_t bytes, bool no_stop)
{
  ret_code_t err_code;

  err_code = nrf_drv_twi_tx(&twi_instance, device_addr, &register_addr, 1, no_stop);
  APP_ERROR_CHECK(err_code);

  if(err_code != NRF_SUCCESS) {
    return err_code;
  }

  err_code = nrf_drv_twi_rx(&twi_instance, device_addr, p_data, bytes);
  return err_code;
} 

int main(void)
{
  ret_code_t err_code;
  APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
  NRF_LOG_DEFAULT_BACKENDS_INIT();
  twi_init();    // need aonodon
  while (true)
    {
       err_code =  read_register(m_twi, DEVICE_ADDR, 0x0f,&m_sample, sizeof(m_sample),false); // WHO AM I .. Return 0x69 
       NRF_LOG_INFO("WHO AM I %d.", m_sample);
       NRF_LOG_FLUSH();
       nrf_delay_ms(5000);
    }
}

上記のコードで、以下のような反応が取れました。

<info> app: WHO AMI 105.
<info> app: WHO AMI 105.
<info> app: WHO AMI 105.

`
最初は、

// non-blocking mode
    err_code = nrf_drv_twi_init(&m_twi, &twi_lm75b_config, twi_handler, NULL);
// blocking mode
//    err_code = nrf_drv_twi_init(&m_twi, &twi_lm75b_config, NULL, NULL);
    APP_ERROR_CHECK(err_code);

としていたら 0 の値しか返ってきませんでした。
あれれーと思ってこちら見てみたら、
https://devzone.nordicsemi.com/f/nordic-q-a/21920/twi-nrf_drv_twi_rx-function-retun-error-3
ブロッキングモードについて書いてあり、そのようにしたらうまくいきました。

データ取ってみる

(途中)

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした