#![deny(missing_docs)]
const VDDA_CALIB: u32 = 3300;
use crate::{gpio::*, signature::VrefCal, stm32};
use core::fmt;
use embedded_hal::adc::{Channel, OneShot};
pub struct Vref;
pub struct Vbat;
pub struct Temperature;
macro_rules! adc_pins {
($($pin:ty => ($adc:ident, $chan:expr)),+ $(,)*) => {
$(
impl Channel<stm32::$adc> for $pin {
type ID = u8;
fn channel() -> u8 { $chan }
}
)+
};
}
pub mod config {
#[derive(Debug, PartialEq, PartialOrd, Copy, Clone)]
pub enum Sequence {
One,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
Ten,
Eleven,
Twelve,
Thirteen,
Fourteen,
Fifteen,
Sixteen,
}
impl From<Sequence> for u8 {
fn from(s: Sequence) -> u8 {
match s {
Sequence::One => 0,
Sequence::Two => 1,
Sequence::Three => 2,
Sequence::Four => 3,
Sequence::Five => 4,
Sequence::Six => 5,
Sequence::Seven => 6,
Sequence::Eight => 7,
Sequence::Nine => 8,
Sequence::Ten => 9,
Sequence::Eleven => 10,
Sequence::Twelve => 11,
Sequence::Thirteen => 12,
Sequence::Fourteen => 13,
Sequence::Fifteen => 14,
Sequence::Sixteen => 15,
}
}
}
impl From<u8> for Sequence {
fn from(bits: u8) -> Self {
match bits {
0 => Sequence::One,
1 => Sequence::Two,
2 => Sequence::Three,
3 => Sequence::Four,
4 => Sequence::Five,
5 => Sequence::Six,
6 => Sequence::Seven,
7 => Sequence::Eight,
8 => Sequence::Nine,
9 => Sequence::Ten,
10 => Sequence::Eleven,
11 => Sequence::Twelve,
12 => Sequence::Thirteen,
13 => Sequence::Fourteen,
14 => Sequence::Fifteen,
15 => Sequence::Sixteen,
_ => unimplemented!(),
}
}
}
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum SampleTime {
Cycles_3,
Cycles_15,
Cycles_28,
Cycles_56,
Cycles_84,
Cycles_112,
Cycles_144,
Cycles_480,
}
impl From<u8> for SampleTime {
fn from(f: u8) -> SampleTime {
match f {
0 => SampleTime::Cycles_3,
1 => SampleTime::Cycles_15,
2 => SampleTime::Cycles_28,
3 => SampleTime::Cycles_56,
4 => SampleTime::Cycles_84,
5 => SampleTime::Cycles_112,
6 => SampleTime::Cycles_144,
7 => SampleTime::Cycles_480,
_ => unimplemented!(),
}
}
}
impl From<SampleTime> for u8 {
fn from(l: SampleTime) -> u8 {
match l {
SampleTime::Cycles_3 => 0,
SampleTime::Cycles_15 => 1,
SampleTime::Cycles_28 => 2,
SampleTime::Cycles_56 => 3,
SampleTime::Cycles_84 => 4,
SampleTime::Cycles_112 => 5,
SampleTime::Cycles_144 => 6,
SampleTime::Cycles_480 => 7,
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum Clock {
Pclk2_div_2,
Pclk2_div_4,
Pclk2_div_6,
Pclk2_div_8,
}
impl From<Clock> for u8 {
fn from(c: Clock) -> u8 {
match c {
Clock::Pclk2_div_2 => 0,
Clock::Pclk2_div_4 => 1,
Clock::Pclk2_div_6 => 2,
Clock::Pclk2_div_8 => 3,
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum Resolution {
Twelve,
Ten,
Eight,
Six,
}
impl From<Resolution> for u8 {
fn from(r: Resolution) -> u8 {
match r {
Resolution::Twelve => 0,
Resolution::Ten => 1,
Resolution::Eight => 2,
Resolution::Six => 3,
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum ExternalTrigger {
Tim_1_cc_1,
Tim_1_cc_2,
Tim_1_cc_3,
Tim_2_cc_2,
Tim_2_cc_3,
Tim_2_cc_4,
Tim_2_trgo,
Tim_3_cc_1,
Tim_3_trgo,
Tim_4_cc_4,
Tim_5_cc_1,
Tim_5_cc_2,
Tim_5_cc_3,
Exti_11,
}
impl From<ExternalTrigger> for u8 {
fn from(et: ExternalTrigger) -> u8 {
match et {
ExternalTrigger::Tim_1_cc_1 => 0b0000,
ExternalTrigger::Tim_1_cc_2 => 0b0001,
ExternalTrigger::Tim_1_cc_3 => 0b0010,
ExternalTrigger::Tim_2_cc_2 => 0b0011,
ExternalTrigger::Tim_2_cc_3 => 0b0100,
ExternalTrigger::Tim_2_cc_4 => 0b0101,
ExternalTrigger::Tim_2_trgo => 0b0110,
ExternalTrigger::Tim_3_cc_1 => 0b0111,
ExternalTrigger::Tim_3_trgo => 0b1000,
ExternalTrigger::Tim_4_cc_4 => 0b1001,
ExternalTrigger::Tim_5_cc_1 => 0b1010,
ExternalTrigger::Tim_5_cc_2 => 0b1011,
ExternalTrigger::Tim_5_cc_3 => 0b1100,
ExternalTrigger::Exti_11 => 0b1111,
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum TriggerMode {
Disabled,
RisingEdge,
FallingEdge,
BothEdges,
}
impl From<TriggerMode> for u8 {
fn from(tm: TriggerMode) -> u8 {
match tm {
TriggerMode::Disabled => 0,
TriggerMode::RisingEdge => 1,
TriggerMode::FallingEdge => 2,
TriggerMode::BothEdges => 3,
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum Align {
Right,
Left,
}
impl From<Align> for bool {
fn from(a: Align) -> bool {
match a {
Align::Right => false,
Align::Left => true,
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum Scan {
Disabled,
Enabled,
}
impl From<Scan> for bool {
fn from(s: Scan) -> bool {
match s {
Scan::Disabled => false,
Scan::Enabled => true,
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum Continuous {
Single,
Continuous,
}
impl From<Continuous> for bool {
fn from(c: Continuous) -> bool {
match c {
Continuous::Single => false,
Continuous::Continuous => true,
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum Dma {
Disabled,
Single,
Continuous,
}
#[derive(Debug, Clone, Copy)]
pub enum Eoc {
Disabled,
Conversion,
Sequence,
}
#[derive(Debug, Clone, Copy)]
pub struct AdcConfig {
pub(crate) clock: Clock,
pub(crate) resolution: Resolution,
pub(crate) align: Align,
pub(crate) scan: Scan,
pub(crate) external_trigger: (TriggerMode, ExternalTrigger),
pub(crate) continuous: Continuous,
pub(crate) dma: Dma,
pub(crate) end_of_conversion_interrupt: Eoc,
pub(crate) default_sample_time: SampleTime,
}
impl AdcConfig {
pub fn clock(mut self, clock: Clock) -> Self {
self.clock = clock;
self
}
pub fn resolution(mut self, resolution: Resolution) -> Self {
self.resolution = resolution;
self
}
pub fn align(mut self, align: Align) -> Self {
self.align = align;
self
}
pub fn scan(mut self, scan: Scan) -> Self {
self.scan = scan;
self
}
pub fn external_trigger(
mut self,
trigger_mode: TriggerMode,
trigger: ExternalTrigger,
) -> Self {
self.external_trigger = (trigger_mode, trigger);
self
}
pub fn continuous(mut self, continuous: Continuous) -> Self {
self.continuous = continuous;
self
}
pub fn dma(mut self, dma: Dma) -> Self {
self.dma = dma;
self
}
pub fn end_of_conversion_interrupt(mut self, end_of_conversion_interrupt: Eoc) -> Self {
self.end_of_conversion_interrupt = end_of_conversion_interrupt;
self
}
pub fn default_sample_time(mut self, default_sample_time: SampleTime) -> Self {
self.default_sample_time = default_sample_time;
self
}
}
impl Default for AdcConfig {
fn default() -> Self {
Self {
clock: Clock::Pclk2_div_2,
resolution: Resolution::Twelve,
align: Align::Right,
scan: Scan::Disabled,
external_trigger: (TriggerMode::Disabled, ExternalTrigger::Tim_1_cc_1),
continuous: Continuous::Single,
dma: Dma::Disabled,
end_of_conversion_interrupt: Eoc::Disabled,
default_sample_time: SampleTime::Cycles_480,
}
}
}
}
#[derive(Clone, Copy)]
pub struct Adc<ADC> {
config: config::AdcConfig,
adc_reg: ADC,
calibrated_vdda: u32,
max_sample: u32,
}
impl<ADC> fmt::Debug for Adc<ADC> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Adc: {{ calibrated_vdda: {:?}, max_sample: {:?}, config: {:?}, ... }}",
self.calibrated_vdda, self.max_sample, self.config
)
}
}
macro_rules! adc {
($($adc_type:ident => ($constructor_fn_name:ident, $common_type:ident, $rcc_enr_reg:ident, $rcc_enr_field: ident, $rcc_rst_reg: ident, $rcc_rst_field: ident)),+ $(,)*) => {
$(
impl Adc<stm32::$adc_type> {
pub fn $constructor_fn_name(adc: stm32::$adc_type, reset: bool, config: config::AdcConfig) -> Adc<stm32::$adc_type> {
unsafe {
let rcc = &(*stm32::RCC::ptr());
rcc.$rcc_enr_reg.modify(|_, w| w.$rcc_enr_field().set_bit());
if reset {
rcc.$rcc_rst_reg.modify(|_, w| w.$rcc_rst_field().set_bit());
rcc.$rcc_rst_reg.modify(|_, w| w.$rcc_rst_field().clear_bit());
}
}
let mut s = Self {
config,
adc_reg: adc,
calibrated_vdda: VDDA_CALIB,
max_sample: 0,
};
s.disable();
s.apply_config(config);
s.enable();
s.calibrate();
s
}
pub fn apply_config(&mut self, config: config::AdcConfig) {
self.set_clock(config.clock);
self.set_resolution(config.resolution);
self.set_align(config.align);
self.set_scan(config.scan);
self.set_external_trigger(config.external_trigger);
self.set_continuous(config.continuous);
self.set_dma(config.dma);
self.set_end_of_conversion_interrupt(config.end_of_conversion_interrupt);
self.set_default_sample_time(config.default_sample_time);
}
pub fn calibrate(&mut self) {
self.enable();
let vref_en = self.temperature_and_vref_enabled();
if !vref_en {
self.enable_temperature_and_vref();
}
let vref_cal = VrefCal::get().read();
let vref_samp = self.read(&mut Vref).unwrap();
self.calibrated_vdda = (VDDA_CALIB * u32::from(vref_cal)) / u32::from(vref_samp);
if !vref_en {
self.disable_temperature_and_vref();
}
}
pub fn enable_vbat(&self) {
unsafe {
let common = &(*stm32::$common_type::ptr());
common.ccr.modify(|_, w| w.vbate().set_bit());
}
}
pub fn disable_vbat(&self) {
unsafe {
let common = &(*stm32::$common_type::ptr());
common.ccr.modify(|_, w| w.vbate().clear_bit());
}
}
pub fn enable_temperature_and_vref(&mut self) {
self.disable_vbat();
unsafe {
let common = &(*stm32::$common_type::ptr());
common.ccr.modify(|_, w| w.tsvrefe().set_bit());
}
}
pub fn disable_temperature_and_vref(&mut self) {
unsafe {
let common = &(*stm32::$common_type::ptr());
common.ccr.modify(|_, w| w.tsvrefe().clear_bit());
}
}
pub fn temperature_and_vref_enabled(&mut self) -> bool {
unsafe {
let common = &(*stm32::$common_type::ptr());
common.ccr.read().tsvrefe().bit_is_set()
}
}
pub fn is_enabled(&self) -> bool {
self.adc_reg.cr2.read().adon().bit_is_set()
}
pub fn enable(&mut self) {
self.adc_reg.cr2.modify(|_, w| w.adon().set_bit());
}
pub fn disable(&mut self) {
self.adc_reg.cr2.modify(|_, w| w.adon().clear_bit());
}
pub fn start_conversion(&mut self) {
self.enable();
self.clear_end_of_conversion_flag();
self.adc_reg.cr2.modify(|_, w| w.swstart().set_bit());
while !self.adc_reg.sr.read().strt().bit_is_set() {}
}
pub fn set_clock(&mut self, clock: config::Clock) {
self.config.clock = clock;
unsafe {
let common = &(*stm32::$common_type::ptr());
common.ccr.modify(|_, w| w.adcpre().bits(clock.into()));
}
}
pub fn set_resolution(&mut self, resolution: config::Resolution) {
self.max_sample = match resolution {
config::Resolution::Twelve => (1 << 12) - 1,
config::Resolution::Ten => (1 << 10) - 1,
config::Resolution::Eight => (1 << 8) - 1,
config::Resolution::Six => (1 << 6) -1,
};
self.config.resolution = resolution;
self.adc_reg.cr1.modify(|_, w| w.res().bits(resolution.into()));
}
pub fn set_align(&mut self, align: config::Align) {
self.config.align = align;
self.adc_reg.cr2.modify(|_, w| w.align().bit(align.into()));
}
pub fn set_scan(&mut self, scan: config::Scan) {
self.config.scan = scan;
self.adc_reg.cr1.modify(|_, w| w.scan().bit(scan.into()));
}
pub fn set_external_trigger(&mut self, (edge, extsel): (config::TriggerMode, config::ExternalTrigger)) {
self.config.external_trigger = (edge, extsel);
self.adc_reg.cr2.modify(|_, w| unsafe { w
.extsel().bits(extsel.into())
.exten().bits(edge.into())
});
}
pub fn set_continuous(&mut self, continuous: config::Continuous) {
self.config.continuous = continuous;
self.adc_reg.cr2.modify(|_, w| w.cont().bit(continuous.into()));
}
pub fn set_dma(&mut self, dma: config::Dma) {
self.config.dma = dma;
let (dds, en) = match dma {
config::Dma::Disabled => (false, false),
config::Dma::Single => (false, true),
config::Dma::Continuous => (true, true),
};
self.adc_reg.cr2.modify(|_, w| w
.dds().bit(dds)
.dma().bit(en)
);
}
pub fn set_end_of_conversion_interrupt(&mut self, eoc: config::Eoc) {
self.config.end_of_conversion_interrupt = eoc;
let (en, eocs) = match eoc {
config::Eoc::Disabled => (false, false),
config::Eoc::Conversion => (true, true),
config::Eoc::Sequence => (true, false),
};
self.adc_reg.cr1.modify(|_, w| w.eocie().bit(en));
self.adc_reg.cr2.modify(|_, w| w.eocs().bit(eocs));
}
pub fn clear_end_of_conversion_flag(&mut self) {
self.adc_reg.sr.modify(|_, w| w.eoc().clear_bit());
}
pub fn set_default_sample_time(&mut self, sample_time: config::SampleTime) {
self.config.default_sample_time = sample_time;
}
pub fn sequence_length(&mut self) -> u8 {
self.adc_reg.sqr1.read().l().bits() + 1
}
pub fn reset_sequence(&mut self) {
self.adc_reg.sqr1.modify(|_, w| w.l().bits(config::Sequence::One.into()));
}
pub fn data_register_address(&mut self) -> u32 {
&self.adc_reg.dr as *const _ as u32
}
pub fn configure_channel<CHANNEL>(&mut self, _channel: &CHANNEL, sequence: config::Sequence, sample_time: config::SampleTime)
where
CHANNEL: Channel<stm32::$adc_type, ID=u8>
{
self.adc_reg.sqr1.modify(|r, w| {
let prev: config::Sequence = r.l().bits().into();
if prev < sequence {
w.l().bits(sequence.into())
} else {
w
}
});
let channel = CHANNEL::channel();
match sequence {
config::Sequence::One => self.adc_reg.sqr3.modify(|_, w| unsafe {w.sq1().bits(channel) }),
config::Sequence::Two => self.adc_reg.sqr3.modify(|_, w| unsafe {w.sq2().bits(channel) }),
config::Sequence::Three => self.adc_reg.sqr3.modify(|_, w| unsafe {w.sq3().bits(channel) }),
config::Sequence::Four => self.adc_reg.sqr3.modify(|_, w| unsafe {w.sq4().bits(channel) }),
config::Sequence::Five => self.adc_reg.sqr3.modify(|_, w| unsafe {w.sq5().bits(channel) }),
config::Sequence::Six => self.adc_reg.sqr3.modify(|_, w| unsafe {w.sq6().bits(channel) }),
config::Sequence::Seven => self.adc_reg.sqr2.modify(|_, w| unsafe {w.sq7().bits(channel) }),
config::Sequence::Eight => self.adc_reg.sqr2.modify(|_, w| unsafe {w.sq8().bits(channel) }),
config::Sequence::Nine => self.adc_reg.sqr2.modify(|_, w| unsafe {w.sq9().bits(channel) }),
config::Sequence::Ten => self.adc_reg.sqr2.modify(|_, w| unsafe {w.sq10().bits(channel) }),
config::Sequence::Eleven => self.adc_reg.sqr2.modify(|_, w| unsafe {w.sq11().bits(channel) }),
config::Sequence::Twelve => self.adc_reg.sqr2.modify(|_, w| unsafe {w.sq12().bits(channel) }),
config::Sequence::Thirteen => self.adc_reg.sqr1.modify(|_, w| unsafe {w.sq13().bits(channel) }),
config::Sequence::Fourteen => self.adc_reg.sqr1.modify(|_, w| unsafe {w.sq14().bits(channel) }),
config::Sequence::Fifteen => self.adc_reg.sqr1.modify(|_, w| unsafe {w.sq15().bits(channel) }),
config::Sequence::Sixteen => self.adc_reg.sqr1.modify(|_, w| unsafe {w.sq16().bits(channel) }),
}
fn replace_bits(mut v: u32, offset: u32, width: u32, value: u32) -> u32 {
let mask = !(((1 << width) -1) << (offset * width));
v &= mask;
v |= value << (offset * width);
v
}
let st = u8::from(sample_time);
let st = u32::from(st);
let ch = u32::from(channel);
match channel {
0...9 => self.adc_reg.smpr2.modify(|r, w| unsafe { w.bits(replace_bits(r.bits(), ch, 3, st)) }),
10...18 => self.adc_reg.smpr1.modify(|r, w| unsafe { w.bits(replace_bits(r.bits(), ch-10, 3, st)) }),
_ => unimplemented!(),
}
}
pub fn current_sample(&self) -> u16 {
self.adc_reg.dr.read().data().bits()
}
pub fn sample_to_millivolts(&self, sample: u16) -> u16 {
((u32::from(sample) * self.calibrated_vdda) / self.max_sample) as u16
}
pub fn wait_for_conversion_sequence(&self) {
if !self.adc_reg.sr.read().strt().bit_is_set() && !self.adc_reg.sr.read().eoc().bit_is_set() {
panic!("Waiting for end-of-conversion but no conversion started");
}
while !self.adc_reg.sr.read().eoc().bit_is_set() {}
self.adc_reg.sr.modify(|_, w| w.strt().clear_bit());
}
pub fn convert<PIN>(&mut self, pin: &PIN, sample_time: config::SampleTime) -> u16
where
PIN: Channel<stm32::$adc_type, ID=u8>
{
self.adc_reg.cr2.modify(|_, w| w
.dma().clear_bit()
.cont().clear_bit()
.exten().bits(config::TriggerMode::Disabled.into())
.eocs().clear_bit()
);
self.adc_reg.cr1.modify(|_, w| w
.scan().clear_bit()
.eocie().clear_bit()
);
self.reset_sequence();
self.configure_channel(pin, config::Sequence::One, sample_time);
self.enable();
self.clear_end_of_conversion_flag();
self.start_conversion();
self.wait_for_conversion_sequence();
let result = self.current_sample();
self.apply_config(self.config);
result
}
}
impl<PIN> OneShot<stm32::$adc_type, u16, PIN> for Adc<stm32::$adc_type>
where
PIN: Channel<stm32::$adc_type, ID=u8>,
{
type Error = ();
fn read(&mut self, pin: &mut PIN) -> nb::Result<u16, Self::Error> {
let enabled = self.is_enabled();
if !enabled {
self.enable();
}
let sample = self.convert(pin, self.config.default_sample_time);
if !enabled {
self.disable();
}
Ok(sample)
}
}
)+
};
}
#[cfg(any(
feature = "stm32f401",
feature = "stm32f405",
feature = "stm32f415",
feature = "stm32f407",
feature = "stm32f417",
feature = "stm32f410",
feature = "stm32f411",
feature = "stm32f412",
feature = "stm32f413",
feature = "stm32f423",
feature = "stm32f427",
feature = "stm32f437",
feature = "stm32f429",
feature = "stm32f439",
feature = "stm32f446",
feature = "stm32f469",
feature = "stm32f479",
))]
adc!(ADC1 => (adc1, ADC_COMMON, apb2enr, adc1en, apb2rstr, adcrst));
#[cfg(any(
feature = "stm32f405",
feature = "stm32f415",
feature = "stm32f407",
feature = "stm32f417",
feature = "stm32f427",
feature = "stm32f437",
feature = "stm32f429",
feature = "stm32f439",
feature = "stm32f446",
feature = "stm32f469",
feature = "stm32f479",
))]
adc!(ADC2 => (adc2, ADC_COMMON, apb2enr, adc2en, apb2rstr, adcrst));
#[cfg(any(
feature = "stm32f405",
feature = "stm32f415",
feature = "stm32f407",
feature = "stm32f417",
feature = "stm32f427",
feature = "stm32f437",
feature = "stm32f429",
feature = "stm32f439",
feature = "stm32f446",
feature = "stm32f469",
feature = "stm32f479",
))]
adc!(ADC3 => (adc3, ADC_COMMON, apb2enr, adc3en, apb2rstr, adcrst));
#[cfg(feature = "stm32f401")]
adc_pins!(
gpioa::PA0<Analog> => (ADC1, 0),
gpioa::PA1<Analog> => (ADC1, 1),
gpioa::PA2<Analog> => (ADC1, 2),
gpioa::PA3<Analog> => (ADC1, 3),
gpioa::PA4<Analog> => (ADC1, 4),
gpioa::PA5<Analog> => (ADC1, 5),
gpioa::PA6<Analog> => (ADC1, 6),
gpioa::PA7<Analog> => (ADC1, 7),
gpiob::PB0<Analog> => (ADC1, 8),
gpiob::PB1<Analog> => (ADC1, 9),
Temperature => (ADC1, 18),
Vbat => (ADC1, 18),
Vref => (ADC1, 17),
);
#[cfg(feature = "stm32f401")]
adc_pins!(
gpioc::PC0<Analog> => (ADC1, 10),
gpioc::PC1<Analog> => (ADC1, 11),
gpioc::PC2<Analog> => (ADC1, 12),
gpioc::PC3<Analog> => (ADC1, 13),
gpioc::PC4<Analog> => (ADC1, 14),
gpioc::PC5<Analog> => (ADC1, 15),
);
#[cfg(any(feature = "stm32f405", feature = "stm32f415"))]
adc_pins!(
gpioa::PA0<Analog> => (ADC1, 0),
gpioa::PA0<Analog> => (ADC2, 0),
gpioa::PA0<Analog> => (ADC3, 0),
gpioa::PA1<Analog> => (ADC1, 1),
gpioa::PA1<Analog> => (ADC2, 1),
gpioa::PA1<Analog> => (ADC3, 1),
gpioa::PA2<Analog> => (ADC1, 2),
gpioa::PA2<Analog> => (ADC2, 2),
gpioa::PA2<Analog> => (ADC3, 2),
gpioa::PA3<Analog> => (ADC1, 3),
gpioa::PA3<Analog> => (ADC2, 3),
gpioa::PA3<Analog> => (ADC3, 3),
gpioa::PA4<Analog> => (ADC1, 4),
gpioa::PA4<Analog> => (ADC2, 4),
gpioa::PA5<Analog> => (ADC1, 5),
gpioa::PA5<Analog> => (ADC2, 5),
gpioa::PA6<Analog> => (ADC1, 6),
gpioa::PA6<Analog> => (ADC2, 6),
gpioa::PA7<Analog> => (ADC1, 7),
gpioa::PA7<Analog> => (ADC2, 7),
gpiob::PB0<Analog> => (ADC1, 8),
gpiob::PB0<Analog> => (ADC2, 8),
gpiob::PB1<Analog> => (ADC1, 9),
gpiob::PB1<Analog> => (ADC2, 9),
gpioc::PC0<Analog> => (ADC1, 10),
gpioc::PC0<Analog> => (ADC2, 10),
gpioc::PC0<Analog> => (ADC3, 10),
gpioc::PC2<Analog> => (ADC1, 12),
gpioc::PC2<Analog> => (ADC2, 12),
gpioc::PC2<Analog> => (ADC3, 12),
gpioc::PC3<Analog> => (ADC1, 13),
gpioc::PC3<Analog> => (ADC2, 13),
gpioc::PC3<Analog> => (ADC3, 13),
Temperature => (ADC1, 18),
Temperature => (ADC2, 18),
Temperature => (ADC3, 18),
Vbat => (ADC1, 18),
Vbat => (ADC2, 18),
Vbat => (ADC3, 18),
Vref => (ADC1, 17),
Vref => (ADC2, 17),
Vref => (ADC3, 17),
);
#[cfg(any(feature = "stm32f405", feature = "stm32f415"))]
adc_pins!(
gpioc::PC1<Analog> => (ADC1, 11),
gpioc::PC1<Analog> => (ADC2, 11),
gpioc::PC1<Analog> => (ADC3, 11),
gpioc::PC4<Analog> => (ADC1, 14),
gpioc::PC4<Analog> => (ADC2, 14),
gpioc::PC5<Analog> => (ADC1, 15),
gpioc::PC5<Analog> => (ADC2, 15),
gpiof::PF10<Analog> => (ADC3, 8),
gpiof::PF3<Analog> => (ADC3, 9),
gpiof::PF4<Analog> => (ADC3, 14),
gpiof::PF5<Analog> => (ADC3, 15),
gpiof::PF6<Analog> => (ADC3, 4),
gpiof::PF7<Analog> => (ADC3, 5),
gpiof::PF8<Analog> => (ADC3, 6),
gpiof::PF9<Analog> => (ADC3, 7),
);
#[cfg(any(feature = "stm32f407", feature = "stm32f417"))]
adc_pins!(
gpioa::PA0<Analog> => (ADC1, 0),
gpioa::PA0<Analog> => (ADC2, 0),
gpioa::PA0<Analog> => (ADC3, 0),
gpioa::PA1<Analog> => (ADC1, 1),
gpioa::PA1<Analog> => (ADC2, 1),
gpioa::PA1<Analog> => (ADC3, 1),
gpioa::PA2<Analog> => (ADC1, 2),
gpioa::PA2<Analog> => (ADC2, 2),
gpioa::PA2<Analog> => (ADC3, 2),
gpioa::PA3<Analog> => (ADC1, 3),
gpioa::PA3<Analog> => (ADC2, 3),
gpioa::PA3<Analog> => (ADC3, 3),
gpioa::PA4<Analog> => (ADC1, 4),
gpioa::PA4<Analog> => (ADC2, 4),
gpioa::PA5<Analog> => (ADC1, 5),
gpioa::PA5<Analog> => (ADC2, 5),
gpioa::PA6<Analog> => (ADC1, 6),
gpioa::PA6<Analog> => (ADC2, 6),
gpioa::PA7<Analog> => (ADC1, 7),
gpioa::PA7<Analog> => (ADC2, 7),
gpiob::PB0<Analog> => (ADC1, 8),
gpiob::PB0<Analog> => (ADC2, 8),
gpiob::PB1<Analog> => (ADC1, 9),
gpiob::PB1<Analog> => (ADC2, 9),
gpioc::PC0<Analog> => (ADC1, 10),
gpioc::PC0<Analog> => (ADC2, 10),
gpioc::PC0<Analog> => (ADC3, 10),
gpioc::PC1<Analog> => (ADC1, 11),
gpioc::PC1<Analog> => (ADC2, 11),
gpioc::PC1<Analog> => (ADC3, 11),
gpioc::PC2<Analog> => (ADC1, 12),
gpioc::PC2<Analog> => (ADC2, 12),
gpioc::PC2<Analog> => (ADC3, 12),
gpioc::PC3<Analog> => (ADC1, 13),
gpioc::PC3<Analog> => (ADC2, 13),
gpioc::PC3<Analog> => (ADC3, 13),
gpioc::PC4<Analog> => (ADC1, 14),
gpioc::PC4<Analog> => (ADC2, 14),
gpioc::PC5<Analog> => (ADC1, 15),
gpioc::PC5<Analog> => (ADC2, 15),
Temperature => (ADC1, 18),
Temperature => (ADC2, 18),
Temperature => (ADC3, 18),
Vbat => (ADC1, 18),
Vbat => (ADC2, 18),
Vbat => (ADC3, 18),
Vref => (ADC1, 17),
Vref => (ADC2, 17),
Vref => (ADC3, 17),
);
#[cfg(any(feature = "stm32f407", feature = "stm32f417"))]
adc_pins!(
gpiof::PF10<Analog> => (ADC3, 8),
gpiof::PF3<Analog> => (ADC3, 9),
gpiof::PF4<Analog> => (ADC3, 14),
gpiof::PF5<Analog> => (ADC3, 15),
gpiof::PF6<Analog> => (ADC3, 4),
gpiof::PF7<Analog> => (ADC3, 5),
gpiof::PF8<Analog> => (ADC3, 6),
gpiof::PF9<Analog> => (ADC3, 7),
);
#[cfg(feature = "stm32f410")]
adc_pins!(
gpioa::PA0<Analog> => (ADC1, 0),
gpioa::PA2<Analog> => (ADC1, 2),
gpioa::PA3<Analog> => (ADC1, 3),
gpioa::PA5<Analog> => (ADC1, 5),
Temperature => (ADC1, 18),
Vbat => (ADC1, 18),
Vref => (ADC1, 17),
);
#[cfg(feature = "stm32f410")]
adc_pins!(
gpioa::PA1<Analog> => (ADC1, 1),
gpioa::PA4<Analog> => (ADC1, 4),
gpioa::PA6<Analog> => (ADC1, 6),
gpioa::PA7<Analog> => (ADC1, 7),
gpiob::PB0<Analog> => (ADC1, 8),
gpiob::PB1<Analog> => (ADC1, 9),
);
#[cfg(feature = "stm32f410")]
adc_pins!(
gpioc::PC0<Analog> => (ADC1, 10),
gpioc::PC1<Analog> => (ADC1, 11),
gpioc::PC2<Analog> => (ADC1, 12),
gpioc::PC3<Analog> => (ADC1, 13),
gpioc::PC4<Analog> => (ADC1, 14),
gpioc::PC5<Analog> => (ADC1, 15),
);
#[cfg(feature = "stm32f411")]
adc_pins!(
gpioa::PA0<Analog> => (ADC1, 0),
gpioa::PA1<Analog> => (ADC1, 1),
gpioa::PA2<Analog> => (ADC1, 2),
gpioa::PA3<Analog> => (ADC1, 3),
gpioa::PA4<Analog> => (ADC1, 4),
gpioa::PA5<Analog> => (ADC1, 5),
gpioa::PA6<Analog> => (ADC1, 6),
gpioa::PA7<Analog> => (ADC1, 7),
gpiob::PB0<Analog> => (ADC1, 8),
gpiob::PB1<Analog> => (ADC1, 9),
Temperature => (ADC1, 18),
Vbat => (ADC1, 18),
Vref => (ADC1, 17),
);
#[cfg(feature = "stm32f411")]
adc_pins!(
gpioc::PC0<Analog> => (ADC1, 10),
gpioc::PC1<Analog> => (ADC1, 11),
gpioc::PC2<Analog> => (ADC1, 12),
gpioc::PC3<Analog> => (ADC1, 13),
gpioc::PC4<Analog> => (ADC1, 14),
gpioc::PC5<Analog> => (ADC1, 15),
);
#[cfg(feature = "stm32f412")]
adc_pins!(
gpioa::PA0<Analog> => (ADC1, 0),
gpioa::PA1<Analog> => (ADC1, 1),
gpioa::PA2<Analog> => (ADC1, 2),
gpioa::PA3<Analog> => (ADC1, 3),
gpioa::PA4<Analog> => (ADC1, 4),
gpioa::PA5<Analog> => (ADC1, 5),
gpioa::PA6<Analog> => (ADC1, 6),
gpioa::PA7<Analog> => (ADC1, 7),
gpiob::PB0<Analog> => (ADC1, 8),
gpiob::PB1<Analog> => (ADC1, 9),
gpioc::PC0<Analog> => (ADC1, 10),
gpioc::PC1<Analog> => (ADC1, 11),
gpioc::PC2<Analog> => (ADC1, 12),
gpioc::PC3<Analog> => (ADC1, 13),
gpioc::PC4<Analog> => (ADC1, 14),
gpioc::PC5<Analog> => (ADC1, 15),
Temperature => (ADC1, 18),
Vbat => (ADC1, 18),
Vref => (ADC1, 17),
);
#[cfg(any(feature = "stm32f413", feature = "stm32f423"))]
adc_pins!(
gpioa::PA0<Analog> => (ADC1, 0),
gpioa::PA1<Analog> => (ADC1, 1),
gpioa::PA2<Analog> => (ADC1, 2),
gpioa::PA3<Analog> => (ADC1, 3),
gpioa::PA4<Analog> => (ADC1, 4),
gpioa::PA5<Analog> => (ADC1, 5),
gpioa::PA6<Analog> => (ADC1, 6),
gpioa::PA7<Analog> => (ADC1, 7),
gpiob::PB0<Analog> => (ADC1, 8),
gpiob::PB1<Analog> => (ADC1, 9),
Temperature => (ADC1, 18),
Vbat => (ADC1, 18),
Vref => (ADC1, 17),
);
#[cfg(any(feature = "stm32f413", feature = "stm32f423"))]
adc_pins!(
gpioc::PC0<Analog> => (ADC1, 10),
gpioc::PC1<Analog> => (ADC1, 11),
gpioc::PC2<Analog> => (ADC1, 12),
gpioc::PC3<Analog> => (ADC1, 13),
gpioc::PC4<Analog> => (ADC1, 14),
gpioc::PC5<Analog> => (ADC1, 15),
);
#[cfg(any(feature = "stm32f427", feature = "stm32f437"))]
adc_pins!(
gpioa::PA0<Analog> => (ADC1, 0),
gpioa::PA0<Analog> => (ADC2, 0),
gpioa::PA0<Analog> => (ADC3, 0),
gpioa::PA1<Analog> => (ADC1, 1),
gpioa::PA1<Analog> => (ADC2, 1),
gpioa::PA1<Analog> => (ADC3, 1),
gpioa::PA2<Analog> => (ADC1, 2),
gpioa::PA2<Analog> => (ADC2, 2),
gpioa::PA2<Analog> => (ADC3, 2),
gpioa::PA3<Analog> => (ADC1, 3),
gpioa::PA3<Analog> => (ADC2, 3),
gpioa::PA3<Analog> => (ADC3, 3),
gpioa::PA4<Analog> => (ADC1, 4),
gpioa::PA4<Analog> => (ADC2, 4),
gpioa::PA5<Analog> => (ADC1, 5),
gpioa::PA5<Analog> => (ADC2, 5),
gpioa::PA6<Analog> => (ADC1, 6),
gpioa::PA6<Analog> => (ADC2, 6),
gpioa::PA7<Analog> => (ADC1, 7),
gpioa::PA7<Analog> => (ADC2, 7),
gpiob::PB0<Analog> => (ADC1, 8),
gpiob::PB0<Analog> => (ADC2, 8),
gpiob::PB1<Analog> => (ADC1, 9),
gpiob::PB1<Analog> => (ADC2, 9),
gpioc::PC0<Analog> => (ADC1, 10),
gpioc::PC0<Analog> => (ADC2, 10),
gpioc::PC0<Analog> => (ADC3, 10),
gpioc::PC1<Analog> => (ADC1, 11),
gpioc::PC1<Analog> => (ADC2, 11),
gpioc::PC1<Analog> => (ADC3, 11),
gpioc::PC2<Analog> => (ADC1, 12),
gpioc::PC2<Analog> => (ADC2, 12),
gpioc::PC2<Analog> => (ADC3, 12),
gpioc::PC3<Analog> => (ADC1, 13),
gpioc::PC3<Analog> => (ADC2, 13),
gpioc::PC3<Analog> => (ADC3, 13),
gpioc::PC4<Analog> => (ADC1, 14),
gpioc::PC4<Analog> => (ADC2, 14),
gpioc::PC5<Analog> => (ADC1, 15),
gpioc::PC5<Analog> => (ADC2, 15),
Temperature => (ADC1, 18),
Temperature => (ADC2, 18),
Temperature => (ADC3, 18),
Vbat => (ADC1, 18),
Vbat => (ADC2, 18),
Vbat => (ADC3, 18),
Vref => (ADC1, 17),
Vref => (ADC2, 17),
Vref => (ADC3, 17),
);
#[cfg(any(feature = "stm32f427", feature = "stm32f437"))]
adc_pins!(
gpiof::PF10<Analog> => (ADC3, 8),
gpiof::PF3<Analog> => (ADC3, 9),
gpiof::PF4<Analog> => (ADC3, 14),
gpiof::PF5<Analog> => (ADC3, 15),
);
#[cfg(any(feature = "stm32f427", feature = "stm32f437"))]
adc_pins!(
gpiof::PF6<Analog> => (ADC3, 4),
gpiof::PF7<Analog> => (ADC3, 5),
gpiof::PF8<Analog> => (ADC3, 6),
gpiof::PF9<Analog> => (ADC3, 7),
);
#[cfg(any(feature = "stm32f429", feature = "stm32f439"))]
adc_pins!(
gpioa::PA0<Analog> => (ADC1, 0),
gpioa::PA0<Analog> => (ADC2, 0),
gpioa::PA0<Analog> => (ADC3, 0),
gpioa::PA1<Analog> => (ADC1, 1),
gpioa::PA1<Analog> => (ADC2, 1),
gpioa::PA1<Analog> => (ADC3, 1),
gpioa::PA2<Analog> => (ADC1, 2),
gpioa::PA2<Analog> => (ADC2, 2),
gpioa::PA2<Analog> => (ADC3, 2),
gpioa::PA3<Analog> => (ADC1, 3),
gpioa::PA3<Analog> => (ADC2, 3),
gpioa::PA3<Analog> => (ADC3, 3),
gpioa::PA4<Analog> => (ADC1, 4),
gpioa::PA4<Analog> => (ADC2, 4),
gpioa::PA5<Analog> => (ADC1, 5),
gpioa::PA5<Analog> => (ADC2, 5),
gpioa::PA6<Analog> => (ADC1, 6),
gpioa::PA6<Analog> => (ADC2, 6),
gpioa::PA7<Analog> => (ADC1, 7),
gpioa::PA7<Analog> => (ADC2, 7),
gpiob::PB0<Analog> => (ADC1, 8),
gpiob::PB0<Analog> => (ADC2, 8),
gpiob::PB1<Analog> => (ADC1, 9),
gpiob::PB1<Analog> => (ADC2, 9),
gpioc::PC0<Analog> => (ADC1, 10),
gpioc::PC0<Analog> => (ADC2, 10),
gpioc::PC0<Analog> => (ADC3, 10),
gpioc::PC1<Analog> => (ADC1, 11),
gpioc::PC1<Analog> => (ADC2, 11),
gpioc::PC1<Analog> => (ADC3, 11),
gpioc::PC2<Analog> => (ADC1, 12),
gpioc::PC2<Analog> => (ADC2, 12),
gpioc::PC2<Analog> => (ADC3, 12),
gpioc::PC3<Analog> => (ADC1, 13),
gpioc::PC3<Analog> => (ADC2, 13),
gpioc::PC3<Analog> => (ADC3, 13),
gpioc::PC4<Analog> => (ADC1, 14),
gpioc::PC4<Analog> => (ADC2, 14),
gpioc::PC5<Analog> => (ADC1, 15),
gpioc::PC5<Analog> => (ADC2, 15),
Temperature => (ADC1, 18),
Temperature => (ADC2, 18),
Temperature => (ADC3, 18),
Vbat => (ADC1, 18),
Vbat => (ADC2, 18),
Vbat => (ADC3, 18),
Vref => (ADC1, 17),
Vref => (ADC2, 17),
Vref => (ADC3, 17),
);
#[cfg(any(feature = "stm32f429", feature = "stm32f439"))]
adc_pins!(
gpiof::PF10<Analog> => (ADC3, 8),
gpiof::PF3<Analog> => (ADC3, 9),
gpiof::PF4<Analog> => (ADC3, 14),
gpiof::PF5<Analog> => (ADC3, 15),
);
#[cfg(any(feature = "stm32f429", feature = "stm32f439"))]
adc_pins!(
gpiof::PF6<Analog> => (ADC3, 4),
gpiof::PF7<Analog> => (ADC3, 5),
gpiof::PF8<Analog> => (ADC3, 6),
gpiof::PF9<Analog> => (ADC3, 7),
);
#[cfg(feature = "stm32f446")]
adc_pins!(
gpioa::PA0<Analog> => (ADC1, 0),
gpioa::PA0<Analog> => (ADC2, 0),
gpioa::PA0<Analog> => (ADC3, 0),
gpioa::PA1<Analog> => (ADC1, 1),
gpioa::PA1<Analog> => (ADC2, 1),
gpioa::PA1<Analog> => (ADC3, 1),
gpioa::PA2<Analog> => (ADC1, 2),
gpioa::PA2<Analog> => (ADC2, 2),
gpioa::PA2<Analog> => (ADC3, 2),
gpioa::PA3<Analog> => (ADC1, 3),
gpioa::PA3<Analog> => (ADC2, 3),
gpioa::PA3<Analog> => (ADC3, 3),
gpioa::PA4<Analog> => (ADC1, 4),
gpioa::PA4<Analog> => (ADC2, 4),
gpioa::PA5<Analog> => (ADC1, 5),
gpioa::PA5<Analog> => (ADC2, 5),
gpioa::PA6<Analog> => (ADC1, 6),
gpioa::PA6<Analog> => (ADC2, 6),
gpioa::PA7<Analog> => (ADC1, 7),
gpioa::PA7<Analog> => (ADC2, 7),
gpiob::PB0<Analog> => (ADC1, 8),
gpiob::PB0<Analog> => (ADC2, 8),
gpiob::PB1<Analog> => (ADC1, 9),
gpiob::PB1<Analog> => (ADC2, 9),
gpioc::PC0<Analog> => (ADC1, 10),
gpioc::PC0<Analog> => (ADC2, 10),
gpioc::PC0<Analog> => (ADC3, 10),
gpioc::PC2<Analog> => (ADC1, 12),
gpioc::PC2<Analog> => (ADC2, 12),
gpioc::PC2<Analog> => (ADC3, 12),
gpioc::PC3<Analog> => (ADC1, 13),
gpioc::PC3<Analog> => (ADC2, 13),
gpioc::PC3<Analog> => (ADC3, 13),
gpioc::PC4<Analog> => (ADC1, 14),
gpioc::PC4<Analog> => (ADC2, 14),
Temperature => (ADC1, 18),
Temperature => (ADC2, 18),
Temperature => (ADC3, 18),
Vbat => (ADC1, 18),
Vbat => (ADC2, 18),
Vbat => (ADC3, 18),
Vref => (ADC1, 17),
Vref => (ADC2, 17),
Vref => (ADC3, 17),
);
#[cfg(feature = "stm32f446")]
adc_pins!(
gpioc::PC1<Analog> => (ADC1, 11),
gpioc::PC1<Analog> => (ADC2, 11),
gpioc::PC1<Analog> => (ADC3, 11),
gpioc::PC5<Analog> => (ADC1, 15),
gpioc::PC5<Analog> => (ADC2, 15),
gpioc::PC5<Analog> => (ADC3, 15),
);
#[cfg(feature = "stm32f446")]
adc_pins!(
gpiof::PF10<Analog> => (ADC3, 8),
gpiof::PF3<Analog> => (ADC3, 9),
gpiof::PF4<Analog> => (ADC3, 14),
gpiof::PF5<Analog> => (ADC3, 15),
gpiof::PF6<Analog> => (ADC3, 4),
gpiof::PF7<Analog> => (ADC3, 5),
gpiof::PF8<Analog> => (ADC3, 6),
gpiof::PF9<Analog> => (ADC3, 7),
);
#[cfg(any(feature = "stm32f469", feature = "stm32f479"))]
adc_pins!(
gpioa::PA0<Analog> => (ADC1, 0),
gpioa::PA0<Analog> => (ADC2, 0),
gpioa::PA0<Analog> => (ADC3, 0),
gpioa::PA1<Analog> => (ADC1, 1),
gpioa::PA1<Analog> => (ADC2, 1),
gpioa::PA1<Analog> => (ADC3, 1),
gpioa::PA2<Analog> => (ADC1, 2),
gpioa::PA2<Analog> => (ADC2, 2),
gpioa::PA2<Analog> => (ADC3, 2),
gpioa::PA3<Analog> => (ADC1, 3),
gpioa::PA3<Analog> => (ADC2, 3),
gpioa::PA3<Analog> => (ADC3, 3),
gpioa::PA4<Analog> => (ADC1, 4),
gpioa::PA4<Analog> => (ADC2, 4),
gpioa::PA5<Analog> => (ADC1, 5),
gpioa::PA5<Analog> => (ADC2, 5),
gpioa::PA6<Analog> => (ADC1, 6),
gpioa::PA6<Analog> => (ADC2, 6),
gpioa::PA7<Analog> => (ADC1, 7),
gpioa::PA7<Analog> => (ADC2, 7),
gpiob::PB0<Analog> => (ADC1, 8),
gpiob::PB0<Analog> => (ADC2, 8),
gpiob::PB1<Analog> => (ADC1, 9),
gpiob::PB1<Analog> => (ADC2, 9),
gpioc::PC0<Analog> => (ADC1, 10),
gpioc::PC0<Analog> => (ADC2, 10),
gpioc::PC0<Analog> => (ADC3, 10),
gpioc::PC1<Analog> => (ADC1, 11),
gpioc::PC1<Analog> => (ADC2, 11),
gpioc::PC1<Analog> => (ADC3, 11),
Temperature => (ADC1, 18),
Temperature => (ADC2, 18),
Temperature => (ADC3, 18),
Vbat => (ADC1, 18),
Vbat => (ADC2, 18),
Vbat => (ADC3, 18),
Vref => (ADC1, 17),
Vref => (ADC2, 17),
Vref => (ADC3, 17),
);
#[cfg(any(feature = "stm32f469", feature = "stm32f479"))]
adc_pins!(
gpioc::PC2<Analog> => (ADC1, 12),
gpioc::PC2<Analog> => (ADC2, 12),
gpioc::PC2<Analog> => (ADC3, 12),
gpioc::PC3<Analog> => (ADC1, 13),
gpioc::PC3<Analog> => (ADC2, 13),
gpioc::PC3<Analog> => (ADC3, 13),
);
#[cfg(any(feature = "stm32f469", feature = "stm32f479"))]
adc_pins!(
gpioc::PC4<Analog> => (ADC1, 14),
gpioc::PC4<Analog> => (ADC2, 14),
gpioc::PC5<Analog> => (ADC1, 15),
gpioc::PC5<Analog> => (ADC2, 15),
);
#[cfg(any(feature = "stm32f469", feature = "stm32f479"))]
adc_pins!(
gpiof::PF10<Analog> => (ADC3, 8),
gpiof::PF3<Analog> => (ADC3, 9),
gpiof::PF4<Analog> => (ADC3, 14),
gpiof::PF5<Analog> => (ADC3, 15),
);
#[cfg(any(feature = "stm32f469", feature = "stm32f479"))]
adc_pins!(
gpiof::PF6<Analog> => (ADC3, 4),
gpiof::PF7<Analog> => (ADC3, 5),
gpiof::PF8<Analog> => (ADC3, 6),
gpiof::PF9<Analog> => (ADC3, 7),
);