Skip to content

Commit 6700dbc

Browse files
authored
Merge pull request #86 from braun-embedded/adc
Add support for continous conversions to ADC
2 parents f3b3e82 + 322378f commit 6700dbc

File tree

11 files changed

+873
-62
lines changed

11 files changed

+873
-62
lines changed

Cargo.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,18 @@ debug = true
262262
opt-level = "s"
263263

264264

265+
[[example]]
266+
name = "adc_cont"
267+
required-features = ["stm32l0x2"]
268+
269+
[[example]]
270+
name = "adc_multi"
271+
required-features = ["stm32l0x2"]
272+
273+
[[example]]
274+
name = "adc_trig"
275+
required-features = ["stm32l0x2"]
276+
265277
[[example]]
266278
name = "aes_ecb"
267279
required-features = ["stm32l082"]

examples/adc_cont.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//! Example showing continuous ADC
2+
3+
4+
#![no_main]
5+
#![no_std]
6+
7+
8+
extern crate panic_halt;
9+
10+
11+
use core::{
12+
fmt::Write as _,
13+
pin::Pin,
14+
};
15+
16+
use cortex_m_rt::entry;
17+
// use nb::block;
18+
use stm32l0xx_hal::{
19+
prelude::*,
20+
dma::DMA,
21+
pac,
22+
rcc,
23+
serial,
24+
};
25+
26+
27+
#[entry]
28+
fn main() -> ! {
29+
let dp = pac::Peripherals::take().unwrap();
30+
31+
let mut rcc = dp.RCC.freeze(rcc::Config::hsi16());
32+
let adc = dp.ADC.constrain(&mut rcc);
33+
let mut dma = DMA::new(dp.DMA1, &mut rcc);
34+
let gpioa = dp.GPIOA.split(&mut rcc);
35+
36+
// The A0 connector on the B-L072Z-LRWAN1 Discovery kit
37+
let a0 = gpioa.pa0.into_analog();
38+
39+
// Connected to the host computer via the ST-LINK
40+
let tx = gpioa.pa2;
41+
let rx = gpioa.pa3;
42+
43+
// Initialize USART for test output
44+
let (mut tx, _) = dp.USART2
45+
.usart(
46+
(tx, rx),
47+
serial::Config::default()
48+
.baudrate(115_200.bps()),
49+
&mut rcc,
50+
)
51+
.unwrap()
52+
.split();
53+
54+
// Create the buffer we're going to use for DMA.
55+
//
56+
// This is safe, since this is the main function, and it's only executed
57+
// once. This means there is no other code accessing this `static`.
58+
static mut BUFFER: [u16; 256] = [0; 256];
59+
let buffer = Pin::new(unsafe { &mut BUFFER });
60+
61+
// Start reading ADC values
62+
let mut adc = adc.start(
63+
a0,
64+
None,
65+
&mut dma.handle,
66+
dma.channels.channel1,
67+
buffer,
68+
);
69+
70+
loop {
71+
let read_available = match adc.read_available() {
72+
Ok(read_available) => {
73+
read_available
74+
}
75+
Err(err) => {
76+
write!(tx, "Error reading available values: {:?}\r\n", err).unwrap();
77+
continue;
78+
}
79+
};
80+
81+
for val in read_available {
82+
// Printing values out is way too slow to process all the values
83+
// being created, meaning we're going to see buffer overruns all the
84+
// time.
85+
//
86+
// For this reason, we're ignoring buffer overrun errors here, and
87+
// just process any values that were put into the buffer for us.
88+
if let Ok(val) = val {
89+
write!(tx, "{}\r\n", val).unwrap();
90+
}
91+
}
92+
}
93+
}

examples/adc_multi.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//! Example showing continuous ADC with hardware trigger
2+
3+
4+
#![no_main]
5+
#![no_std]
6+
7+
8+
extern crate panic_halt;
9+
10+
11+
use core::{
12+
fmt::Write as _,
13+
pin::Pin,
14+
};
15+
16+
17+
use cortex_m_rt::entry;
18+
use stm32l0xx_hal::{
19+
prelude::*,
20+
adc,
21+
dma::DMA,
22+
pac::{
23+
self,
24+
tim2::cr2::MMS_A,
25+
},
26+
rcc,
27+
serial,
28+
};
29+
30+
31+
#[entry]
32+
fn main() -> ! {
33+
let dp = pac::Peripherals::take().unwrap();
34+
35+
let mut rcc = dp.RCC.freeze(rcc::Config::hsi16());
36+
let adc = dp.ADC.constrain(&mut rcc);
37+
let mut dma = DMA::new(dp.DMA1, &mut rcc);
38+
let gpioa = dp.GPIOA.split(&mut rcc);
39+
40+
// Connected to the host computer via the ST-LINK
41+
let tx = gpioa.pa2;
42+
let rx = gpioa.pa3;
43+
44+
// Initialize USART for test output
45+
let (mut tx, _) = dp.USART2
46+
.usart(
47+
(tx, rx),
48+
serial::Config::default()
49+
.baudrate(115_200.bps()),
50+
&mut rcc,
51+
)
52+
.unwrap()
53+
.split();
54+
55+
// Create the buffer we're going to use for DMA.
56+
//
57+
// This is safe, since this is the main function, and it's only executed
58+
// once. This means there is no other code accessing this `static`.
59+
static mut BUFFER: [u16; 256] = [0; 256];
60+
let buffer = Pin::new(unsafe { &mut BUFFER });
61+
62+
// Let's select some channels
63+
let mut channels = adc::Channels::from(gpioa.pa0.into_analog());
64+
channels.add(gpioa.pa1.into_analog());
65+
channels.add(gpioa.pa4.into_analog());
66+
channels.add(gpioa.pa5.into_analog());
67+
68+
// Start reading ADC values
69+
let mut adc = adc.start(
70+
channels,
71+
Some(adc::Trigger::TIM2_TRGO),
72+
&mut dma.handle,
73+
dma.channels.channel1,
74+
buffer,
75+
);
76+
77+
// Enable trigger output for TIM2. This must happen after ADC has been
78+
// configured.
79+
dp.TIM2
80+
.timer(1u32.hz(), &mut rcc)
81+
.select_master_mode(MMS_A::UPDATE);
82+
83+
loop {
84+
for val in adc.read_available().unwrap() {
85+
write!(tx, "{}\r\n", val.unwrap()).unwrap();
86+
}
87+
}
88+
}

examples/adc_trig.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//! Example showing continuous ADC with hardware trigger
2+
3+
4+
#![no_main]
5+
#![no_std]
6+
7+
8+
extern crate panic_halt;
9+
10+
11+
use core::{
12+
fmt::Write as _,
13+
pin::Pin,
14+
};
15+
16+
17+
use cortex_m_rt::entry;
18+
use stm32l0xx_hal::{
19+
prelude::*,
20+
adc,
21+
dma::DMA,
22+
pac::{
23+
self,
24+
tim2::cr2::MMS_A,
25+
},
26+
rcc,
27+
serial,
28+
};
29+
30+
31+
#[entry]
32+
fn main() -> ! {
33+
let dp = pac::Peripherals::take().unwrap();
34+
35+
let mut rcc = dp.RCC.freeze(rcc::Config::hsi16());
36+
let adc = dp.ADC.constrain(&mut rcc);
37+
let mut dma = DMA::new(dp.DMA1, &mut rcc);
38+
let gpioa = dp.GPIOA.split(&mut rcc);
39+
40+
// The A0 connector on the B-L072Z-LRWAN1 Discovery kit
41+
let a0 = gpioa.pa0.into_analog();
42+
43+
// Connected to the host computer via the ST-LINK
44+
let tx = gpioa.pa2;
45+
let rx = gpioa.pa3;
46+
47+
// Initialize USART for test output
48+
let (mut tx, _) = dp.USART2
49+
.usart(
50+
(tx, rx),
51+
serial::Config::default()
52+
.baudrate(115_200.bps()),
53+
&mut rcc,
54+
)
55+
.unwrap()
56+
.split();
57+
58+
// Create the buffer we're going to use for DMA.
59+
//
60+
// This is safe, since this is the main function, and it's only executed
61+
// once. This means there is no other code accessing this `static`.
62+
static mut BUFFER: [u16; 256] = [0; 256];
63+
let buffer = Pin::new(unsafe { &mut BUFFER });
64+
65+
// Start reading ADC values
66+
let mut adc = adc.start(
67+
a0,
68+
Some(adc::Trigger::TIM2_TRGO),
69+
&mut dma.handle,
70+
dma.channels.channel1,
71+
buffer,
72+
);
73+
74+
// Enable trigger output for TIM2. This must happen after ADC has been
75+
// configured.
76+
dp.TIM2
77+
.timer(1u32.hz(), &mut rcc)
78+
.select_master_mode(MMS_A::UPDATE);
79+
80+
loop {
81+
for val in adc.read_available().unwrap() {
82+
write!(tx, "{}\r\n", val.unwrap()).unwrap();
83+
}
84+
}
85+
}

0 commit comments

Comments
 (0)