From ed49071ffaef0bdefb70975e1583cf929bb427a4 Mon Sep 17 00:00:00 2001 From: Hubald Verzijl Date: Wed, 16 Jul 2025 14:57:34 +0200 Subject: [PATCH] Working temperature readout. --- Cargo.toml | 2 + src/ad5940.rs | 141 +++++++++++++++++++++++++++++++++++++--- src/ad5940_registers.rs | 31 +++++++++ src/main.rs | 15 ++++- 4 files changed, 176 insertions(+), 13 deletions(-) create mode 100644 src/ad5940_registers.rs diff --git a/Cargo.toml b/Cargo.toml index 0a8a64e..6b4057b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,8 @@ embassy-time = { version = "0.4.0", features = ["defmt", "defmt-timestamp-uptime defmt = "1.0.1" defmt-rtt = "1.0.0" +bitflags = "2.9.1" + cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" # embedded-hal = "0.2.6" diff --git a/src/ad5940.rs b/src/ad5940.rs index 646a21b..4946167 100644 --- a/src/ad5940.rs +++ b/src/ad5940.rs @@ -1,4 +1,7 @@ -use embassy_stm32::{gpio::Output, mode::Blocking, spi::Spi}; +use embassy_stm32::{gpio::Output, mode::Blocking, spi::Spi, spi::Error}; +use embassy_time::Timer; + +use crate::ad5940_registers::*; pub struct AD5940 { spi: Spi<'static, Blocking>, @@ -10,15 +13,16 @@ impl AD5940 { AD5940 { spi, cs } } - fn read_reg_16(&mut self, address: u16) -> Result { - let addr_bytes = address.to_be_bytes(); - + async fn read_reg_16(&mut self, address: Register) -> Result { // Write address command self.cs.set_low(); self.spi.blocking_write(&[Command::SPICMD_SETADDR as u8])?; - self.spi.blocking_write(&addr_bytes)?; + self.spi.blocking_write(&[address as u16])?; self.cs.set_high(); + // Wait after cs is high + Timer::after_nanos(80).await; + // Read command self.cs.set_low(); self.spi.blocking_write(&[Command::SPICMD_READREG as u8])?; @@ -30,22 +34,139 @@ impl AD5940 { Ok(u16::from_be_bytes([data[1], data[2]])) } - pub fn get_chipid(&mut self) -> Result { - self.read_reg_16(Register::CHIPID as u16) + async fn read_reg_32(&mut self, address: Register) -> Result { + // Write address command + self.cs.set_low(); + self.spi.blocking_write(&[Command::SPICMD_SETADDR as u8])?; + self.spi.blocking_write(&[address as u16])?; + self.cs.set_high(); + + // Wait after cs is high + Timer::after_nanos(80).await; + + // Read command + self.cs.set_low(); + self.spi.blocking_write(&[Command::SPICMD_READREG as u8])?; + + let mut data = [0u8; 5]; // First byte dummy, then four data bytes + self.spi.blocking_read(&mut data)?; + self.cs.set_high(); + + Ok(u32::from_be_bytes([data[1], data[2], data[3], data[4]])) + } + + async fn write_reg_32(&mut self, address: Register, value: u32) -> Result<(), Error> { + self.write_reg_32_raw(address as u16, value).await + } + + async fn write_reg_32_raw(&mut self, address: u16, value: u32) -> Result<(), Error> { + // Write address command + self.cs.set_low(); + self.spi.blocking_write(&[Command::SPICMD_SETADDR as u8])?; + self.spi.blocking_write(&[address as u16])?; + self.cs.set_high(); + + // Wait after cs is high + Timer::after_nanos(80).await; + + // Write value command + self.cs.set_low(); + self.spi.blocking_write(&[Command::SPICMD_WRITEREG as u8])?; + self.spi.blocking_write(&[value])?; + self.cs.set_high(); + + Ok(()) + } + + async fn write_reg_16_raw(&mut self, address: u16, value: u16) -> Result<(), Error> { + // Write address command + self.cs.set_low(); + self.spi.blocking_write(&[Command::SPICMD_SETADDR as u8])?; + self.spi.blocking_write(&[address as u16])?; + self.cs.set_high(); + + // Wait after cs is high + Timer::after_nanos(80).await; + + // Write value command + self.cs.set_low(); + self.spi.blocking_write(&[Command::SPICMD_WRITEREG as u8])?; + self.spi.blocking_write(&[value])?; + self.cs.set_high(); + + Ok(()) + } + + pub async fn system_init(&mut self) -> Result<(), Error> { + // See table 14 + self.write_reg_16_raw(0x0908, 0x02C9).await?; + self.write_reg_16_raw(0x0C08, 0x206C).await?; + self.write_reg_16_raw(0x21F0, 0x0010).await?; + self.write_reg_16_raw(0x0410, 0x02C9).await?; + self.write_reg_16_raw(0x0A28, 0x0009).await?; + self.write_reg_16_raw(0x238C, 0x0104).await?; + self.write_reg_16_raw(0x0A04, 0x4859).await?; + self.write_reg_16_raw(0x0A04, 0xF27B).await?; + self.write_reg_16_raw(0x0A00, 0x8009).await?; + self.write_reg_16_raw(0x22F0, 0x0000).await?; + Ok(()) + } + + pub async fn get_chipid(&mut self) -> Result { + self.read_reg_16(Register::CHIPID).await + } + + pub async fn get_adiid(&mut self) -> Result { + self.read_reg_16(Register::ADIID).await + } + + pub async fn init_temperature(&mut self) -> Result<(), Error> { + // AFECON: + let mut config_afecon = ConfigurationRegister::reset.bits() | ConfigurationRegister::TEMPSENSEN.bits() | ConfigurationRegister::ADCEN.bits(); + self.write_reg_32(Register::AFECON, config_afecon).await?; + + // ADCCON + let config_adccon = ADCConfigurationRegister::GNPGA_1_5.bits() | ADCConfigurationRegister::MUXSELN_TEMP.bits() | ADCConfigurationRegister::MUXSELP_TEMP.bits(); + self.write_reg_32(Register::ADCCON, config_adccon).await?; + + // AFECON - start conversion + config_afecon |= ConfigurationRegister::TEMPCONVEN.bits(); + config_afecon |= ConfigurationRegister::ADCCONVEN.bits(); + self.write_reg_32(Register::AFECON, config_afecon).await?; + + Ok(()) + } + + pub async fn get_temperature(&mut self) -> Result { + // See page 57 of the datasheet for temperature calculation + let pga_gain = 1.5; + let k = 8.13; + + let mut tempsensdat0: u32 = self.read_reg_32(Register::TEMPSENSDAT).await?; + tempsensdat0 &= 0x0000FFFF; + + Ok((tempsensdat0 as f32/(pga_gain * k)) - 273.15) } } #[allow(dead_code)] #[allow(non_camel_case_types)] enum Command { - SPICMD_SETADDR = 0x20, - SPICMD_READREG = 0x6D, + SPICMD_SETADDR = 0x20, + SPICMD_READREG = 0x6D, SPICMD_WRITEREG = 0x2D, SPICMD_READFIFO = 0x5F, } +#[allow(dead_code)] #[allow(non_camel_case_types)] #[repr(u16)] enum Register { - CHIPID = 0x0000_0404, // Changed from u32 to u16, as expected by SPI write + ADIID = 0x0000_0400, // Analog Devices Inc., identification register + CHIPID = 0x0000_0404, // Chip identification register + AFECON = 0x0000_2000, // Configuration Register + TEMPSENSDAT = 0x0000_2084, // Temperature Sensor Result Register + ADCDAT = 0x0000_2074, // ADC Raw Result Register + TEMPSENS = 0x0000_2174, // Temperature Sensor Configuration Register + ADCCON = 0x0000_21A8, // ADC Configuration Register } diff --git a/src/ad5940_registers.rs b/src/ad5940_registers.rs new file mode 100644 index 0000000..10c0c3d --- /dev/null +++ b/src/ad5940_registers.rs @@ -0,0 +1,31 @@ +use bitflags::bitflags; + +bitflags! { + // Address 0x00002000, Reset: 0x00080000, Name: AFECON + pub struct ConfigurationRegister: u32 { + const reset = 0x00080000; + const DACBUFEN = 1 << 21; + const DACREFEN = 1 << 20; + const SINC2EN = 1 << 16; + const DFTEN = 1 << 15; + const WAVEGENEN = 1 << 14; + const TEMPCONVEN = 1 << 13; + const TEMPSENSEN = 1 << 12; + const TIAEN = 1 << 11; + const INAMPEN = 1 << 10; + const EXBUFEN = 1 << 9; + const ADCCONVEN = 1 << 8; + const ADCEN = 1 << 7; + const DACEN = 1 << 6; + const HSREFDIS = 1 << 5; + } +} + +bitflags! { + // Address 0x000021A8, Reset: 0x00000000, Name: ADCCON + pub struct ADCConfigurationRegister: u32 { + const GNPGA_1_5 = 1 << 16; + const MUXSELN_TEMP = 0b01011 << 8; + const MUXSELP_TEMP = 0b01011; + } +} diff --git a/src/main.rs b/src/main.rs index 6c5b5d0..5e61a74 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,13 +4,15 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::gpio::{Level, Output, Speed}; -use embassy_stm32::{spi, Config}; +use embassy_stm32::{adc, spi, Config}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; mod ad5940; use ad5940::AD5940; +mod ad5940_registers; + #[embassy_executor::main] async fn main(_spawner: Spawner) { @@ -43,11 +45,18 @@ async fn main(_spawner: Spawner) { ); let mut ad5940 = AD5940::new(spi, cs); + ad5940.system_init().await.unwrap(); + + ad5940.init_temperature().await.unwrap(); loop { // Read chip id - let chip_id = ad5940.get_chipid().unwrap(); - info!("Chip ID: 0x{:04X}", chip_id); + // let chip_id = ad5940.get_chipid().await.unwrap(); + // info!("Chip ID: 0x{:04X}", chip_id); + + // Read temperature + let temp = ad5940.get_temperature().await.unwrap(); + info!("Temperature: {}°C", temp); // info!("high"); // led.set_high();