DAC是STM32系列的一个基本外设,可以将数字信号转化成模拟信号,这次我将使用DAC来输出一个特定波形。

首先确定工作方法,由于我目前在做的简易示波器在输出波形的同时还需要显示输入信号,所以不能占用太多CPU时间,于是就选用了基于DMA的ADC。

使用DMA只需告诉DMA外设它要怎么搬移数据就可以处理其他事。

首先定义一下

#define DAC_DHR12R1    (u32)&(DAC->DHR12R1)   //DAC DATA buff

作为DMA的外设数据地址

首先是初始化输出管脚

DAC1对应PA4

void Wave_GPIO_Config(void)//DAC!-------PA5
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 ;
GPIO_SetBits(GPIOA,GPIO_Pin_4) ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}

需要注意的是,ST官方文档上的说明

一旦使能DACx通道,相应的GPIO引脚(PA4或者PA5)就会自动与DAC的模拟输出相连
(DAC_OUTx)。为了避免寄生的干扰和额外的功耗,引脚PA4或者PA5在之前应当设置成模拟输
入(AIN)。

然后是DAC外设的初始化

void Wave_DAC_Config( void)
{
DAC_InitTypeDef DAC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE); DAC_StructInit(&DAC_InitStructure);
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;//不使用波形发生器
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;//TIM2 Trigger
DAC_Init(DAC_Channel_1, &DAC_InitStructure);
DAC_Cmd(DAC_Channel_1, ENABLE);
DAC_DMACmd(DAC_Channel_1, ENABLE);
}

DAC_OutputBuffer,即是否使用输出缓存。输出缓存的功能主要用来减小输出阻抗,是STM32的DAC无需外部运放就可以直接驱动负载。(一般不用,因为不确定要求

使用TIM2来触发一次DAC,DAC的输出缓存有两个,一个是DAC_DORx ,用户不能直接写入,另一个是DAC_DHRx (DAC_DHR8Rx、 DAC_DHR12Lx、 DAC_DHR12Rx、 DAC_DHR8RD、DAC_DHR12LD、或者DAC_DHR12RD寄存器 )如果没有选中硬件触发 ,存入寄存器DAC_DHRx的数据会在
一个APB1时钟周期后自动传至寄存器DAC_DORx。如果选中硬件触发 ,数据传输在触发发生以后3个APB1时钟周期后完成。

下面是TIM初始化,TIM的工作决定了DMA与DAC的工作频率

void Wave_TIM_Config(u32 Wave1_Fre)//TIM2 Init
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 0x0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_Period = Wave1_Fre;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
}

默认情况下TIM的时钟频率为36Mhz,经过分频为36M/((Prescaler+1)*ClockDivision)。

当计数溢出时就会产生触发事件,TIM_TRG

接着是DMA的初始化
void Wave_DMA_Config(uint16_t* wave)//DMA2
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE); DMA_StructInit( &DMA_InitStructure);
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//peripherals to memory
DMA_InitStructure.DMA_BufferSize = ;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR12R1;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)wave; DMA_Init(DMA2_Channel3, &DMA_InitStructure);
DMA_Cmd(DMA2_Channel3, ENABLE); }

对于DMA要搞清楚要搬的数据的地址在哪,要搬到哪,这里要搬的数据在存储器中,地址为(uint32_t)wave,外设地址为DAC_DHR12R1,是从内存到外设,所以工作模式为

DMA_DIR_PeripheralDST,为双向传输,禁止M2M,存储至存储。触发源为TIM2

最后为总体调用
void Wave_Init(uint16_t* wave)
{
Wave_GPIO_Config();
Wave_TIM_Config(); //72000000/3000=24000 points per second
Wave_DAC_Config();
Wave_DMA_Config(wave);
TIM_Cmd(TIM2, ENABLE);
}

总结:多看官方文档,程序分段写函数

												

STM32 基DMA的DAC波形发生器的更多相关文章

  1. 【STM32H7教程】第60章 STM32H7的DAC应用之定时器触发实现DMA方式双通道波形

    完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第60章       STM32H7的DAC应用之定时器触发实 ...

  2. STM32之DMA+ADC

    借用小甲鱼的经典:各位互联网的广大网友们.大家早上中午晚上好..(打下小广告,因为小甲鱼的视频真的很不错).每次看小甲鱼的视频自学都是比较轻松愉快的..我在想,如果小甲鱼出STM32的视频,我会一集不 ...

  3. STM32之DMA

    一.DMA简介 1.DMA简介 DMA(Direct Memory Access:直接内存存取)是一种可以大大减轻CPU工作量的数据转移方式. CPU有转移数据.计算.控制程序转移等很多功能,但其实转 ...

  4. 基于FPGA的DDS任意波形发生器设计

    一.简介       DDS技术最初是作为频率合成技术提出的,由于其易于控制,相位连续,输出频率稳定度高,分辨率高, 频率转换速度快等优点,现在被广泛应用于任意波形发生器(AWG).基于DDS技术的任 ...

  5. STM32使用DMA发送串口数据

    1.概述 上一篇文章<STM32使用DMA接收串口数据>讲解了如何使用DMA接收数据,使用DMA外设和串口外设,使用的中断是串口空闲中断.本篇文章主要讲解使用DMA发送数据,不会讲解基础的 ...

  6. (DDS)正弦波形发生器——幅值、频率、相位可调(二)

    (DDS)正弦波形发生器--幅值.频率.相位可调(二) 主要关于调相方面 一.项目任务: 设计一个幅值.频率.相位均可调的正弦波发生器. 频率每次增加10kHz 相位每次增加 PI/2 幅值每次增加两 ...

  7. (DDS)正弦波形发生器——幅值、频率、相位可调(一)

    (DDS)正弦波形发生器--幅值.频率.相位可调 一.项目任务: 设计一个幅值.频率.相位均可调的正弦波发生器. 频率每次增加1kHz. 相位每次增加 2*PI/256 幅值每次增加两倍 二.文章内容 ...

  8. STM32 使用DMA+DAC+TIMER 输出正弦波

    之前已经简单论述过,根据我个人菜鸟的了解与认识,对之前的知识进行整理回顾: DMA:我的理解就是一个通道,或者是一座桥梁.在静态内存到静态内存,或者外设到静态内存间的一个通讯的通道.建立这个通道的好处 ...

  9. stm32 DMA+timer+DAC

    是有延迟的:

随机推荐

  1. WPF 自定义RadioButton样式

    一.RadioButton基本样式 RadioButton基本样式包含两种状态,这里也是使用两张图片来代替两种状态,当然你也可以通过IconFont或Path来替换这两种状态. 效果如下: 样式代码如 ...

  2. confluence搭建详情

    Confluence安装&破解&汉化 编辑时间: 2017年7月7日18:01:13 1.介绍 Atlassian Confluence(简称Confluence)是一个专业的wiki ...

  3. Linux网络配置(仅主机模式)

    1.启动虚机,网络选择:仅主机模式 2.命令行输入 rm -rf /etc/udev/rules.d/70-persistent-net.rules 3.修改虚机中的网络配置 >>vim ...

  4. 关于tr069网管开发系列教程

    原创作品,转载请注明出处,严禁非法转载.如有错误,请留言! email:40879506@qq.com 声明:本系列涉及的开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅 ...

  5. spark2.1:读取hive中存储的多元组(string,double)失败

    这两天和同事一起在想着如何把一个表的记录减少,表记录包含了:objectid(主小区信息),gridid(归属栅格),height(高度),rsrp(主小区rsrp),n_objectid(邻区),n ...

  6. Java 静态内部类注意点

    静态内部类(嵌套类)的对象除了没有对生成它的外部类对象的引用特权外,与其他所有内部类完全一样. 在内部类不需要访问外部类时,应该使用静态内部类(嵌套类). 与常规内部类不同的是,静态内部类可以拥有静态 ...

  7. 前端监控系统(二)JS错误日志收集篇

    前端监控系统 目前已经上线,欢迎使用! 服务器搭建好了,可以着手开发了. 其实前端需要分析的数据有很多,包括,PVUV, 接口请求统计,耗时统计,JS错误统计,用户使用设备统计,用户地域分布,页面用户 ...

  8. [SCOI2008]天平

    题目描述 你有n个砝码,均为1克,2克或者3克.你并不清楚每个砝码的重量,但你知道其中一些砝码重量的大小关系.你把其中两个砝码A 和B 放在天平的左边,需要另外选出两个砝码放在天平的右边.问:有多少种 ...

  9. codeforces 651C Watchmen

    Watchmen are in a danger and Doctor Manhattan together with his friend Daniel Dreiberg should warn t ...

  10. STL注意比较函数

    可重复插入?: set<int ,less_equal<int> >s; s.insert(10); s.insert(10); 第二次调用insert,集合回去确认10是否已 ...