125
									
								
								embassy-stm32/src/adc/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								embassy-stm32/src/adc/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | ||||
| #![macro_use] | ||||
|  | ||||
| #[cfg_attr(adc_v3, path = "v3.rs")] | ||||
| mod _version; | ||||
|  | ||||
| #[allow(unused)] | ||||
| pub use _version::*; | ||||
|  | ||||
| use crate::gpio::NoPin; | ||||
| use crate::peripherals; | ||||
|  | ||||
| pub(crate) mod sealed { | ||||
|     use crate::gpio::Pin; | ||||
|  | ||||
|     pub trait Instance { | ||||
|         fn regs() -> &'static crate::pac::adc::Adc; | ||||
|         fn common_regs() -> &'static crate::pac::adccommon::AdcCommon; | ||||
|     } | ||||
|  | ||||
|     pub trait Common { | ||||
|         fn regs() -> &'static crate::pac::adccommon::AdcCommon; | ||||
|     } | ||||
|  | ||||
|     pub trait AdcPin<T: Instance> { | ||||
|         fn channel(&self) -> u8; | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub trait Instance: sealed::Instance + 'static {} | ||||
| pub trait Common: sealed::Common + 'static {} | ||||
| pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {} | ||||
|  | ||||
| crate::pac::peripherals!( | ||||
|     (adc, $inst:ident) => { | ||||
|         impl crate::adc::sealed::Instance for peripherals::$inst { | ||||
|             fn regs() -> &'static crate::pac::adc::Adc { | ||||
|                 &crate::pac::$inst | ||||
|             } | ||||
|             fn common_regs() -> &'static crate::pac::adccommon::AdcCommon { | ||||
|                 crate::pac::peripherals!{ | ||||
|                     (adccommon, $common_inst:ident) => { | ||||
|                         return &crate::pac::$common_inst | ||||
|                     }; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         impl crate::adc::Instance for peripherals::$inst {} | ||||
|     }; | ||||
| ); | ||||
|  | ||||
| crate::pac::peripherals!( | ||||
|     (adccommon, $inst:ident) => { | ||||
|         impl sealed::Common for peripherals::$inst { | ||||
|             fn regs() -> &'static crate::pac::adccommon::AdcCommon { | ||||
|                 &crate::pac::$inst | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         impl crate::adc::Common for peripherals::$inst {} | ||||
|     }; | ||||
| ); | ||||
|  | ||||
| macro_rules! impl_pin { | ||||
|     ($inst:ident, $pin:ident, $ch:expr) => { | ||||
|         impl AdcPin<peripherals::$inst> for peripherals::$pin {} | ||||
|  | ||||
|         impl sealed::AdcPin<peripherals::$inst> for peripherals::$pin { | ||||
|             fn channel(&self) -> u8 { | ||||
|                 $ch | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| crate::pac::peripheral_pins!( | ||||
|     ($inst:ident, adc, ADC, $pin:ident, IN1) => { | ||||
|         impl_pin!($inst, $pin, 1); | ||||
|     }; | ||||
|     ($inst:ident, adc, ADC, $pin:ident, IN2) => { | ||||
|         impl_pin!($inst, $pin, 2); | ||||
|     }; | ||||
|     ($inst:ident, adc, ADC, $pin:ident, IN3) => { | ||||
|         impl_pin!($inst, $pin, 3); | ||||
|     }; | ||||
|     ($inst:ident, adc, ADC, $pin:ident, IN4) => { | ||||
|         impl_pin!($inst, $pin, 4); | ||||
|     }; | ||||
|     ($inst:ident, adc, ADC, $pin:ident, IN5) => { | ||||
|         impl_pin!($inst, $pin, 5); | ||||
|     }; | ||||
|     ($inst:ident, adc, ADC, $pin:ident, IN6) => { | ||||
|         impl_pin!($inst, $pin, 6); | ||||
|     }; | ||||
|     ($inst:ident, adc, ADC, $pin:ident, IN7) => { | ||||
|         impl_pin!($inst, $pin, 7); | ||||
|     }; | ||||
|     ($inst:ident, adc, ADC, $pin:ident, IN8) => { | ||||
|         impl_pin!($inst, $pin, 8); | ||||
|     }; | ||||
|     ($inst:ident, adc, ADC, $pin:ident, IN9) => { | ||||
|         impl_pin!($inst, $pin, 9); | ||||
|     }; | ||||
|     ($inst:ident, adc, ADC, $pin:ident, IN10) => { | ||||
|         impl_pin!($inst, $pin, 10); | ||||
|     }; | ||||
|     ($inst:ident, adc, ADC, $pin:ident, IN11) => { | ||||
|         impl_pin!($inst, $pin, 11); | ||||
|     }; | ||||
|     ($inst:ident, adc, ADC, $pin:ident, IN12) => { | ||||
|         impl_pin!($inst, $pin, 12); | ||||
|     }; | ||||
|     ($inst:ident, adc, ADC, $pin:ident, IN13) => { | ||||
|         impl_pin!($inst, $pin, 13); | ||||
|     }; | ||||
|     ($inst:ident, adc, ADC, $pin:ident, IN14) => { | ||||
|         impl_pin!($inst, $pin, 14); | ||||
|     }; | ||||
|     ($inst:ident, adc, ADC, $pin:ident, IN15) => { | ||||
|         impl_pin!($inst, $pin, 15); | ||||
|     }; | ||||
|     ($inst:ident, adc, ADC, $pin:ident, IN16) => { | ||||
|         impl_pin!($inst, $pin, 16); | ||||
|     }; | ||||
| ); | ||||
							
								
								
									
										317
									
								
								embassy-stm32/src/adc/v3.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										317
									
								
								embassy-stm32/src/adc/v3.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,317 @@ | ||||
| use crate::adc::{AdcPin, Instance}; | ||||
| use core::convert::Infallible; | ||||
| use core::marker::PhantomData; | ||||
| use cortex_m::delay::Delay; | ||||
| use embassy::util::Unborrow; | ||||
| use embassy_extras::unborrow; | ||||
| use embedded_hal::blocking::delay::{DelayMs, DelayUs}; | ||||
|  | ||||
| pub const VDDA_CALIB_MV: u32 = 3000; | ||||
|  | ||||
| pub enum Resolution { | ||||
|     TwelveBit, | ||||
|     TenBit, | ||||
|     EightBit, | ||||
|     SixBit, | ||||
| } | ||||
|  | ||||
| impl Default for Resolution { | ||||
|     fn default() -> Self { | ||||
|         Self::TwelveBit | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Resolution { | ||||
|     fn res(&self) -> crate::pac::adc::vals::Res { | ||||
|         match self { | ||||
|             Resolution::TwelveBit => crate::pac::adc::vals::Res::TWELVEBIT, | ||||
|             Resolution::TenBit => crate::pac::adc::vals::Res::TENBIT, | ||||
|             Resolution::EightBit => crate::pac::adc::vals::Res::EIGHTBIT, | ||||
|             Resolution::SixBit => crate::pac::adc::vals::Res::SIXBIT, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn to_max_count(&self) -> u32 { | ||||
|         match self { | ||||
|             Resolution::TwelveBit => (1 << 12) - 1, | ||||
|             Resolution::TenBit => (1 << 10) - 1, | ||||
|             Resolution::EightBit => (1 << 8) - 1, | ||||
|             Resolution::SixBit => (1 << 6) - 1, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub struct Vref; | ||||
| impl<T: Instance> AdcPin<T> for Vref {} | ||||
| impl<T: Instance> super::sealed::AdcPin<T> for Vref { | ||||
|     fn channel(&self) -> u8 { | ||||
|         0 | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub struct Temperature; | ||||
| impl<T: Instance> AdcPin<T> for Temperature {} | ||||
| impl<T: Instance> super::sealed::AdcPin<T> for Temperature { | ||||
|     fn channel(&self) -> u8 { | ||||
|         17 | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub struct Vbat; | ||||
| impl<T: Instance> AdcPin<T> for Vbat {} | ||||
| impl<T: Instance> super::sealed::AdcPin<T> for Vbat { | ||||
|     fn channel(&self) -> u8 { | ||||
|         18 | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// ADC sample time | ||||
| /// | ||||
| /// The default setting is 2.5 ADC clock cycles. | ||||
| #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)] | ||||
| pub enum SampleTime { | ||||
|     /// 2.5 ADC clock cycles | ||||
|     Cycles2_5 = 0b000, | ||||
|  | ||||
|     /// 6.5 ADC clock cycles | ||||
|     Cycles6_5 = 0b001, | ||||
|  | ||||
|     /// 12.5 ADC clock cycles | ||||
|     Cycles12_5 = 0b010, | ||||
|  | ||||
|     /// 24.5 ADC clock cycles | ||||
|     Cycles24_5 = 0b011, | ||||
|  | ||||
|     /// 47.5 ADC clock cycles | ||||
|     Cycles47_5 = 0b100, | ||||
|  | ||||
|     /// 92.5 ADC clock cycles | ||||
|     Cycles92_5 = 0b101, | ||||
|  | ||||
|     /// 247.5 ADC clock cycles | ||||
|     Cycles247_5 = 0b110, | ||||
|  | ||||
|     /// 640.5 ADC clock cycles | ||||
|     Cycles640_5 = 0b111, | ||||
| } | ||||
|  | ||||
| impl SampleTime { | ||||
|     fn sample_time(&self) -> crate::pac::adc::vals::SampleTime { | ||||
|         match self { | ||||
|             SampleTime::Cycles2_5 => crate::pac::adc::vals::SampleTime::CYCLES2_5, | ||||
|             SampleTime::Cycles6_5 => crate::pac::adc::vals::SampleTime::CYCLES6_5, | ||||
|             SampleTime::Cycles12_5 => crate::pac::adc::vals::SampleTime::CYCLES12_5, | ||||
|             SampleTime::Cycles24_5 => crate::pac::adc::vals::SampleTime::CYCLES24_5, | ||||
|             SampleTime::Cycles47_5 => crate::pac::adc::vals::SampleTime::CYCLES47_5, | ||||
|             SampleTime::Cycles92_5 => crate::pac::adc::vals::SampleTime::CYCLES92_5, | ||||
|             SampleTime::Cycles247_5 => crate::pac::adc::vals::SampleTime::CYCLES247_5, | ||||
|             SampleTime::Cycles640_5 => crate::pac::adc::vals::SampleTime::CYCLES640_5, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Default for SampleTime { | ||||
|     fn default() -> Self { | ||||
|         Self::Cycles2_5 | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub struct Adc<'d, T: Instance> { | ||||
|     sample_time: SampleTime, | ||||
|     calibrated_vdda: u32, | ||||
|     resolution: Resolution, | ||||
|     phantom: PhantomData<&'d mut T>, | ||||
| } | ||||
|  | ||||
| impl<'d, T: Instance> Adc<'d, T> { | ||||
|     pub fn new(_peri: impl Unborrow<Target = T> + 'd, mut delay: Delay) -> (Self, Delay) { | ||||
|         unborrow!(_peri); | ||||
|         unsafe { | ||||
|             T::regs().cr().modify(|reg| { | ||||
|                 reg.set_deeppwd(false); | ||||
|                 reg.set_advregen(true); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         delay.delay_us(20); | ||||
|  | ||||
|         unsafe { | ||||
|             while T::regs().cr().read().adcal() { | ||||
|                 // spin | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         delay.delay_us(1); | ||||
|  | ||||
|         ( | ||||
|             Self { | ||||
|                 sample_time: Default::default(), | ||||
|                 resolution: Resolution::default(), | ||||
|                 calibrated_vdda: VDDA_CALIB_MV, | ||||
|                 phantom: PhantomData, | ||||
|             }, | ||||
|             delay, | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     pub fn enable_vref(&self, mut delay: Delay) -> (Vref, Delay) { | ||||
|         unsafe { | ||||
|             T::common_regs().ccr().modify(|reg| { | ||||
|                 reg.set_vrefen(true); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us | ||||
|         // to stabilize the internal voltage reference, we wait a little more. | ||||
|         // TODO: delay 15us | ||||
|         //cortex_m::asm::delay(20_000_000); | ||||
|         delay.delay_us(15); | ||||
|  | ||||
|         (Vref {}, delay) | ||||
|     } | ||||
|  | ||||
|     pub fn enable_temperature(&self) -> Temperature { | ||||
|         unsafe { | ||||
|             T::common_regs().ccr().modify(|reg| { | ||||
|                 reg.set_ch17sel(true); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         Temperature {} | ||||
|     } | ||||
|  | ||||
|     pub fn enable_vbat(&self) -> Vbat { | ||||
|         unsafe { | ||||
|             T::common_regs().ccr().modify(|reg| { | ||||
|                 reg.set_ch18sel(true); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         Vbat {} | ||||
|     } | ||||
|  | ||||
|     /// Calculates the system VDDA by sampling the internal VREF channel and comparing | ||||
|     /// the result with the value stored at the factory. If the chip's VDDA is not stable, run | ||||
|     /// this before each ADC conversion. | ||||
|     fn calibrate(&mut self, vref: &mut Vref) { | ||||
|         let vref_cal = unsafe { crate::pac::VREFINTCAL.data().read().value() }; | ||||
|         let old_sample_time = self.sample_time; | ||||
|  | ||||
|         // "Table 24. Embedded internal voltage reference" states that the sample time needs to be | ||||
|         // at a minimum 4 us. With 640.5 ADC cycles we have a minimum of 8 us at 80 MHz, leaving | ||||
|         // some headroom. | ||||
|         self.sample_time = SampleTime::Cycles640_5; | ||||
|  | ||||
|         // This can't actually fail, it's just in a result to satisfy hal trait | ||||
|         let vref_samp = self.read(vref); | ||||
|  | ||||
|         self.sample_time = old_sample_time; | ||||
|  | ||||
|         self.calibrated_vdda = (VDDA_CALIB_MV * u32::from(vref_cal)) / u32::from(vref_samp); | ||||
|     } | ||||
|  | ||||
|     pub fn set_sample_time(&mut self, sample_time: SampleTime) { | ||||
|         self.sample_time = sample_time; | ||||
|     } | ||||
|  | ||||
|     pub fn set_resolution(&mut self, resolution: Resolution) { | ||||
|         self.resolution = resolution; | ||||
|     } | ||||
|  | ||||
|     /// Convert a measurement to millivolts | ||||
|     pub fn to_millivolts(&self, sample: u16) -> u16 { | ||||
|         ((u32::from(sample) * self.calibrated_vdda) / self.resolution.to_max_count()) as u16 | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|     /// Convert a raw sample from the `Temperature` to deg C | ||||
|     pub fn to_degrees_centigrade(sample: u16) -> f32 { | ||||
|         (130.0 - 30.0) / (VtempCal130::get().read() as f32 - VtempCal30::get().read() as f32) | ||||
|             * (sample as f32 - VtempCal30::get().read() as f32) | ||||
|             + 30.0 | ||||
|     } | ||||
|      */ | ||||
|  | ||||
|     pub fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 { | ||||
|         let v = pin.channel(); | ||||
|  | ||||
|         unsafe { | ||||
|             // Make sure bits are off | ||||
|             while T::regs().cr().read().addis() { | ||||
|                 // spin | ||||
|             } | ||||
|  | ||||
|             // Enable ADC | ||||
|             T::regs().isr().modify(|reg| { | ||||
|                 reg.set_adrdy(true); | ||||
|             }); | ||||
|             T::regs().cr().modify(|reg| { | ||||
|                 reg.set_aden(true); | ||||
|             }); | ||||
|  | ||||
|             while !T::regs().isr().read().adrdy() { | ||||
|                 // spin | ||||
|             } | ||||
|  | ||||
|             // Configure ADC | ||||
|             T::regs() | ||||
|                 .cfgr() | ||||
|                 .modify(|reg| reg.set_res(self.resolution.res())); | ||||
|  | ||||
|             // Configure channel | ||||
|             Self::set_channel_sample_time(pin.channel(), self.sample_time); | ||||
|  | ||||
|             // Select channel | ||||
|             T::regs().sqr1().write(|reg| reg.set_sq(0, pin.channel())); | ||||
|  | ||||
|             // Start conversion | ||||
|             T::regs().isr().modify(|reg| { | ||||
|                 reg.set_eos(true); | ||||
|                 reg.set_eoc(true); | ||||
|             }); | ||||
|             T::regs().cr().modify(|reg| { | ||||
|                 reg.set_adstart(true); | ||||
|             }); | ||||
|  | ||||
|             while !T::regs().isr().read().eos() { | ||||
|                 // spin | ||||
|             } | ||||
|  | ||||
|             // Read ADC value first time and discard it, as per errata sheet. | ||||
|             // The errata states that if we do conversions slower than 1 kHz, the | ||||
|             // first read ADC value can be corrupted, so we discard it and measure again. | ||||
|  | ||||
|             let _ = T::regs().dr().read(); | ||||
|  | ||||
|             T::regs().isr().modify(|reg| { | ||||
|                 reg.set_eos(true); | ||||
|                 reg.set_eoc(true); | ||||
|             }); | ||||
|             T::regs().cr().modify(|reg| { | ||||
|                 reg.set_adstart(true); | ||||
|             }); | ||||
|  | ||||
|             while !T::regs().isr().read().eos() { | ||||
|                 // spin | ||||
|             } | ||||
|  | ||||
|             let val = T::regs().dr().read().0 as u16; | ||||
|  | ||||
|             T::regs().cr().modify(|reg| reg.set_addis(true)); | ||||
|  | ||||
|             val | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { | ||||
|         if ch >= 0 && ch <= 9 { | ||||
|             T::regs() | ||||
|                 .smpr1() | ||||
|                 .modify(|reg| reg.set_smp(ch as _, sample_time.sample_time())); | ||||
|         } else { | ||||
|             T::regs() | ||||
|                 .smpr2() | ||||
|                 .modify(|reg| reg.set_smp((ch - 10) as _, sample_time.sample_time())); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -21,6 +21,8 @@ pub mod gpio; | ||||
| pub mod rcc; | ||||
|  | ||||
| // Sometimes-present hardware | ||||
| #[cfg(adc)] | ||||
| pub mod adc; | ||||
| #[cfg(timer)] | ||||
| pub mod clock; | ||||
| #[cfg(dac)] | ||||
|   | ||||
							
								
								
									
										100
									
								
								examples/stm32l4/src/bin/adc.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								examples/stm32l4/src/bin/adc.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| #![no_std] | ||||
| #![no_main] | ||||
| #![feature(trait_alias)] | ||||
| #![feature(min_type_alias_impl_trait)] | ||||
| #![feature(impl_trait_in_bindings)] | ||||
| #![feature(type_alias_impl_trait)] | ||||
|  | ||||
| #[path = "../example_common.rs"] | ||||
| mod example_common; | ||||
|  | ||||
| use embassy_stm32::gpio::{Input, Level, NoPin, Output, Pull}; | ||||
| use embedded_hal::digital::v2::{InputPin, OutputPin}; | ||||
| use example_common::*; | ||||
|  | ||||
| use cortex_m_rt::entry; | ||||
| //use stm32f4::stm32f429 as pac; | ||||
| use cortex_m::delay::Delay; | ||||
| use embassy_stm32::adc::{Adc, Resolution}; | ||||
| use embassy_stm32::dac::{Channel, Dac, Value}; | ||||
| use embassy_stm32::spi::{ByteOrder, Config, Spi, MODE_0}; | ||||
| use embassy_stm32::time::Hertz; | ||||
| use embedded_hal::blocking::spi::Transfer; | ||||
| use micromath::F32Ext; | ||||
| use stm32l4::stm32l4x5 as pac; | ||||
| use stm32l4xx_hal::gpio::PA4; | ||||
| use stm32l4xx_hal::rcc::PllSource; | ||||
| use stm32l4xx_hal::{prelude::*, rcc}; | ||||
|  | ||||
| #[entry] | ||||
| fn main() -> ! { | ||||
|     info!("Hello World, dude!"); | ||||
|     //let pp = pac::Peripherals::take().unwrap(); | ||||
|     let cp = cortex_m::Peripherals::take().unwrap(); | ||||
|     let pp = stm32l4xx_hal::stm32::Peripherals::take().unwrap(); | ||||
|     let mut flash = pp.FLASH.constrain(); | ||||
|     let mut rcc = pp.RCC.constrain(); | ||||
|     let mut pwr = pp.PWR.constrain(&mut rcc.apb1r1); | ||||
|  | ||||
|     let mut delay = Delay::new(cp.SYST, 80_000_000); | ||||
|  | ||||
|     // TRY the other clock configuration | ||||
|     // let clocks = rcc.cfgr.freeze(&mut flash.acr); | ||||
|     let clocks = rcc | ||||
|         .cfgr | ||||
|         .sysclk(80.mhz()) | ||||
|         .pclk1(80.mhz()) | ||||
|         .pclk2(80.mhz()) | ||||
|         .pll_source(PllSource::HSI16) | ||||
|         .freeze(&mut flash.acr, &mut pwr); | ||||
|  | ||||
|     let pp = unsafe { pac::Peripherals::steal() }; | ||||
|  | ||||
|     pp.RCC.ccipr.modify(|_, w| { | ||||
|         unsafe { | ||||
|             w.adcsel().bits(0b11); | ||||
|         } | ||||
|         w | ||||
|     }); | ||||
|  | ||||
|     pp.DBGMCU.cr.modify(|_, w| { | ||||
|         w.dbg_sleep().set_bit(); | ||||
|         w.dbg_standby().set_bit(); | ||||
|         w.dbg_stop().set_bit() | ||||
|     }); | ||||
|  | ||||
|     pp.RCC.ahb2enr.modify(|_, w| { | ||||
|         w.adcen().set_bit(); | ||||
|         w.gpioaen().set_bit(); | ||||
|         w.gpioben().set_bit(); | ||||
|         w.gpiocen().set_bit(); | ||||
|         w.gpioden().set_bit(); | ||||
|         w.gpioeen().set_bit(); | ||||
|         w.gpiofen().set_bit(); | ||||
|         w | ||||
|     }); | ||||
|  | ||||
|     let p = embassy_stm32::init(Default::default()); | ||||
|  | ||||
|     let (mut adc, mut delay) = Adc::new(p.ADC1, delay); | ||||
|     //adc.enable_vref(); | ||||
|     adc.set_resolution(Resolution::EightBit); | ||||
|     let mut channel = p.PC0; | ||||
|  | ||||
|     loop { | ||||
|         let v = adc.read(&mut channel); | ||||
|         info!("--> {}", v); | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn to_sine_wave(v: u8) -> u8 { | ||||
|     if v >= 128 { | ||||
|         // top half | ||||
|         let r = 3.14 * ((v - 128) as f32 / 128.0); | ||||
|         (r.sin() * 128.0 + 127.0) as u8 | ||||
|     } else { | ||||
|         // bottom half | ||||
|         let r = 3.14 + 3.14 * (v as f32 / 128.0); | ||||
|         (r.sin() * 128.0 + 127.0) as u8 | ||||
|     } | ||||
| } | ||||
| @@ -15,7 +15,6 @@ use example_common::*; | ||||
| use cortex_m_rt::entry; | ||||
| use stm32l4::stm32l4x5 as pac; | ||||
|  | ||||
|  | ||||
| #[entry] | ||||
| fn main() -> ! { | ||||
|     info!("Hello World!"); | ||||
|   | ||||
| @@ -80,5 +80,4 @@ fn main() -> ! { | ||||
|     executor.run(|spawner| { | ||||
|         unwrap!(spawner.spawn(main_task())); | ||||
|     }) | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -8,20 +8,20 @@ | ||||
| #[path = "../example_common.rs"] | ||||
| mod example_common; | ||||
|  | ||||
| use embassy_stm32::gpio::{Level, Output, Input, Pull, NoPin}; | ||||
| use embedded_hal::digital::v2::{OutputPin, InputPin}; | ||||
| use embassy_stm32::gpio::{Input, Level, NoPin, Output, Pull}; | ||||
| use embedded_hal::digital::v2::{InputPin, OutputPin}; | ||||
| use example_common::*; | ||||
|  | ||||
| use cortex_m_rt::entry; | ||||
| //use stm32f4::stm32f429 as pac; | ||||
| use stm32l4::stm32l4x5 as pac; | ||||
| use embassy_stm32::spi::{Spi, MODE_0, ByteOrder, Config}; | ||||
| use embassy_stm32::dac::{Channel, Dac, Value}; | ||||
| use embassy_stm32::spi::{ByteOrder, Config, Spi, MODE_0}; | ||||
| use embassy_stm32::time::Hertz; | ||||
| use embedded_hal::blocking::spi::Transfer; | ||||
| use stm32l4xx_hal::{rcc, prelude::*}; | ||||
| use stm32l4xx_hal::rcc::PllSource; | ||||
| use embassy_stm32::dac::{Dac, Value, Channel}; | ||||
| use stm32l4::stm32l4x5 as pac; | ||||
| use stm32l4xx_hal::gpio::PA4; | ||||
| use stm32l4xx_hal::rcc::PllSource; | ||||
| use stm32l4xx_hal::{prelude::*, rcc}; | ||||
|  | ||||
| #[entry] | ||||
| fn main() -> ! { | ||||
| @@ -72,7 +72,7 @@ fn main() -> ! { | ||||
|     loop { | ||||
|         for v in 0..=255 { | ||||
|             dac.set(Channel::Ch1, Value::Bit8(to_sine_wave(v))); | ||||
|             dac.trigger( Channel::Ch1 ); | ||||
|             dac.trigger(Channel::Ch1); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -82,11 +82,11 @@ use micromath::F32Ext; | ||||
| fn to_sine_wave(v: u8) -> u8 { | ||||
|     if v >= 128 { | ||||
|         // top half | ||||
|         let r = 3.14 * ( (v-128) as f32/ 128.0) ; | ||||
|         let r = 3.14 * ((v - 128) as f32 / 128.0); | ||||
|         (r.sin() * 128.0 + 127.0) as u8 | ||||
|     } else { | ||||
|         // bottom half | ||||
|         let r = 3.14 + 3.14 * (v as f32/ 128.0); | ||||
|         let r = 3.14 + 3.14 * (v as f32 / 128.0); | ||||
|         (r.sin() * 128.0 + 127.0) as u8 | ||||
|     } | ||||
| } | ||||
|   | ||||
 Submodule stm32-data updated: 8f32d8e4f2...67b2029a7f
									
								
							
		Reference in New Issue
	
	Block a user