|
1 year ago | |
---|---|---|
.. | ||
Makefile | 1 year ago | |
README.md | 1 year ago | |
main.c | 1 year ago |
README.md
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:
RCC->APB1ENR1 |= RCC_APB1ENR1_DAC1EN;
Then, just enable DAC channel one. This will output over pin PA4:
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.
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
:
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.
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.
for (int i = 0; i < 100; ++i);
}