max1968: Fix ADC+DMA does not start converting bug

This commit is contained in:
linuswck 2024-03-15 14:45:19 +08:00
parent 74c465d16f
commit 1480305c16
1 changed files with 59 additions and 32 deletions

View File

@ -1,15 +1,14 @@
use crate::thermostat::ad5680; use crate::thermostat::ad5680;
use fugit::KilohertzU32; use fugit::KilohertzU32;
use stm32_eth::stm32::{ADC2, DMA2};
use stm32f4xx_hal::{ use stm32f4xx_hal::{
adc::{config::{self, AdcConfig}, Adc}, adc::{config::{self, AdcConfig}, Adc},
dma::{config::DmaConfig, PeripheralToMemory, Stream2, StreamsTuple, Transfer as DMA_Transfer}, dma::{config::DmaConfig, PeripheralToMemory, Stream2, StreamsTuple, Transfer as DMA_Transfer},
gpio::{gpioa::*, gpiob::*, gpioc::*, Alternate, Analog, Output, PushPull}, gpio::{gpioa::*, gpiob::*, gpioc::*, Alternate, Analog, Output, PushPull},
hal::{self, blocking::spi::Transfer, digital::v2::OutputPin}, hal::{self, blocking::spi::Transfer, digital::v2::OutputPin},
pac::{ADC1, SPI1, TIM4}, pac::{ADC1, ADC2, DMA2, SPI1, TIM4, Peripherals, NVIC},
spi::{NoMiso, Spi, TransferModeNormal}, spi::{NoMiso, Spi, TransferModeNormal},
timer::pwm::PwmChannel timer::pwm::PwmChannel,
interrupt
}; };
use uom::si::{ use uom::si::{
@ -75,10 +74,14 @@ pub struct MAX1968PinSet<C: ChannelPins> {
type DacSpi = Spi<SPI1, (PB3<Alternate<5>>, NoMiso, PB5<Alternate<5>>), TransferModeNormal>; type DacSpi = Spi<SPI1, (PB3<Alternate<5>>, NoMiso, PB5<Alternate<5>>), TransferModeNormal>;
type DacSync = PB4<Output<PushPull>>; type DacSync = PB4<Output<PushPull>>;
static mut DMA_TRANSFER_COMPLETE: bool = true;
pub struct MAX1968 { pub struct MAX1968 {
pub phy: MAX1968Phy<Channel0>, pub phy: MAX1968Phy<Channel0>,
pub pins_adc: Adc<ADC1>, pub pins_adc: Adc<ADC1>,
pub dma_adc: DMA_Transfer<Stream2<DMA2>, 1, Adc<ADC2>, PeripheralToMemory, &'static mut [u16; 16]>, pub dma_adc: DMA_Transfer<Stream2<DMA2>, 1, Adc<ADC2>, PeripheralToMemory, &'static mut [u16; 16]>,
prev_vtec_volt: ElectricPotential,
prev_itec_volt: ElectricPotential,
} }
pub enum PwmPinsEnum { pub enum PwmPinsEnum {
@ -155,50 +158,57 @@ impl MAX1968 {
let dma_adc : DMA_Transfer<Stream2<DMA2>, 1, Adc<ADC2>, PeripheralToMemory, &'static mut [u16; 16]>; let dma_adc : DMA_Transfer<Stream2<DMA2>, 1, Adc<ADC2>, PeripheralToMemory, &'static mut [u16; 16]>;
unsafe { unsafe {
dma_adc = DMA_Transfer::init_peripheral_to_memory(dma.2, pins_adc2, &mut ADC2_FIRST_BUFFER, None, dma_config); dma_adc = DMA_Transfer::init_peripheral_to_memory(dma.2, pins_adc2, &mut ADC2_FIRST_BUFFER, None, dma_config);
NVIC::unmask(interrupt::DMA2_STREAM2);
} }
MAX1968 { MAX1968 {
phy: phy_ch0, phy: phy_ch0,
pins_adc: pins_adc1, pins_adc: pins_adc1,
dma_adc: dma_adc, dma_adc: dma_adc,
prev_vtec_volt: ElectricPotential::new::<millivolt>(0.0),
prev_itec_volt: ElectricPotential::new::<millivolt>(0.0),
} }
} }
pub fn dma_adc_start_conversion(&mut self){ pub fn dma_adc_start_conversion(&mut self){
self.dma_adc.clear_interrupts(); if unsafe {DMA_TRANSFER_COMPLETE} {
self.dma_adc.start(|adc| { unsafe { DMA_TRANSFER_COMPLETE = false; }
adc.clear_end_of_conversion_flag(); self.dma_adc.start(|adc| {
adc.start_conversion(); adc.clear_end_of_conversion_flag();
}); adc.start_conversion();
});
}
} }
pub fn get_tec_readings(&mut self) -> (ElectricPotential, ElectricPotential) { pub fn get_tec_readings(&mut self) -> (ElectricPotential, ElectricPotential) {
self.dma_adc.clear_interrupts(); if unsafe { DMA_TRANSFER_COMPLETE } {
let buffer: &[u16; 16]; let buffer: &[u16; 16];
unsafe{ unsafe {
(buffer, _) = self.dma_adc (buffer, _) = self.dma_adc
.next_transfer(&mut ADC2_LOCAL_BUFFER) .next_transfer(&mut ADC2_LOCAL_BUFFER)
.unwrap(); .unwrap();
} }
let sample_to_millivolts = self.dma_adc.peripheral().make_sample_to_millivolts(); let sample_to_millivolts = self.dma_adc.peripheral().make_sample_to_millivolts();
let mut itec: u16 = 0; let mut itec: u16 = 0;
for data in buffer.into_iter().step_by(2){ for data in buffer.into_iter().step_by(2) {
itec += *data; itec += *data;
} }
itec = itec >> 3; itec = itec >> 3;
let mut vtec: u16 = 0; let mut vtec: u16 = 0;
for data in buffer.into_iter().skip(1).step_by(2){ for data in buffer.into_iter().skip(1).step_by(2) {
vtec += *data; vtec += *data;
} }
vtec = vtec >> 3; vtec = vtec >> 3;
unsafe { unsafe {
ADC2_LOCAL_BUFFER = *buffer; ADC2_LOCAL_BUFFER = *buffer;
}
self.prev_vtec_volt = ElectricPotential::new::<millivolt>(sample_to_millivolts(vtec) as f32);
self.prev_itec_volt = ElectricPotential::new::<millivolt>(sample_to_millivolts(itec) as f32);
} }
(self.prev_vtec_volt, self.prev_itec_volt)
(ElectricPotential::new::<millivolt>(sample_to_millivolts(vtec) as f32), ElectricPotential::new::<millivolt>(sample_to_millivolts(itec) as f32))
} }
// Return the calibrated VDDA Voltage // Return the calibrated VDDA Voltage
@ -292,3 +302,20 @@ impl MAX1968 {
} }
} }
#[interrupt]
fn DMA2_STREAM2(){
cortex_m::interrupt::free(|_| {
unsafe {
// Clear all DMA2_STREAM2 interrupt flags
Peripherals::steal().DMA2.lifcr.write(|w| w
.ctcif2().set_bit()
.cdmeif2().set_bit()
.chtif2().set_bit()
.cteif2().set_bit()
);
DMA_TRANSFER_COMPLETE = true;
}
}
)
}