Skip to content

Commit 187ddd8

Browse files
committed
[example] Add Nucleo-L552ZE-Q DAC DMA example
1 parent e846c8c commit 187ddd8

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright (c) 2021, Christopher Durand
3+
*
4+
* This file is part of the modm project.
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public
7+
* License, v. 2.0. If a copy of the MPL was not distributed with this
8+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
11+
#include <modm/board.hpp>
12+
13+
#include <numbers>
14+
#include <cmath>
15+
#include <array>
16+
17+
using namespace Board;
18+
19+
constexpr auto computeSinTable(float frequency = 1.f)
20+
{
21+
std::array<uint16_t, 100> data{};
22+
constexpr auto HalfOutput = ((1 << 12) - 1) / 2; // 12 bit dac
23+
for (size_t i = 0; i < data.size(); ++i) {
24+
constexpr auto pi = std::numbers::pi_v<float>;
25+
data[i] = HalfOutput * (1 + sin(i * (2 * pi * frequency / data.size())));
26+
}
27+
return data;
28+
}
29+
30+
constexpr auto sinTable1 = computeSinTable(1.0f);
31+
constexpr auto sinTable2 = computeSinTable(2.0f);
32+
33+
// DAC1 channel 1 on GpioA4: switch between 10 kHz and 20 kHz sine signal after DMA transfer complete
34+
35+
void setupDac()
36+
{
37+
using Dac = Dac1Dma;
38+
using DacChannel = Dac::Channel1<Dma1::Channel1>;
39+
40+
Dac::connect<GpioOutputA4::Out1>();
41+
Dac::initialize();
42+
43+
DacChannel::configure(sinTable1.data(), sinTable1.size(), DmaBase::CircularMode::Disabled);
44+
45+
// trigger source 3: timer 4 for DAC1, see reference manual
46+
DacChannel::setTriggerSource(3);
47+
48+
// switch between signals when transfer completed
49+
static bool toggleBit = false;
50+
Dma1::Channel1::setTransferCompleteIrqHandler([]() {
51+
DacChannel::stopDma();
52+
toggleBit = !toggleBit;
53+
if (toggleBit) {
54+
DacChannel::setData(sinTable1.data(), sinTable1.size());
55+
} else {
56+
DacChannel::setData(sinTable2.data(), sinTable2.size());
57+
}
58+
DacChannel::startDma();
59+
});
60+
61+
Dma1::Channel1::enableInterruptVector();
62+
Dma1::Channel1::enableInterrupt(Dma1::InterruptEnable::TransferComplete |
63+
Dma1::InterruptEnable::TransferError);
64+
65+
DacChannel::startDma();
66+
DacChannel::enableDacChannel();
67+
}
68+
69+
int main()
70+
{
71+
Board::initialize();
72+
Leds::setOutput();
73+
74+
MODM_LOG_INFO << "DAC DMA Demo" << modm::endl;
75+
76+
Dma1::enable();
77+
78+
setupDac();
79+
80+
// configure timer 4 as trigger for DACs
81+
// 110 MHz / 110 = 1 MHz => 1 Msps DAC output
82+
Timer4::enable();
83+
Timer4::setMode(Timer4::Mode::UpCounter);
84+
Timer4::setPrescaler(1);
85+
Timer4::setOverflow(110 - 1);
86+
Timer4::applyAndReset();
87+
Timer4::start();
88+
89+
// Enable trigger out for timer 4
90+
TIM4->CR2 |= TIM_CR2_MMS_1;
91+
92+
while (true)
93+
{
94+
Leds::toggle();
95+
modm::delay_ms(500);
96+
}
97+
98+
return 0;
99+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<library>
2+
<extends>modm:nucleo-l552ze-q</extends>
3+
<options>
4+
<option name="modm:build:build.path">../../../build/nucleo_l552-ze/dac_dma</option>
5+
</options>
6+
<modules>
7+
<module>modm:debug</module>
8+
<module>modm:platform:dac:1</module>
9+
<module>modm:platform:dma</module>
10+
<module>modm:platform:timer:4</module>
11+
<module>modm:build:scons</module>
12+
</modules>
13+
</library>

0 commit comments

Comments
 (0)