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

View File

@ -1,15 +1,14 @@
use crate::thermostat::ad5680;
use fugit::KilohertzU32;
use stm32_eth::stm32::{ADC2, DMA2};
use stm32f4xx_hal::{
adc::{config::{self, AdcConfig}, Adc},
dma::{config::DmaConfig, PeripheralToMemory, Stream2, StreamsTuple, Transfer as DMA_Transfer},
gpio::{gpioa::*, gpiob::*, gpioc::*, Alternate, Analog, Output, PushPull},
hal::{self, blocking::spi::Transfer, digital::v2::OutputPin},
pac::{ADC1, SPI1, TIM4},
pac::{ADC1, ADC2, DMA2, SPI1, TIM4, Peripherals, NVIC},
spi::{NoMiso, Spi, TransferModeNormal},
timer::pwm::PwmChannel
timer::pwm::PwmChannel,
interrupt
};
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 DacSync = PB4<Output<PushPull>>;
static mut DMA_TRANSFER_COMPLETE: bool = true;
pub struct MAX1968 {
pub phy: MAX1968Phy<Channel0>,
pub pins_adc: Adc<ADC1>,
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 {
@ -155,50 +158,57 @@ impl MAX1968 {
let dma_adc : DMA_Transfer<Stream2<DMA2>, 1, Adc<ADC2>, PeripheralToMemory, &'static mut [u16; 16]>;
unsafe {
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 {
phy: phy_ch0,
pins_adc: pins_adc1,
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){
self.dma_adc.clear_interrupts();
self.dma_adc.start(|adc| {
adc.clear_end_of_conversion_flag();
adc.start_conversion();
});
if unsafe {DMA_TRANSFER_COMPLETE} {
unsafe { DMA_TRANSFER_COMPLETE = false; }
self.dma_adc.start(|adc| {
adc.clear_end_of_conversion_flag();
adc.start_conversion();
});
}
}
pub fn get_tec_readings(&mut self) -> (ElectricPotential, ElectricPotential) {
self.dma_adc.clear_interrupts();
let buffer: &[u16; 16];
unsafe{
(buffer, _) = self.dma_adc
.next_transfer(&mut ADC2_LOCAL_BUFFER)
.unwrap();
}
let sample_to_millivolts = self.dma_adc.peripheral().make_sample_to_millivolts();
let mut itec: u16 = 0;
for data in buffer.into_iter().step_by(2){
itec += *data;
}
itec = itec >> 3;
if unsafe { DMA_TRANSFER_COMPLETE } {
let buffer: &[u16; 16];
unsafe {
(buffer, _) = self.dma_adc
.next_transfer(&mut ADC2_LOCAL_BUFFER)
.unwrap();
}
let sample_to_millivolts = self.dma_adc.peripheral().make_sample_to_millivolts();
let mut itec: u16 = 0;
for data in buffer.into_iter().step_by(2) {
itec += *data;
}
itec = itec >> 3;
let mut vtec: u16 = 0;
for data in buffer.into_iter().skip(1).step_by(2){
vtec += *data;
}
vtec = vtec >> 3;
let mut vtec: u16 = 0;
for data in buffer.into_iter().skip(1).step_by(2) {
vtec += *data;
}
vtec = vtec >> 3;
unsafe {
ADC2_LOCAL_BUFFER = *buffer;
unsafe {
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);
}
(ElectricPotential::new::<millivolt>(sample_to_millivolts(vtec) as f32), ElectricPotential::new::<millivolt>(sample_to_millivolts(itec) as f32))
(self.prev_vtec_volt, self.prev_itec_volt)
}
// 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;
}
}
)
}