Expand description
§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§
Enums§
- AD7124
Burnout Current - AD7124
Channel - AD7124
ClkSource - AD7124
Error - AD7124
ExCurrent - AD7124
Filter - AD7124
Gain Sel - AD7124
Input Sel - AD7124
Operating Mode - AD7124
Post Filter - AD7124
Power Mode - AD7124RW
- AD7124
RefSource - AD7124
RegId - AD7124V
Bias Pin
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_ VBIA S0 - AD7124_
8_ IO_ CTRL2_ REG_ GPIO_ VBIA S1 - AD7124_
8_ IO_ CTRL2_ REG_ GPIO_ VBIA S2 - AD7124_
8_ IO_ CTRL2_ REG_ GPIO_ VBIA S3 - AD7124_
8_ IO_ CTRL2_ REG_ GPIO_ VBIA S4 - AD7124_
8_ IO_ CTRL2_ REG_ GPIO_ VBIA S5 - AD7124_
8_ IO_ CTRL2_ REG_ GPIO_ VBIA S6 - AD7124_
8_ IO_ CTRL2_ REG_ GPIO_ VBIA S7 - AD7124_
8_ IO_ CTRL2_ REG_ GPIO_ VBIA S8 - AD7124_
8_ IO_ CTRL2_ REG_ GPIO_ VBIA S9 - AD7124_
8_ IO_ CTRL2_ REG_ GPIO_ VBIA S10 - AD7124_
8_ IO_ CTRL2_ REG_ GPIO_ VBIA S11 - AD7124_
8_ IO_ CTRL2_ REG_ GPIO_ VBIA S12 - AD7124_
8_ IO_ CTRL2_ REG_ GPIO_ VBIA S13 - AD7124_
8_ IO_ CTRL2_ REG_ GPIO_ VBIA S14 - AD7124_
8_ IO_ CTRL2_ REG_ GPIO_ VBIA S15 - 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_ VBIA S0 - AD7124_
IO_ CTRL2_ REG_ GPIO_ VBIA S1 - AD7124_
IO_ CTRL2_ REG_ GPIO_ VBIA S2 - AD7124_
IO_ CTRL2_ REG_ GPIO_ VBIA S3 - AD7124_
IO_ CTRL2_ REG_ GPIO_ VBIA S4 - AD7124_
IO_ CTRL2_ REG_ GPIO_ VBIA S5 - AD7124_
IO_ CTRL2_ REG_ GPIO_ VBIA S6 - AD7124_
IO_ CTRL2_ REG_ GPIO_ VBIA S7 - 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