aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorJuliDi <[email protected]>2023-06-28 11:58:25 +0200
committerJuliDi <[email protected]>2023-06-28 11:58:25 +0200
commit91c31d5e437b510af3c535f5e597881042563496 (patch)
tree001888ad099d1253a7d90d553776ad36e016cb16 /examples
parent9c81d6315500b236adc7634d2d2d6ef776f984eb (diff)
Update DAC examples, add DAC + DMA example
Diffstat (limited to 'examples')
-rw-r--r--examples/stm32f4/src/bin/dac.rs9
-rw-r--r--examples/stm32h7/src/bin/dac.rs9
-rw-r--r--examples/stm32l4/Cargo.toml2
-rw-r--r--examples/stm32l4/src/bin/dac.rs16
-rw-r--r--examples/stm32l4/src/bin/dac_dma.rs148
5 files changed, 166 insertions, 18 deletions
diff --git a/examples/stm32f4/src/bin/dac.rs b/examples/stm32f4/src/bin/dac.rs
index d97ae7082..3a6216712 100644
--- a/examples/stm32f4/src/bin/dac.rs
+++ b/examples/stm32f4/src/bin/dac.rs
@@ -4,7 +4,8 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::dac::{Channel, Dac, Value}; 7use embassy_stm32::dac::{DacCh1, DacChannel, Value};
8use embassy_stm32::dma::NoDma;
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
10#[embassy_executor::main] 11#[embassy_executor::main]
@@ -12,12 +13,12 @@ async fn main(_spawner: Spawner) -> ! {
12 let p = embassy_stm32::init(Default::default()); 13 let p = embassy_stm32::init(Default::default());
13 info!("Hello World, dude!"); 14 info!("Hello World, dude!");
14 15
15 let mut dac = Dac::new_1ch(p.DAC, p.PA4); 16 let mut dac = DacCh1::new(p.DAC, NoDma, p.PA4);
16 17
17 loop { 18 loop {
18 for v in 0..=255 { 19 for v in 0..=255 {
19 unwrap!(dac.set(Channel::Ch1, Value::Bit8(to_sine_wave(v)))); 20 unwrap!(dac.set(Value::Bit8(to_sine_wave(v))));
20 unwrap!(dac.trigger(Channel::Ch1)); 21 dac.trigger();
21 } 22 }
22 } 23 }
23} 24}
diff --git a/examples/stm32h7/src/bin/dac.rs b/examples/stm32h7/src/bin/dac.rs
index f12716370..586b4154b 100644
--- a/examples/stm32h7/src/bin/dac.rs
+++ b/examples/stm32h7/src/bin/dac.rs
@@ -4,7 +4,8 @@
4 4
5use cortex_m_rt::entry; 5use cortex_m_rt::entry;
6use defmt::*; 6use defmt::*;
7use embassy_stm32::dac::{Channel, Dac, Value}; 7use embassy_stm32::dac::{DacCh1, DacChannel, Value};
8use embassy_stm32::dma::NoDma;
8use embassy_stm32::time::mhz; 9use embassy_stm32::time::mhz;
9use embassy_stm32::Config; 10use embassy_stm32::Config;
10use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
@@ -19,12 +20,12 @@ fn main() -> ! {
19 config.rcc.pll1.q_ck = Some(mhz(100)); 20 config.rcc.pll1.q_ck = Some(mhz(100));
20 let p = embassy_stm32::init(config); 21 let p = embassy_stm32::init(config);
21 22
22 let mut dac = Dac::new_1ch(p.DAC1, p.PA4); 23 let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4);
23 24
24 loop { 25 loop {
25 for v in 0..=255 { 26 for v in 0..=255 {
26 unwrap!(dac.set(Channel::Ch1, Value::Bit8(to_sine_wave(v)))); 27 unwrap!(dac.set(Value::Bit8(to_sine_wave(v))));
27 unwrap!(dac.trigger(Channel::Ch1)); 28 dac.trigger();
28 } 29 }
29 } 30 }
30} 31}
diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml
index 3bb473ef5..d2d228282 100644
--- a/examples/stm32l4/Cargo.toml
+++ b/examples/stm32l4/Cargo.toml
@@ -25,3 +25,5 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
25heapless = { version = "0.7.5", default-features = false } 25heapless = { version = "0.7.5", default-features = false }
26 26
27micromath = "2.0.0" 27micromath = "2.0.0"
28
29static_cell = "1.0.0"
diff --git a/examples/stm32l4/src/bin/dac.rs b/examples/stm32l4/src/bin/dac.rs
index a36ed5d90..8aad27646 100644
--- a/examples/stm32l4/src/bin/dac.rs
+++ b/examples/stm32l4/src/bin/dac.rs
@@ -3,26 +3,22 @@
3#![feature(type_alias_impl_trait)] 3#![feature(type_alias_impl_trait)]
4 4
5use defmt::*; 5use defmt::*;
6use embassy_stm32::dac::{Channel, Dac, Value}; 6use embassy_stm32::dac::{DacCh1, DacChannel, Value};
7use embassy_stm32::dma::NoDma;
7use embassy_stm32::pac; 8use embassy_stm32::pac;
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
10#[cortex_m_rt::entry] 11#[cortex_m_rt::entry]
11fn main() -> ! { 12fn main() -> ! {
12 info!("Hello World!");
13
14 pac::RCC.apb1enr1().modify(|w| {
15 w.set_dac1en(true);
16 });
17
18 let p = embassy_stm32::init(Default::default()); 13 let p = embassy_stm32::init(Default::default());
14 info!("Hello World!");
19 15
20 let mut dac = Dac::new_1ch(p.DAC1, p.PA4); 16 let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4);
21 17
22 loop { 18 loop {
23 for v in 0..=255 { 19 for v in 0..=255 {
24 unwrap!(dac.set(Channel::Ch1, Value::Bit8(to_sine_wave(v)))); 20 unwrap!(dac.set(Value::Bit8(to_sine_wave(v))));
25 unwrap!(dac.trigger(Channel::Ch1)); 21 dac.trigger();
26 } 22 }
27 } 23 }
28} 24}
diff --git a/examples/stm32l4/src/bin/dac_dma.rs b/examples/stm32l4/src/bin/dac_dma.rs
new file mode 100644
index 000000000..81e6a58e4
--- /dev/null
+++ b/examples/stm32l4/src/bin/dac_dma.rs
@@ -0,0 +1,148 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_stm32::dac::{DacChannel, ValueArray};
8use embassy_stm32::pac::timer::vals::{Mms, Opm};
9use embassy_stm32::peripherals::{TIM6, TIM7};
10use embassy_stm32::rcc::low_level::RccPeripheral;
11use embassy_stm32::time::Hertz;
12use embassy_stm32::timer::low_level::Basic16bitInstance;
13use micromath::F32Ext;
14use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _};
16
17pub type Dac1Type<'d> =
18 embassy_stm32::dac::DacCh1<'d, embassy_stm32::peripherals::DAC1, embassy_stm32::peripherals::DMA1_CH3>;
19
20pub type Dac2Type<'d> =
21 embassy_stm32::dac::DacCh2<'d, embassy_stm32::peripherals::DAC1, embassy_stm32::peripherals::DMA1_CH4>;
22
23#[embassy_executor::main]
24async fn main(spawner: Spawner) {
25 let config = embassy_stm32::Config::default();
26
27 // Initialize the board and obtain a Peripherals instance
28 let p: embassy_stm32::Peripherals = embassy_stm32::init(config);
29
30 // Obtain two independent channels (p.DAC1 can only be consumed once, though!)
31 let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split();
32
33 let dac1 = {
34 type T = impl Sized;
35 static STATIC_CELL: StaticCell<T> = StaticCell::new();
36 STATIC_CELL.init(dac_ch1)
37 };
38
39 let dac2 = {
40 type T = impl Sized;
41 static STATIC_CELL: StaticCell<T> = StaticCell::new();
42 STATIC_CELL.init(dac_ch2)
43 };
44
45 spawner.spawn(dac_task1(dac1)).ok();
46 spawner.spawn(dac_task2(dac2)).ok();
47}
48
49#[embassy_executor::task]
50async fn dac_task1(dac: &'static mut Dac1Type<'static>) {
51 let data: &[u8; 256] = &calculate_array::<256>();
52
53 info!("TIM6 frequency is {}", TIM6::frequency());
54 const FREQUENCY: Hertz = Hertz::hz(200);
55 let reload: u32 = (TIM6::frequency().0 / FREQUENCY.0) / data.len() as u32;
56
57 // Depends on your clock and on the specific chip used, you may need higher or lower values here
58 if reload < 10 {
59 error!("Reload value {} below threshold!", reload);
60 }
61
62 dac.select_trigger(embassy_stm32::dac::Ch1Trigger::Tim6).unwrap();
63 dac.enable_channel().unwrap();
64
65 TIM6::enable();
66 TIM6::regs().arr().modify(|w| w.set_arr(reload as u16 - 1));
67 TIM6::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE));
68 TIM6::regs().cr1().modify(|w| {
69 w.set_opm(Opm::DISABLED);
70 w.set_cen(true);
71 });
72
73 debug!(
74 "TIM6 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}",
75 TIM6::frequency(),
76 FREQUENCY,
77 reload,
78 reload as u16,
79 data.len()
80 );
81
82 // Loop technically not necessary if DMA circular mode is enabled
83 loop {
84 info!("Loop DAC1");
85 if let Err(e) = dac.write(ValueArray::Bit8(data), true).await {
86 error!("Could not write to dac: {}", e);
87 }
88 }
89}
90
91#[embassy_executor::task]
92async fn dac_task2(dac: &'static mut Dac2Type<'static>) {
93 let data: &[u8; 256] = &calculate_array::<256>();
94
95 info!("TIM7 frequency is {}", TIM7::frequency());
96
97 const FREQUENCY: Hertz = Hertz::hz(600);
98 let reload: u32 = (TIM7::frequency().0 / FREQUENCY.0) / data.len() as u32;
99
100 if reload < 10 {
101 error!("Reload value {} below threshold!", reload);
102 }
103
104 TIM7::enable();
105 TIM7::regs().arr().modify(|w| w.set_arr(reload as u16 - 1));
106 TIM7::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE));
107 TIM7::regs().cr1().modify(|w| {
108 w.set_opm(Opm::DISABLED);
109 w.set_cen(true);
110 });
111
112 dac.select_trigger(embassy_stm32::dac::Ch2Trigger::Tim7).unwrap();
113
114 debug!(
115 "TIM7 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}",
116 TIM7::frequency(),
117 FREQUENCY,
118 reload,
119 reload as u16,
120 data.len()
121 );
122
123 if let Err(e) = dac.write(ValueArray::Bit8(data), true).await {
124 error!("Could not write to dac: {}", e);
125 }
126}
127
128fn to_sine_wave(v: u8) -> u8 {
129 if v >= 128 {
130 // top half
131 let r = 3.14 * ((v - 128) as f32 / 128.0);
132 (r.sin() * 128.0 + 127.0) as u8
133 } else {
134 // bottom half
135 let r = 3.14 + 3.14 * (v as f32 / 128.0);
136 (r.sin() * 128.0 + 127.0) as u8
137 }
138}
139
140fn calculate_array<const N: usize>() -> [u8; N] {
141 let mut res = [0; N];
142 let mut i = 0;
143 while i < N {
144 res[i] = to_sine_wave(i as u8);
145 i += 1;
146 }
147 res
148}