博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
STM32 F4 DAC DMA Waveform Generator
阅读量:6977 次
发布时间:2019-06-27

本文共 6620 字,大约阅读时间需要 22 分钟。

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, offsetclose; clear; clc;points = 128;                            % number of points between sin(0) to sin(2*pi)bits   = 12;                             % 12-bit sine wave for 12-bit DACoffset = 75;                             % limiting DAC output voltaget = 0:((2*pi/(points-1))):(2*pi);        % creating a vector from 0 to 2*piy = sin(t);                              % getting the sine valuesy = y + 1;                               % getting rid of negative values (shifting up by 1)y = y*((2^bits-1)-2*offset)/2+offset;    % limiting the range (0+offset) to (2^bits-offset)y = round(y);                            % rounding the valuesplot(t, y); grid                         % plotting for visual confirmationfprintf('%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 
#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 valueconst uint16_t function[SINE_RES] = { 2048, 2145, 2242, 2339, 2435, 2530, 2624, 2717, 2808, 2897, 2984, 3069, 3151, 3230, 3307, 3381, 3451, 3518, 3581, 3640, 3696, 3748, 3795, 3838, 3877, 3911, 3941, 3966, 3986, 4002, 4013, 4019, 4020, 4016, 4008, 3995, 3977, 3954, 3926, 3894, 3858, 3817, 3772, 3722, 3669, 3611, 3550, 3485, 3416, 3344, 3269, 3191, 3110, 3027, 2941, 2853, 2763, 2671, 2578, 2483, 2387, 2291, 2194, 2096, 1999, 1901, 1804, 1708, 1612, 1517, 1424, 1332, 1242, 1154, 1068, 985, 904, 826, 751, 679, 610, 545, 484, 426, 373, 323, 278, 237, 201, 169, 141, 118, 100, 87, 79, 75, 76, 82, 93, 109, 129, 154, 184, 218, 257, 300, 347, 399, 455, 514, 577, 644, 714, 788, 865, 944, 1026, 1111, 1198, 1287, 1378, 1471, 1565, 1660, 1756, 1853, 1950, 2047 }; 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 (1) { } }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 = 0; TIM6_TimeBase.TIM_ClockDivision = 0; 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. 

 

转载地址:http://uyupl.baihongyu.com/

你可能感兴趣的文章
Java中正则Matcher类的matches()、lookAt()和find()的区别
查看>>
PHP获取毫秒时间戳,利用microtime()函数
查看>>
【ASP.NET Core】解决“The required antiforgery cookie "xxx" is not present”的错误
查看>>
C++ 纯虚方法
查看>>
.net内存回收与Dispose﹐Close﹐Finalize方法
查看>>
oracle update批量修改sql语句编写
查看>>
Web前端开发人员和设计师必读文章推荐【系列七】
查看>>
我的四轴专用PID参数整定方法及原理---超长文慎入(转)
查看>>
Python-常用字符串转换实例
查看>>
大数据高效复制的处理案例分析总结
查看>>
PagedGeometry 笔记03
查看>>
IAR生产HEX文件
查看>>
WCF笔记
查看>>
MOS2010开发基础和集几种开发模型
查看>>
配置导出MOSS2010列表数据到Excel并根据列表记录自动刷新数据
查看>>
Sharepoint学习笔记—ECMAScript对象模型系列-- 8、组与用户操作(一)
查看>>
SQuirreL SQL Client 使用记录
查看>>
HTML Inspector – 帮助你编写高质量的 HTML 代码
查看>>
vb.net结构化异常处理和“邪用”
查看>>
HEVC/H.265 的未来必须是使用并行处理(OpenCL?) OpenCV和OpenCL区别
查看>>