STM32 F4 DAC DMA Waveform Generator

Goal: generating an arbitrary periodic waveform using a DAC with DMA and TIM6 as a trigger.

Agenda:

    1. Modeling a waveform in MATLAB and getting the waveform data
    2. Studying the DAC, DMA, and TIM6 to see how it can be used to generate a waveform
    3. Coding and testing a couple of functions
%% Generating an n-bit sine wave
% Modifiable parameters: step, bits, offset
close; clear; clc; points = ; % number of points between sin() to sin(*pi)
bits = ; % -bit sine wave for -bit DAC
offset = ; % limiting DAC output voltage t = :((*pi/(points-))):(*pi); % creating a vector from to *pi
y = sin(t); % getting the sine values
y = y + ; % getting rid of negative values (shifting up by )
y = y*((^bits-)-*offset)/+offset; % limiting the range (+offset) to (^bits-offset)
y = round(y); % rounding the values
plot(t, y); grid % plotting for visual confirmation fprintf('%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, \n', y);

There's a trade-off between the sine wave resolution (number of points from sin(0) to sin(2*pi)), output frequency range, and precision of the output frequency (e.g. we want a 20kHz wave, but we can only get 19.8kHz or 20.2kHz because the step is 0.4kHz). The output frequency is a non-linear function with multiple variables. To complicate it further, some of these variables must be integers within 1 to 65535 range which makes it impossible to output certain frequencies precisely.
Although precise frequency control is terribly hard (if not impossible), one feature does stand out - ability to generate a periodic waveform of any shape. 
Below is the code for mediocre range/precision/resolution but excellent versatility in terms of shaping the output waveform.

@input - uint16_t function[waveform_resolution]
@output - PA4 in analog configuration
@parameters - OUT_FREQ, SIN_RES

To tailor other parameters, study the DAC channel block diagram, electrical characteristics, timing diagrams, etc. To switch DAC channels, see memory map, specifically DAC DHRx register for DMA writes.

#include <stm32f4xx.h>
#include "other_stuff.h" #define OUT_FREQ 5000 // Output waveform frequency
#define SINE_RES 128 // Waveform resolution
#define DAC_DHR12R1_ADDR 0x40007408 // DMA writes into this reg on every request
#define CNT_FREQ 42000000 // TIM6 counter clock (prescaled APB1)
#define TIM_PERIOD ((CNT_FREQ)/((SINE_RES)*(OUT_FREQ))) // Autoreload reg value const uint16_t function[SINE_RES] = { , , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , , , ,
, , , , , , , }; static void TIM6_Config(void);
static void DAC1_Config(void); int main()
{
GPIO_InitTypeDef gpio_A; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); gpio_A.GPIO_Pin = GPIO_Pin_4;
gpio_A.GPIO_Mode = GPIO_Mode_AN;
gpio_A.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &gpio_A); TIM6_Config();
DAC1_Config(); while ()
{ } } static void TIM6_Config(void)
{
TIM_TimeBaseInitTypeDef TIM6_TimeBase; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); TIM_TimeBaseStructInit(&TIM6_TimeBase);
TIM6_TimeBase.TIM_Period = (uint16_t)TIM_PERIOD;
TIM6_TimeBase.TIM_Prescaler = ;
TIM6_TimeBase.TIM_ClockDivision = ;
TIM6_TimeBase.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM6, &TIM6_TimeBase);
TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update); TIM_Cmd(TIM6, ENABLE);
} static void DAC1_Config(void)
{
DAC_InitTypeDef DAC_INIT;
DMA_InitTypeDef DMA_INIT; DAC_INIT.DAC_Trigger = DAC_Trigger_T6_TRGO;
DAC_INIT.DAC_WaveGeneration = DAC_WaveGeneration_None;
DAC_INIT.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
DAC_Init(DAC_Channel_1, &DAC_INIT); DMA_DeInit(DMA1_Stream5);
DMA_INIT.DMA_Channel = DMA_Channel_7;
DMA_INIT.DMA_PeripheralBaseAddr = (uint32_t)DAC_DHR12R1_ADDR;
DMA_INIT.DMA_Memory0BaseAddr = (uint32_t)&function;
DMA_INIT.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_INIT.DMA_BufferSize = SINE_RES;
DMA_INIT.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_INIT.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_INIT.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_INIT.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_INIT.DMA_Mode = DMA_Mode_Circular;
DMA_INIT.DMA_Priority = DMA_Priority_High;
DMA_INIT.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_INIT.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_INIT.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_INIT.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream5, &DMA_INIT); DMA_Cmd(DMA1_Stream5, ENABLE);
DAC_Cmd(DAC_Channel_1, ENABLE);
DAC_DMACmd(DAC_Channel_1, ENABLE);
}

Using the code above we are supposed to get a 5kHz sine wave constructed with 128 points (for better quality, consider using more points).
Here's a picture of what we actually get (off by 25Hz, not too bad).

And here's the cool sinc(x) function. To generate other functions, model it in MATLAB, cast to 12-bit, STM32F4 does the rest.

STM32 F4 DAC DMA Waveform Generator的更多相关文章

  1. STM32 F4 ADC DMA Temperature Sensor

    STM32 F4 ADC DMA Temperature Sensor Goal: detecting temperature variations using a temperature senso ...

  2. STM32之DAC君

    如花说得好:呃呃呃.是俗话说得好:有了ADC,怎可少了DAC..我觉得奇怪.今天我开头就直奔主题了.我想了想,总结了一句话:孙悟空纵然有七十二变.无论是变成猫也好,变成狗也罢.始终还是会变回他本身.所 ...

  3. STM32之串口DMA接收不定长数据

    STM32之串口DMA接收不定长数据 引言 在使用stm32或者其他单片机的时候,会经常使用到串口通讯,那么如何有效地接收数据呢?假如这段数据是不定长的有如何高效接收呢? 同学A:数据来了就会进入串口 ...

  4. STM32的USART DMA传输(转)

    源:STM32的USART DMA传输 问题描述: 我有一个需求,AD采得一定数目的数据之后,由串口DMA发出,由于AD使用双缓冲,所以每次开始DMA的时候都需要重新设置开始的内存地址以及传输的数目( ...

  5. STM32 F4 Clock Sources

    STM32 F4 Clock Sources Goal: routing clock sources to the microcontroller output pin (MCO1)    High- ...

  6. STM32 F4 General-purpose Timers for Periodic Interrupts

    STM32 F4 General-purpose Timers for Periodic Interrupts

  7. STM32 F4 SPI Accelerometer

    STM32 F4 SPI Accelerometer

  8. STM32 F4 GPIO Modes

    STM32 F4 GPIO Modes Goal: creating a visual summary of GPIO configuration modes. The summary at the ...

  9. 重学STM32---(六)DAC+DMA+TIM

    这两天复习了DAC,DMA再加上把基本定时器TIM6和TIM7看了一下,打算写一个综合点的程序,,,就在网上找了一些关于DAC,DMA和定时器相关的程序,最终打算写了输出正弦波的程序... 由于没有示 ...

随机推荐

  1. 云计算-MapReduce

    Hadoop示例程序WordCount详解及实例http://blog.csdn.net/xw13106209/article/details/6116323 hadoop中使用MapReduce编程 ...

  2. Redis的五大数据类型

    1.String(字符串) String是Redis最基本的类型,一个Key对应一个Value. String类型是二进制安全的,意思是Redis的String可以包含任何数据,比如jpg图片或者序列 ...

  3. 绘图: matplotlib核心剖析

    参考:http://www.cnblogs.com/vamei/archive/2013/01/30/2879700.html http://blog.csdn.net/ywjun0919/artic ...

  4. 使用html+css+js实现弹球游戏

    使用html+css+js实现弹球游戏 效果图: 代码如下,复制即可使用: <!doctype html> <head> <style type="text/c ...

  5. tab切换webuploader失效的解决方法

    <script type="text/javascript"> $(document).ready(function () { $('#tt').tabs({ bord ...

  6. python强大的数据类型转换

    # 原始的二维表数据集 jsonObj=[] # 添加模拟的数据 for i in range(1001,1004): for j in range(1,34): jsonObj.append({&q ...

  7. CSS渐变之CSS3 gradient在Firefox3.6下的使用

    一.引子 Firefox3.6包含了许多CSS的改进,本文将向您展示如果使用CSS渐变. 如果你正在运行的Firefox 3.6的最新测试版,你应该看看我们的互动演示,并查看相应的代码.使用单选按钮来 ...

  8. React、Redux 和 Bootstrap

    使用 React.Redux 和 Bootstrap 实现 Alert 今天,我们来学习使用 React.Redux 和 Bootstrap 实现Alert. 例子 这个例子实现了弹出不同类型信息的功 ...

  9. Codeforces 1088E Ehab and a component choosing problem

    Ehab and a component choosing problem 如果有多个连接件那么这几个连接件一定是一样大的, 所以我们先找到值最大的连通块这个肯定是分数的答案. dp[ i ]表示对于 ...

  10. hadoop日志数据分析开发步骤及代码

    日志数据分析:1.背景1.1 hm论坛日志,数据分为两部分组成,原来是一个大文件,是56GB:以后每天生成一个文件,大约是150-200MB之间:1.2 日志格式是apache common日志格式: ...