Differentiate between read
and read_internal
for STM32F0 ADC
The internal channels (vbat, vref, and temperature) are not real pins and do not have the `set_as_analog` method. They must be read using the `read_internal` method.
This commit is contained in:
parent
a0b6096610
commit
511a951246
@ -48,25 +48,33 @@ impl Resolution {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait InternalChannel<T>: sealed::InternalChannel<T> {}
|
||||||
|
|
||||||
|
mod sealed {
|
||||||
|
pub trait InternalChannel<T> {
|
||||||
|
fn channel(&self) -> u8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Vbat;
|
pub struct Vbat;
|
||||||
impl<T: Instance> AdcPin<T> for Vbat {}
|
impl<T: Instance> InternalChannel<T> for Vbat {}
|
||||||
impl<T: Instance> super::sealed::AdcPin<T> for Vbat {
|
impl<T: Instance> sealed::InternalChannel<T> for Vbat {
|
||||||
fn channel(&self) -> u8 {
|
fn channel(&self) -> u8 {
|
||||||
18
|
18
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Vref;
|
pub struct Vref;
|
||||||
impl<T: Instance> AdcPin<T> for Vref {}
|
impl<T: Instance> InternalChannel<T> for Vref {}
|
||||||
impl<T: Instance> super::sealed::AdcPin<T> for Vref {
|
impl<T: Instance> sealed::InternalChannel<T> for Vref {
|
||||||
fn channel(&self) -> u8 {
|
fn channel(&self) -> u8 {
|
||||||
17
|
17
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Temperature;
|
pub struct Temperature;
|
||||||
impl<T: Instance> AdcPin<T> for Temperature {}
|
impl<T: Instance> InternalChannel<T> for Temperature {}
|
||||||
impl<T: Instance> super::sealed::AdcPin<T> for Temperature {
|
impl<T: Instance> sealed::InternalChannel<T> for Temperature {
|
||||||
fn channel(&self) -> u8 {
|
fn channel(&self) -> u8 {
|
||||||
16
|
16
|
||||||
}
|
}
|
||||||
@ -219,28 +227,25 @@ impl<'d, T: Instance> Adc<'d, T> {
|
|||||||
((u32::from(sample) * self.vref_mv) / self.resolution.to_max_count()) as u16
|
((u32::from(sample) * self.vref_mv) / self.resolution.to_max_count()) as u16
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert(&mut self) -> u16 {
|
|
||||||
unsafe {
|
|
||||||
T::regs().isr().modify(|reg| {
|
|
||||||
reg.set_eoc(true);
|
|
||||||
reg.set_eosmp(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
// A.7.5 Single conversion sequence code example - Software trigger
|
|
||||||
T::regs().cr().modify(|reg| reg.set_adstart(true));
|
|
||||||
while !T::regs().isr().read().eoc() {
|
|
||||||
// spin
|
|
||||||
}
|
|
||||||
|
|
||||||
T::regs().dr().read().0 as u16
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read<P>(&mut self, pin: &mut P) -> u16
|
pub fn read<P>(&mut self, pin: &mut P) -> u16
|
||||||
where
|
where
|
||||||
P: AdcPin<T> + crate::gpio::sealed::Pin,
|
P: AdcPin<T> + crate::gpio::sealed::Pin,
|
||||||
{
|
{
|
||||||
|
let channel = pin.channel();
|
||||||
unsafe {
|
unsafe {
|
||||||
|
pin.set_as_analog();
|
||||||
|
self.read_channel(channel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 {
|
||||||
|
let channel = channel.channel();
|
||||||
|
unsafe {
|
||||||
|
self.read_channel(channel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn read_channel(&mut self, channel: u8) -> u16 {
|
||||||
// A.7.2 ADC enable sequence code example
|
// A.7.2 ADC enable sequence code example
|
||||||
if T::regs().isr().read().adrdy() {
|
if T::regs().isr().read().adrdy() {
|
||||||
T::regs().isr().modify(|reg| reg.set_adrdy(true));
|
T::regs().isr().modify(|reg| reg.set_adrdy(true));
|
||||||
@ -254,13 +259,21 @@ impl<'d, T: Instance> Adc<'d, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
T::regs().cfgr1().modify(|reg| reg.set_res(self.resolution.res()));
|
T::regs().cfgr1().modify(|reg| reg.set_res(self.resolution.res()));
|
||||||
Self::set_channel_sample_time(pin.channel(), self.sample_time);
|
T::regs().isr().modify(|reg| {
|
||||||
pin.set_as_analog();
|
reg.set_eoc(true);
|
||||||
|
reg.set_eosmp(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
// A.7.5 Single conversion sequence code example - Software trigger
|
||||||
T::regs()
|
T::regs()
|
||||||
.chselr()
|
.chselr()
|
||||||
.write(|reg| reg.set_chselx(pin.channel() as usize, true));
|
.write(|reg| reg.set_chselx(channel as usize, true));
|
||||||
|
T::regs().smpr().modify(|reg| reg.set_smp(self.sample_time.sample_time()));
|
||||||
let value = self.convert();
|
T::regs().cr().modify(|reg| reg.set_adstart(true));
|
||||||
|
while !T::regs().isr().read().eoc() {
|
||||||
|
// spin
|
||||||
|
}
|
||||||
|
let value = T::regs().dr().read().0 as u16;
|
||||||
|
|
||||||
// A.7.3 ADC disable code example
|
// A.7.3 ADC disable code example
|
||||||
T::regs().cr().modify(|reg| reg.set_adstp(true));
|
T::regs().cr().modify(|reg| reg.set_adstp(true));
|
||||||
@ -274,9 +287,4 @@ impl<'d, T: Instance> Adc<'d, T> {
|
|||||||
|
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) {
|
|
||||||
T::regs().smpr().modify(|reg| reg.set_smp(sample_time.sample_time()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user