Longan nano を使ってみた [3] – I2C で温度センサを接続

前回までで、Longan Nano の基本的な開発手順とボード上の LCD への表示方法が分かりましたので、次は外部デバイスとの接続を試していきたいと思います.

I2C で温度センサ TMP102 を接続

まずは I2C を使った外部デバイスとの接続を試してみます.接続するデバイスは、以前に Raspberry pi pico との接続を確認した TMP102 のモジュールとしました.
ハードウェア接続
Longan Nano と TMP102 モジュール間の接続は、I2C と電源・GND 端子の4本のみになります.どちらの基板上にも端子名のシルク表示がありますので、それに従って TMP102 モジュールの SCL / SDA 端子を Longan Nano の B6 / B7 端子に、TMP102 モジュールの GND / 1.4-3.6V 端子を Longan Nano の G / 3V3 端子にそれぞれ接続します.ADD0端子はオープンとしていますので、I2C スレーブアドレスは 0x48 となります.
ソフトウェア
Platform IO IDE で作成したプロジェクトの main.c に I2C 周りの関数を追加します.
static void i2c0_config(void);
static int i2c_write(uint8_t i2cAddress, const uint8_t *data, size_t size);
static int i2c_read(uint8_t i2cAddress, uint8_t *data, size_t size);

/* I2C の初期設定(I2C0, SCL = 100kHz) */
static void i2c0_config(void)
{
    i2c_clock_config(I2C0, 100000, I2C_DTCY_2);
    i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0);
    i2c_enable(I2C0);
    i2c_ack_config(I2C0, I2C_ACK_ENABLE);
}

/* I2C 書き込み */
static int i2c_write(uint8_t i2cAddress, const uint8_t *data, size_t size)
{
    while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) ;   // wait until I2C bus is idle
    i2c_start_on_bus(I2C0);                        // send a start condition to I2C bus
    while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));   // wait until SBSEND bit is set
    i2c_master_addressing(I2C0, i2cAddress << 1, I2C_TRANSMITTER);  // send slave address to I2C bus
    while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) ; // wait until ADDSEND bit is set
    i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);        // clear ADDSEND bit
    while(!i2c_flag_get(I2C0, I2C_FLAG_TBE));      // wait until the transmit data buffer is empty
    
    for(size_t i = 0 ; i < size ; i++) {
        i2c_data_transmit(I2C0, data[i]) ;           // data transmission
        while(!i2c_flag_get(I2C0, I2C_FLAG_TBE));    // wait until the TBE bit is set
    }
    
    i2c_stop_on_bus(I2C0);                         // send a stop condition to I2C bus
    while(I2C_CTL0(I2C0) & 0x0200);                // wait until stop condition generate

  return 0;
}

/* I2C 読み出し */
static int i2c_read(uint8_t i2cAddress, uint8_t *data, size_t size)
{
    while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY)) ;   // wait until I2C bus is idle
    i2c_start_on_bus(I2C0);                        // send a start condition to I2C bus
    while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));   // wait until SBSEND bit is set
    i2c_master_addressing(I2C0, i2cAddress << 1, I2C_RECEIVER); // send slave address to I2C bus
    while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND)) ; // wait until ADDSEND bit is set
    i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);        // clear ADDSEND bit
  
    for(size_t i = 0 ; i < size ; i++) {
        if(i == (size - 1)) // wait until the second last data byte is received into the shift register
        {
            while(!i2c_flag_get(I2C0, I2C_FLAG_BTC));
            i2c_ack_config(I2C0, I2C_ACK_DISABLE);     // disable acknowledge
        }
    
        while(!i2c_flag_get(I2C0, I2C_FLAG_RBNE)) ;  // wait until the RBNE bit is set
        data[i] = i2c_data_receive(I2C0) ;           // read a data from I2C_DATA
    }
    
    
    i2c_stop_on_bus(I2C0);                         // send a stop condition to I2C bus
    while(I2C_CTL0(I2C0) & 0x0200) ;               // wait until stop condition generate
    i2c_ack_config(I2C0, I2C_ACK_ENABLE);          // enable acknowledge
    
    return 0;
}
main() 内で定期的に上記関数を読んでセンサにアクセスし温度データを取得、LCD に表示しています.
int main(void)
{
    u8 data[2];
    u8 buf[12];
    longan_led_init();

    Lcd_Init();             // LCD を初期化
    LCD_Clear( CYAN );      // LCD をクリア
    BACK_COLOR = BLACK;     // 文字の背景色

    rcu_periph_clock_enable(RCU_I2C0);
    gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7); //I2C0
    i2c0_config();

    while(1) {
        i2c_read(0x48, data, 2);
        snprintf(buf, 12, "Temp = %d.", data[0]);
        LCD_ShowString( 5, 10, buf, GREEN );

        /* turn on builtin led */
        longan_led_on();
        delay_1ms(100);
        /* turn off uiltin led */
        longan_led_off();
        delay_1ms(100);
    }
}
実行結果
実行結果
参考
プログラムの作成にあたっては、以下を参考とさせていただきました.
デバイスビジネス開拓団
MuellerA /LonganNanoTest

1件のコメント

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です