Crate ad7124_rs

Source
Expand description

crates.io

§Rust driver for 24-Bit ADC with PGA and Reference AD7124

This is a platform-independent Rust driver for AD7124, provided in both synchronous and asynchronous versions, based on the embedded-hal

The following chips are supported:

§The Device

The AD7124-8 is a low power, low noise, completely integrated analog front end for high precision measurement applications. The AD7124-8 W grade is AEC-Q100 qualified for automotive applications. The device contains a low noise, 24-bit Σ-Δ analog-to-digital converter (ADC), and can be configured to have 8 differential inputs or 15 single-ended or pseudo differential inputs. The on-chip low gain stage ensures that signals of small amplitude can be interfaced directly to the ADC.

§Initialization Methods

The library provides two ways to create an AD7124 instance:

§1. Using new method (backward compatible)

Directly accepts SPI, CS, and Delay parameters - ideal for users upgrading from previous versions:

// Synchronous version
let mut adc = AD7124Sync::new(spi, cs, delay).unwrap();

// Asynchronous version
let mut adc = AD7124Async::new(spi, cs, delay).unwrap();

§2. Using from_transport method (new flexible approach)

For more control over the transport layer:

// Create custom transport
let transport = RealSyncTransport { spi, cs, delay };

// Use transport to create AD7124 instance
let mut adc = AD7124Sync::from_transport(transport);

These methods are functionally equivalent, but from_transport provides more flexibility by allowing custom transport implementations.

§Simple Usage Example

// Initialize the AD7124 (synchronous version)
let mut adc = AD7124Sync::new(spi, cs, delay).unwrap();

// Initialize the device
adc.init().unwrap();

// Read device ID
let id = adc.read_id().unwrap();
println!("Device ID: {}", id);

// Configure ADC
adc.set_adc_control(
    AD7124OperatingMode::Continuous, 
    AD7124PowerMode::FullPower,
    AD7124ClkSource::ClkInternal,
    true
).unwrap();

// Configure channel
adc.set_channel(0, AD7124Channel::AIN0, AD7124Channel::AIN1, 0, true).unwrap();
adc.enable_channel(0, true).unwrap();

// Read data
let data = adc.read_single_raw_data(0).unwrap();
println!("Channel 0 data: {}", data);

For the asynchronous version, simply use await with the same methods:

// Initialize the AD7124 (asynchronous version)
let mut adc = AD7124Async::new(spi, cs, delay).unwrap();

// Initialize and read (with await)
adc.init().await.unwrap();
let data = adc.read_single_raw_data(0).await.unwrap();

Note: Starting from v0.3.0, the initialization API has been restructured while maintaining backward compatibility. Existing code using the previous API will continue to work without modifications.

§Usage

The example based on embassy is given below, using the STM32L432KBUx

§Asynchronous version

add the following to your Cargo.toml ad7124-rs = {version = "0.2.0" , features = ["async"]}

#![no_std]
#![no_main]

#![allow(dead_code)]
#![allow(unused_imports)]
use ad7124_rs::*;
use defmt::*;
use embassy_embedded_hal::adapter::BlockingAsync;
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_stm32::spi::{Config as spicon, Spi};
use embassy_stm32::Config;
use embassy_time::Delay;
use embassy_stm32::time::Hertz;
use {defmt_rtt as _, panic_probe as _};
#[embassy_executor::main]
async fn main(_spawner: embassy_executor::Spawner) {
    info!("Hello World!");

    let mut config = Config::default();
    {
        use embassy_stm32::rcc::*;
        config.rcc.hsi = true;
        config.rcc.pll = Some(Pll {
            source: PllSource::MSI,
            prediv: PllPreDiv::DIV1,   //pllm
            mul: PllMul::MUL40,        //plln
            divr: Some(PllRDiv::DIV2), //pllr
            divq: Some(PllQDiv::DIV2), //pllq
            divp: Some(PllPDiv::DIV7), //pllp
        });
        config.rcc.pllsai1 = Some(Pll {
            source: PllSource::MSI,
            prediv: PllPreDiv::DIV1,   //pllm
            mul: PllMul::MUL16,        //plln
            divr: Some(PllRDiv::DIV2), //pllr
            divq: Some(PllQDiv::DIV2), //pllq
            divp: Some(PllPDiv::DIV7), //pllp
        });
        config.rcc.sys = Sysclk::PLL1_R;
        config.rcc.mux.adcsel = mux::Adcsel::PLL1_Q;
    }
    let p = embassy_stm32::init(config);
    let mut spi_config = spicon::default();
    spi_config.frequency = Hertz(1_000_000);
    let spi = Spi::new_blocking(p.SPI3, p.PB3, p.PB5, p.PB4, spi_config);
    let mut spi = BlockingAsync::new(spi);

    let mut cs = Output::new(p.PA15, Level::Low, Speed::High);
    let mut sync = Output::new(p.PB6, Level::Low, Speed::High);
    sync.set_high();

    let mut sensor_clk = p.PB0;
    let mut sensor_data = p.PB1;
    let mut adc = AD7124Async::new(spi, cs, Delay).unwrap();
    adc.init().await.unwrap();
    let reg_now = adc.read_id().await;
    info!("ID:{}", reg_now);
    let init_ctrl = adc
        .set_adc_control(
            AD7124OperatingMode::Continuous,
            AD7124PowerMode::FullPower,
            AD7124ClkSource::ClkInternal,
            true,
        )
        .await;
    info!("init_ctrl:{}", init_ctrl);
    let config_set = adc
        .set_config(
            0,
            AD7124RefSource::Internal,
            AD7124GainSel::_64,
            AD7124BurnoutCurrent::Off,
            true,
        )
        .await;
    info!("config_set:{}", config_set);
    let filter_set = adc
        .set_filter(0, AD7124Filter::POST, 1, AD7124PostFilter::NoPost, false, true)
        .await;

    info!("filter_set:{}", filter_set);
    let adc_ch_set = adc
        .set_channel(0, AD7124Channel::AIN0, AD7124Channel::AIN1, 0, true)
        .await;
    info!("adc_ch_set:{}", adc_ch_set);
    let adc_ch_set2 = adc
        .set_channel(1, AD7124Channel::AIN2, AD7124Channel::AIN3, 0, true)
        .await;
    info!("adc_ch_set2:{}", adc_ch_set2);
    let pws = adc.set_pwrsw(true).await;
    info!("pws:{}", pws);

    adc.enable_channel(0, true).await.unwrap();
    adc.enable_channel(1, true).await.unwrap();
    let status = adc.read_register(AD7124RegId::RegStatus).await;
    info!("status:{}", status);
    let mut data_list = [0u32; 16];
    let errif = adc.read_multi_raw_data(&mut data_list).await;
    match errif {
        Ok(_) => {
            info!("read_multi_raw_data success");
            for i in 0..16 {
                info!("data_list[{}]:{}", i, data_list[i]);
            }
        }
        Err(e) => {
            info!("read_multi_raw_data error:{}", e);
        }
    }
    let ch1_data = adc.read_single_raw_data(0).await;
    match ch1_data {
        Ok(data) => {
            info!("ch1_data:{}", data);
        }
        Err(e) => {
            info!("ch1_data error:{}", e);
        }
    }
    let ch2_data = adc.read_single_raw_data(1).await;
    match ch2_data {
        Ok(data) => {
            info!("ch2_data:{}", data);
        }
        Err(e) => {
            info!("ch2_data error:{}", e);
        }
    }

    loop {

    }
}

§Synchronous version

add the following to your Cargo.toml ad7124-rs = {version = "0.2.0" , features = ["sync"]}

#![no_std]
#![no_main]

#![allow(dead_code)]
#![allow(unused_imports)]
use ad7124_rs::*;
use defmt::*;
use embassy_embedded_hal::adapter::BlockingAsync;
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_stm32::spi::{Config as spicon, Spi};
use embassy_stm32::Config;
use embassy_time::Delay;
use embassy_stm32::time::Hertz;
use {defmt_rtt as _, panic_probe as _};
#[embassy_executor::main]
async fn main(_spawner: embassy_executor::Spawner) {
    info!("Hello World!");

    let mut config = Config::default();
    {
        use embassy_stm32::rcc::*;
        config.rcc.hsi = true;
        config.rcc.pll = Some(Pll {
            source: PllSource::MSI,
            prediv: PllPreDiv::DIV1,   //pllm
            mul: PllMul::MUL40,        //plln
            divr: Some(PllRDiv::DIV2), //pllr
            divq: Some(PllQDiv::DIV2), //pllq
            divp: Some(PllPDiv::DIV7), //pllp
        });
        config.rcc.pllsai1 = Some(Pll {
            source: PllSource::MSI,
            prediv: PllPreDiv::DIV1,   //pllm
            mul: PllMul::MUL16,        //plln
            divr: Some(PllRDiv::DIV2), //pllr
            divq: Some(PllQDiv::DIV2), //pllq
            divp: Some(PllPDiv::DIV7), //pllp
        });
        config.rcc.sys = Sysclk::PLL1_R;
        config.rcc.mux.adcsel = mux::Adcsel::PLL1_Q;
    }
    let p = embassy_stm32::init(config);
    let mut spi_config = spicon::default();
    spi_config.frequency = Hertz(1_000_000);
    let spi = Spi::new_blocking(p.SPI3, p.PB3, p.PB5, p.PB4, spi_config);

    let mut cs = Output::new(p.PA15, Level::Low, Speed::High);
    let mut sync = Output::new(p.PB6, Level::Low, Speed::High);
    sync.set_high();

    let mut sensor_clk = p.PB0;
    let mut sensor_data = p.PB1;
    let mut adc = AD7124Sync::new(spi, cs, Delay).unwrap();
    adc.init().unwrap();
    let reg_now = adc.read_id();
    info!("ID:{}", reg_now);
    let init_ctrl = adc
        .set_adc_control(
            AD7124OperatingMode::Continuous,
            AD7124PowerMode::FullPower,
            AD7124ClkSource::ClkInternal,
            true,
        )
        ;
    info!("init_ctrl:{}", init_ctrl);
    let config_set = adc
        .set_config(
            0,
            AD7124RefSource::Internal,
            AD7124GainSel::_64,
            AD7124BurnoutCurrent::Off,
            true,
        )
        ;
    info!("config_set:{}", config_set);
    let filter_set = adc
        .set_filter(0, AD7124Filter::POST, 1, AD7124PostFilter::NoPost, false, true)
        ;

    info!("filter_set:{}", filter_set);
    let adc_ch_set = adc
        .set_channel(0, AD7124Channel::AIN0, AD7124Channel::AIN1, 0, true)
        ;
    info!("adc_ch_set:{}", adc_ch_set);
    let adc_ch_set2 = adc
        .set_channel(1, AD7124Channel::AIN2, AD7124Channel::AIN3, 0, true)
        ;
    info!("adc_ch_set2:{}", adc_ch_set2);
    let pws = adc.set_pwrsw(true);
    info!("pws:{}", pws);

    adc.enable_channel(0, true).unwrap();
    adc.enable_channel(1, true).unwrap();
    let status = adc.read_register(AD7124RegId::RegStatus);
    info!("status:{}", status);
    let mut data_list = [0u32; 16];
    let errif = adc.read_multi_raw_data(&mut data_list);
    match errif {
        Ok(_) => {
            info!("read_multi_raw_data success");
            for i in 0..16 {
                info!("data_list[{}]:{}", i, data_list[i]);
            }
        }
        Err(e) => {
            info!("read_multi_raw_data error:{}", e);
        }
    }
    let ch1_data = adc.read_single_raw_data(0);
    match ch1_data {
        Ok(data) => {
            info!("ch1_data:{}", data);
        }
        Err(e) => {
            info!("ch1_data error:{}", e);
        }
    }
    let ch2_data = adc.read_single_raw_data(1);
    match ch2_data {
        Ok(data) => {
            info!("ch2_data:{}", data);
        }
        Err(e) => {
            info!("ch2_data error:{}", e);
        }
    }

    loop {

    }
}

Re-exports§

pub use ad7124::AD7124Core;
pub use ad7124::SyncTransport;
pub use ad7124::AsyncTransport;
pub use ad7124::RealSyncTransport;
pub use ad7124::RealAsyncTransport;
pub use ad7124::ad7124_sync::AD7124 as AD7124Sync;
pub use ad7124::ad7124_async::AD7124 as AD7124Async;

Modules§

ad7124
Re-export public types and modules

Structs§

AD7124Register
AD7124Registers

Enums§

AD7124BurnoutCurrent
AD7124Channel
AD7124ClkSource
AD7124Error
AD7124ExCurrent
AD7124Filter
AD7124GainSel
AD7124InputSel
AD7124OperatingMode
AD7124PostFilter
AD7124PowerMode
AD7124RW
AD7124RefSource
AD7124RegId
AD7124VBiasPin

Constants§

AD7124_8_IO_CTRL1_REG_GPIO_CTRL1
AD7124_8_IO_CTRL1_REG_GPIO_CTRL2
AD7124_8_IO_CTRL1_REG_GPIO_CTRL3
AD7124_8_IO_CTRL1_REG_GPIO_CTRL4
AD7124_8_IO_CTRL1_REG_GPIO_DAT1
AD7124_8_IO_CTRL1_REG_GPIO_DAT2
AD7124_8_IO_CTRL1_REG_GPIO_DAT3
AD7124_8_IO_CTRL1_REG_GPIO_DAT4
AD7124_8_IO_CTRL2_REG_GPIO_VBIAS0
AD7124_8_IO_CTRL2_REG_GPIO_VBIAS1
AD7124_8_IO_CTRL2_REG_GPIO_VBIAS2
AD7124_8_IO_CTRL2_REG_GPIO_VBIAS3
AD7124_8_IO_CTRL2_REG_GPIO_VBIAS4
AD7124_8_IO_CTRL2_REG_GPIO_VBIAS5
AD7124_8_IO_CTRL2_REG_GPIO_VBIAS6
AD7124_8_IO_CTRL2_REG_GPIO_VBIAS7
AD7124_8_IO_CTRL2_REG_GPIO_VBIAS8
AD7124_8_IO_CTRL2_REG_GPIO_VBIAS9
AD7124_8_IO_CTRL2_REG_GPIO_VBIAS10
AD7124_8_IO_CTRL2_REG_GPIO_VBIAS11
AD7124_8_IO_CTRL2_REG_GPIO_VBIAS12
AD7124_8_IO_CTRL2_REG_GPIO_VBIAS13
AD7124_8_IO_CTRL2_REG_GPIO_VBIAS14
AD7124_8_IO_CTRL2_REG_GPIO_VBIAS15
AD7124_ADC_CTRL_REG
AD7124_ADC_CTRL_REG_CLK_SEL
AD7124_ADC_CTRL_REG_CONT_READ
AD7124_ADC_CTRL_REG_CS_EN
AD7124_ADC_CTRL_REG_DATA_STATUS
AD7124_ADC_CTRL_REG_DOUT_RDY_DEL
AD7124_ADC_CTRL_REG_MODE
AD7124_ADC_CTRL_REG_POWER_MODE
AD7124_ADC_CTRL_REG_REF_EN
AD7124_CFG0_REG
AD7124_CFG1_REG
AD7124_CFG2_REG
AD7124_CFG3_REG
AD7124_CFG4_REG
AD7124_CFG5_REG
AD7124_CFG6_REG
AD7124_CFG7_REG
AD7124_CFG_REG_AINN_BUFM
AD7124_CFG_REG_AIN_BUFP
AD7124_CFG_REG_BIPOLAR
AD7124_CFG_REG_BURNOUT
AD7124_CFG_REG_PGA
AD7124_CFG_REG_REF_BUFM
AD7124_CFG_REG_REF_BUFP
AD7124_CFG_REG_REF_SEL
AD7124_CH0_MAP_REG
AD7124_CH1_MAP_REG
AD7124_CH2_MAP_REG
AD7124_CH3_MAP_REG
AD7124_CH4_MAP_REG
AD7124_CH5_MAP_REG
AD7124_CH6_MAP_REG
AD7124_CH7_MAP_REG
AD7124_CH8_MAP_REG
AD7124_CH9_MAP_REG
AD7124_CH10_MAP_REG
AD7124_CH11_MAP_REG
AD7124_CH12_MAP_REG
AD7124_CH13_MAP_REG
AD7124_CH14_MAP_REG
AD7124_CH15_MAP_REG
AD7124_CH_MAP_REG_AINM
AD7124_CH_MAP_REG_AINP
AD7124_CH_MAP_REG_CH_ENABLE
AD7124_CH_MAP_REG_SETUP
AD7124_COMM_REG
AD7124_COMM_REG_RA
AD7124_COMM_REG_RD
AD7124_COMM_REG_WEN
AD7124_COMM_REG_WR
AD7124_CRC8_POLYNOMIAL_REPRESENTATION
AD7124_DATA_REG
AD7124_DEFAULT_TIMEOUT_MS
AD7124_DISABLE_CRC
AD7124_ERREN_REG
AD7124_ERREN_REG_ADC_CAL_ERR_EN
AD7124_ERREN_REG_ADC_CONV_ERR_EN
AD7124_ERREN_REG_ADC_SAT_ERR_EN
AD7124_ERREN_REG_AINM_OV_ERR_EN
AD7124_ERREN_REG_AINM_UV_ERR_EN
AD7124_ERREN_REG_AINP_OV_ERR_EN
AD7124_ERREN_REG_AINP_UV_ERR_EN
AD7124_ERREN_REG_ALDO_PSM_ERR_EN
AD7124_ERREN_REG_ALDO_PSM_TRIP_TEST_EN
AD7124_ERREN_REG_DLDO_PSM_ERR_EN
AD7124_ERREN_REG_DLDO_PSM_TRIP_TEST_EN
AD7124_ERREN_REG_LDO_CAP_CHK
AD7124_ERREN_REG_LDO_CAP_CHK_TEST_EN
AD7124_ERREN_REG_MCLK_CNT_EN
AD7124_ERREN_REG_MM_CRC_ERR_EN
AD7124_ERREN_REG_REF_DET_ERR_EN
AD7124_ERREN_REG_SPI_CRC_ERR_EN
AD7124_ERREN_REG_SPI_IGNORE_ERR_EN
AD7124_ERREN_REG_SPI_READ_ERR_EN
AD7124_ERREN_REG_SPI_SCLK_CNT_ERR_EN
AD7124_ERREN_REG_SPI_WRITE_ERR_EN
AD7124_ERR_REG
AD7124_ERR_REG_ADC_CAL_ERR
AD7124_ERR_REG_ADC_CONV_ERR
AD7124_ERR_REG_ADC_SAT_ERR
AD7124_ERR_REG_AINM_OV_ERR
AD7124_ERR_REG_AINM_UV_ERR
AD7124_ERR_REG_AINP_OV_ERR
AD7124_ERR_REG_AINP_UV_ERR
AD7124_ERR_REG_ALDO_PSM_ERR
AD7124_ERR_REG_DLDO_PSM_ERR
AD7124_ERR_REG_LDO_CAP_ERR
AD7124_ERR_REG_MM_CRC_ERR
AD7124_ERR_REG_REF_DET_ERR
AD7124_ERR_REG_SPI_CRC_ERR
AD7124_ERR_REG_SPI_IGNORE_ERR
AD7124_ERR_REG_SPI_READ_ERR
AD7124_ERR_REG_SPI_SLCK_CNT_ERR
AD7124_ERR_REG_SPI_WRITE_ERR
AD7124_FILT0_REG
AD7124_FILT1_REG
AD7124_FILT2_REG
AD7124_FILT3_REG
AD7124_FILT4_REG
AD7124_FILT5_REG
AD7124_FILT6_REG
AD7124_FILT7_REG
AD7124_FILT_REG_FILTER
AD7124_FILT_REG_FS
AD7124_FILT_REG_POST_FILTER
AD7124_FILT_REG_REJ60
AD7124_FILT_REG_SINGLE_CYCLE
AD7124_GAIN0_REG
AD7124_GAIN1_REG
AD7124_GAIN2_REG
AD7124_GAIN3_REG
AD7124_GAIN4_REG
AD7124_GAIN5_REG
AD7124_GAIN6_REG
AD7124_GAIN7_REG
AD7124_ID_REG
AD7124_ID_REG_DEVICE_ID
AD7124_ID_REG_SILICON_REV
AD7124_IO_CTRL1_REG
AD7124_IO_CTRL1_REG_GPIO_CTRL1
AD7124_IO_CTRL1_REG_GPIO_CTRL2
AD7124_IO_CTRL1_REG_GPIO_DAT1
AD7124_IO_CTRL1_REG_GPIO_DAT2
AD7124_IO_CTRL1_REG_IOUT0
AD7124_IO_CTRL1_REG_IOUT1
AD7124_IO_CTRL1_REG_IOUT_CH0
AD7124_IO_CTRL1_REG_IOUT_CH1
AD7124_IO_CTRL1_REG_PDSW
AD7124_IO_CTRL2_REG
AD7124_IO_CTRL2_REG_GPIO_VBIAS0
AD7124_IO_CTRL2_REG_GPIO_VBIAS1
AD7124_IO_CTRL2_REG_GPIO_VBIAS2
AD7124_IO_CTRL2_REG_GPIO_VBIAS3
AD7124_IO_CTRL2_REG_GPIO_VBIAS4
AD7124_IO_CTRL2_REG_GPIO_VBIAS5
AD7124_IO_CTRL2_REG_GPIO_VBIAS6
AD7124_IO_CTRL2_REG_GPIO_VBIAS7
AD7124_MAX_CHANNELS
AD7124_OFFS0_REG
AD7124_OFFS1_REG
AD7124_OFFS2_REG
AD7124_OFFS3_REG
AD7124_OFFS4_REG
AD7124_OFFS5_REG
AD7124_OFFS6_REG
AD7124_OFFS7_REG
AD7124_STATUS_REG
AD7124_STATUS_REG_CH_ACTIVE
AD7124_STATUS_REG_ERROR_FLAG
AD7124_STATUS_REG_POR_FLAG
AD7124_STATUS_REG_RDY
AD7124_USE_CRC

Functions§

calc_crc8