You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
72 lines
1.9 KiB
Markdown
72 lines
1.9 KiB
Markdown
2 years ago
|
# 2. DAC output with an IIR filter
|
||
|
|
||
|
## DAC initialization
|
||
|
|
||
|
This example uses the DAC with minimal configuration.
|
||
|
|
||
|
Enable the DAC's clock through the RCC:
|
||
|
|
||
|
```cpp
|
||
|
RCC->APB1ENR1 |= RCC_APB1ENR1_DAC1EN;
|
||
|
```
|
||
|
|
||
|
Then, just enable DAC channel one. This will output over pin PA4:
|
||
|
|
||
|
```cpp
|
||
|
DAC1->CR = DAC_CR_EN1;
|
||
|
```
|
||
|
|
||
|
We rely on the default/reset configuration of the other DAC registers. In this
|
||
|
configuration, the DAC is running without a hardware or software trigger;
|
||
|
instead, the DAC will update its output whenever we provide a new output value.
|
||
|
|
||
|
There is a variety of output registers available for different bit-sizes and
|
||
|
alignments. We will stick to the basic 12-bit, right-aligned register
|
||
|
`DHR12R1`.
|
||
|
|
||
|
## IIR filter
|
||
|
|
||
|
The filter will run in a `while` loop, reading samples from the ADC and using
|
||
|
them to produce new DAC output data.
|
||
|
|
||
|
The first-order recursive equation is `y[n] = a*y[n-1] + b*x[n]`. Constants `a`
|
||
|
and `b` set the weights for the previous output sample and current input
|
||
|
sample; their sum should not be greater than one.
|
||
|
|
||
|
```cpp
|
||
|
const float a = 0.5f;
|
||
|
const float b = 0.5f;
|
||
|
```
|
||
|
|
||
|
In the `while` loop, we read our input sample from the ADC (`x[n]`) and
|
||
|
calculate the new output value `y`:
|
||
|
|
||
|
```cpp
|
||
|
unsigned int yprev = 0; // y[n-1]
|
||
|
while (1) {
|
||
|
unsigned int x = adc_read();
|
||
|
unsigned int y = a * yprev + b * x;
|
||
|
```
|
||
|
|
||
|
The new output value is then sent out over the DAC and stored in `yprev` for
|
||
|
the next calculation/iteration.
|
||
|
|
||
|
```cpp
|
||
|
DAC1->DHR12R1 = y;
|
||
|
yprev = y;
|
||
|
```
|
||
|
|
||
|
Finally, we add a small delay to have some basic control over the sampling
|
||
|
rate. Increasing the loop's max value may make the filter's effect more
|
||
|
visible, while decreasing it will minimize the observed effect.
|
||
|
|
||
|
Ideally, the sampling rate would instead be controlled by setting the speed of
|
||
|
the clock given to the ADC and configuring the registers responsible for the
|
||
|
conversion and sampling timings.
|
||
|
|
||
|
```cpp
|
||
|
for (int i = 0; i < 100; ++i);
|
||
|
}
|
||
|
```
|
||
|
|