Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

Ubuntu22LTSでRust言語をやる その7:I2Cの実験をやる

Ubuntu22LTSでRust言語をやる その6:teensy4.0で組み込み用環境no_Stdをためす - Bye Bye Moore
の続き。
組み込みといえば外付けセンサー。
まずはI2Cのテストとして、秋月で調達しやすいADT7410を使ってみることにします
akizukidenshi.com

実際のところ

toml

[package]
name = "teensy_temp_monitor"
version = "0.1.0"
edition = "2021"

[dependencies]
cortex-m = "0.7"
cortex-m-rt = "0.7"
embedded-hal = "0.2.7"
teensy4-bsp = "0.4" #Board Support Package、
teensy4-panic = "0.2"
teensy4-usb-serial = "0.2" #USB Serialを文化的に扱う

スクリプト

#![no_std]
#![no_main]

use teensy4_panic as _;
use cortex_m_rt::entry;
use teensy4_bsp as bsp;
use embedded_hal::blocking::i2c;

// ADT7410のドライバ実装
struct ADT7410<I2C> {
    i2c: I2C,
    address: u8,
}

impl<I2C, E> ADT7410<I2C>
where
    I2C: i2c::Write<Error = E> + i2c::Read<Error = E>,
{
    pub fn new(i2c: I2C) -> Self {
        Self {
            i2c,
            address: 0x48, //デフォのI2Cアドレス
        }
    }
    
    pub fn read_temperature(&mut self) -> Result<f32, E> {
        let mut buffer = [0u8; 2];
        self.i2c
            .write_read(self.address, &[0x00], &mut buffer)?;
        
        let raw_temp = ((buffer[0] as i16) << 8) | (buffer[1] as i16);
        let temp = (raw_temp as f32) * 0.0625;
        
        Ok(temp)
    }
}

use teensy4_usb_serial::SerialPort;
use core::fmt::Write;

#[entry]
fn main() -> ! {
    // Teensyのシステム初期化
    let mut peripherals = bsp::Peripherals::take().unwrap();
    let mut led = bsp::configure_led(&mut peripherals.iomuxc);
    
    // USBシリアルの設定
    let mut serial = SerialPort::new();
    
    // I2Cの設定
    let i2c = peripherals.i2c4.configure(
        bsp::hal::i2c::ClockSpeed::KHz100,
        &mut peripherals.iomuxc.gpr,
    );
    
    let mut temp_sensor = ADT7410::new(i2c);
    
    loop {
        if let Ok(temp) = temp_sensor.read_temperature() {
            // LED点滅で動作確認
            led.toggle();
            
            // 温度をシリアルに出力
            writeln!(&mut serial, "Temperature: {:.2}°C", temp).ok();
        } else {
            writeln!(&mut serial, "Error reading temperature").ok();
        }
        
        // 3秒待機
        cortex_m::asm::delay(600_000_000 * 3);
    }
}

今回、"use cortex_m_rt::entry;"は"[entry]"ポイントを使うために必要です。
no_stdとno_mainでmain関数が無効化されてるので、"[entry]"がないと動かんというアレ。