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-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"
|
||||
|
||||
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 {
|
||||
spi: Spi<'static, Blocking>,
|
||||
@@ -10,15 +13,16 @@ impl AD5940 {
|
||||
AD5940 { spi, cs }
|
||||
}
|
||||
|
||||
fn read_reg_16(&mut self, address: u16) -> Result<u16, embassy_stm32::spi::Error> {
|
||||
let addr_bytes = address.to_be_bytes();
|
||||
|
||||
async fn read_reg_16(&mut self, address: Register) -> Result<u16, Error> {
|
||||
// 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<u16, embassy_stm32::spi::Error> {
|
||||
self.read_reg_16(Register::CHIPID as u16)
|
||||
async fn read_reg_32(&mut self, address: Register) -> Result<u32, 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;
|
||||
|
||||
// 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(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
|
||||
}
|
||||
|
||||
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 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();
|
||||
|
||||
Reference in New Issue
Block a user