mirror of
https://github.com/hubaldv/bioz-firmware-rs.git
synced 2025-12-06 05:01:18 +00:00
Working temperature readout.
This commit is contained in:
@@ -16,6 +16,8 @@ embassy-time = { version = "0.4.0", features = ["defmt", "defmt-timestamp-uptime
|
|||||||
defmt = "1.0.1"
|
defmt = "1.0.1"
|
||||||
defmt-rtt = "1.0.0"
|
defmt-rtt = "1.0.0"
|
||||||
|
|
||||||
|
bitflags = "2.9.1"
|
||||||
|
|
||||||
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
|
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
|
||||||
cortex-m-rt = "0.7.0"
|
cortex-m-rt = "0.7.0"
|
||||||
# embedded-hal = "0.2.6"
|
# embedded-hal = "0.2.6"
|
||||||
|
|||||||
141
src/ad5940.rs
141
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 {
|
pub struct AD5940 {
|
||||||
spi: Spi<'static, Blocking>,
|
spi: Spi<'static, Blocking>,
|
||||||
@@ -10,15 +13,16 @@ impl AD5940 {
|
|||||||
AD5940 { spi, cs }
|
AD5940 { spi, cs }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_reg_16(&mut self, address: u16) -> Result<u16, embassy_stm32::spi::Error> {
|
async fn read_reg_16(&mut self, address: Register) -> Result<u16, Error> {
|
||||||
let addr_bytes = address.to_be_bytes();
|
|
||||||
|
|
||||||
// Write address command
|
// Write address command
|
||||||
self.cs.set_low();
|
self.cs.set_low();
|
||||||
self.spi.blocking_write(&[Command::SPICMD_SETADDR as u8])?;
|
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();
|
self.cs.set_high();
|
||||||
|
|
||||||
|
// Wait after cs is high
|
||||||
|
Timer::after_nanos(80).await;
|
||||||
|
|
||||||
// Read command
|
// Read command
|
||||||
self.cs.set_low();
|
self.cs.set_low();
|
||||||
self.spi.blocking_write(&[Command::SPICMD_READREG as u8])?;
|
self.spi.blocking_write(&[Command::SPICMD_READREG as u8])?;
|
||||||
@@ -30,22 +34,139 @@ impl AD5940 {
|
|||||||
Ok(u16::from_be_bytes([data[1], data[2]]))
|
Ok(u16::from_be_bytes([data[1], data[2]]))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_chipid(&mut self) -> Result<u16, embassy_stm32::spi::Error> {
|
async fn read_reg_32(&mut self, address: Register) -> Result<u32, Error> {
|
||||||
self.read_reg_16(Register::CHIPID as u16)
|
// 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<u16, Error> {
|
||||||
|
self.read_reg_16(Register::CHIPID).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_adiid(&mut self) -> Result<u16, Error> {
|
||||||
|
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<f32, Error> {
|
||||||
|
// 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(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
enum Command {
|
enum Command {
|
||||||
SPICMD_SETADDR = 0x20,
|
SPICMD_SETADDR = 0x20,
|
||||||
SPICMD_READREG = 0x6D,
|
SPICMD_READREG = 0x6D,
|
||||||
SPICMD_WRITEREG = 0x2D,
|
SPICMD_WRITEREG = 0x2D,
|
||||||
SPICMD_READFIFO = 0x5F,
|
SPICMD_READFIFO = 0x5F,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
enum Register {
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
31
src/ad5940_registers.rs
Normal file
31
src/ad5940_registers.rs
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/main.rs
15
src/main.rs
@@ -4,13 +4,15 @@
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::gpio::{Level, Output, Speed};
|
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||||
use embassy_stm32::{spi, Config};
|
use embassy_stm32::{adc, spi, Config};
|
||||||
use embassy_time::Timer;
|
use embassy_time::Timer;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
mod ad5940;
|
mod ad5940;
|
||||||
use ad5940::AD5940;
|
use ad5940::AD5940;
|
||||||
|
|
||||||
|
mod ad5940_registers;
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
|
|
||||||
@@ -43,11 +45,18 @@ async fn main(_spawner: Spawner) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let mut ad5940 = AD5940::new(spi, cs);
|
let mut ad5940 = AD5940::new(spi, cs);
|
||||||
|
ad5940.system_init().await.unwrap();
|
||||||
|
|
||||||
|
ad5940.init_temperature().await.unwrap();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// Read chip id
|
// Read chip id
|
||||||
let chip_id = ad5940.get_chipid().unwrap();
|
// let chip_id = ad5940.get_chipid().await.unwrap();
|
||||||
info!("Chip ID: 0x{:04X}", chip_id);
|
// info!("Chip ID: 0x{:04X}", chip_id);
|
||||||
|
|
||||||
|
// Read temperature
|
||||||
|
let temp = ad5940.get_temperature().await.unwrap();
|
||||||
|
info!("Temperature: {}°C", temp);
|
||||||
|
|
||||||
// info!("high");
|
// info!("high");
|
||||||
// led.set_high();
|
// led.set_high();
|
||||||
|
|||||||
Reference in New Issue
Block a user