STM32 F4 DAC DMA Waveform Generator
STM32 F4 DAC DMA Waveform Generator
Goal: generating an arbitrary periodic waveform using a DAC with DMA and TIM6 as a trigger.
Agenda:
- Modeling a waveform in MATLAB and getting the waveform data
- Studying the DAC, DMA, and TIM6 to see how it can be used to generate a waveform
- 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的更多相关文章
- STM32 F4 ADC DMA Temperature Sensor
STM32 F4 ADC DMA Temperature Sensor Goal: detecting temperature variations using a temperature senso ...
- STM32之DAC君
如花说得好:呃呃呃.是俗话说得好:有了ADC,怎可少了DAC..我觉得奇怪.今天我开头就直奔主题了.我想了想,总结了一句话:孙悟空纵然有七十二变.无论是变成猫也好,变成狗也罢.始终还是会变回他本身.所 ...
- STM32之串口DMA接收不定长数据
STM32之串口DMA接收不定长数据 引言 在使用stm32或者其他单片机的时候,会经常使用到串口通讯,那么如何有效地接收数据呢?假如这段数据是不定长的有如何高效接收呢? 同学A:数据来了就会进入串口 ...
- STM32的USART DMA传输(转)
源:STM32的USART DMA传输 问题描述: 我有一个需求,AD采得一定数目的数据之后,由串口DMA发出,由于AD使用双缓冲,所以每次开始DMA的时候都需要重新设置开始的内存地址以及传输的数目( ...
- STM32 F4 Clock Sources
STM32 F4 Clock Sources Goal: routing clock sources to the microcontroller output pin (MCO1) High- ...
- STM32 F4 General-purpose Timers for Periodic Interrupts
STM32 F4 General-purpose Timers for Periodic Interrupts
- STM32 F4 SPI Accelerometer
STM32 F4 SPI Accelerometer
- STM32 F4 GPIO Modes
STM32 F4 GPIO Modes Goal: creating a visual summary of GPIO configuration modes. The summary at the ...
- 重学STM32---(六)DAC+DMA+TIM
这两天复习了DAC,DMA再加上把基本定时器TIM6和TIM7看了一下,打算写一个综合点的程序,,,就在网上找了一些关于DAC,DMA和定时器相关的程序,最终打算写了输出正弦波的程序... 由于没有示 ...
随机推荐
- mysql开启远程连接及本地连接
问题描述 在本机windows上连接linux服务器上的mysql报错:host'XXX' is not allowed to connect to this mysql server. 这个错误是由 ...
- C++--------------------------------指针和数组替换使用原因
马上要考试了,复习数据结构中,对C的指针不太了解,在严蔚敏<数据结构(C语言版)>中,发现p22定义顺序存储结构: typedef srtuct{ ElemType *elem; //存储 ...
- [CEOI2015 Day2]世界冰球锦标赛 (双向搜索)
题目描述 [CEOI2015 Day2]世界冰球锦标赛译自 CEOI2015 Day2 T1「Ice Hockey World Championship」 今年的世界冰球锦标赛在捷克举行.Bobek ...
- sublime text 3 开启卡顿(win7)解决办法
启动sublime3,ctrl+~打开命令窗口,输入以下 { "update<em>check": false, "font</em>size&q ...
- tomcat报错catalina.sh: line 401: /usr/java/jdk1.7.52/bin/java: No such file or directory
将生产服务器的Tomcat目录打包过来后解压后,启动Tomcat后,发现如下问题: # ./shutdown.sh Using CATALINA_BASE: /usr/local/tomcat ...
- js 替换任意字符串中间几位为*星号
<script> var str='河南纳智企业管理咨询有限公司'; a=str.substr(0,2)+'***'+str.substr(5,str.split('').length); ...
- selnium远程机上传图片遇到的坑
一般上传图片方法采取方案如下: input标签的file类型上传图片,使用对象的sendkeys+路径方法 使用js注入,再用使用对象的sendkeys+路径方法 使用autolt生成的exe,打开对 ...
- Java 基本语法---Java数组
Java 基本语法---Java数组 0. 概述 数组:相同类型的数据 按照顺序 组成的一种 引用数据类型 . 数据类型:基本数据类型 + 引用数据类型: 引用数据类型:类 + 接口 + 数组 : 一 ...
- iOS仿安卓手势解锁
界面是一个九宫格的布局.九宫格实现思路. 先确定有多少列 cloum = 3; 计算出每列之间的距离 计算为: CGFloat margin = (当前View的宽度 - 列数 * 按钮的宽度) / ...
- transform:rotate/旋转
<!DOCTYPE html> <html> <head> <style> div { width:100px; height:75px; backgr ...