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. C# 启动 SQL Server 服务

    //首先要添加 System.ServiceProcess.dll 引用 ServiceController sc = new ServiceController("MSSQLSERVER& ...

  2. 手机PC监听用户复制内容

    最近应项目需求,为了获取到更多用户想要搜索的信息,需要把用户点击复制的内容获取到,然后传送给后台以更好的了解客户需求,自己在这个方法上栽了个大跟头,只考虑其一却不知道结合使用,脑袋卡顿,随笔记下,望自 ...

  3. 快速搭建fabric-v1.1.0的chaincode开发环境

    本文参考了fabric官方文档:http://hyperledger-fabric.readthedocs.io/en/latest/peer-chaincode-devmode.html?highl ...

  4. Linux入门:usermod - 修改用户帐户信息

    一.什么是usermod? usermod 命令通过修改系统帐户文件来修改用户账户信息usermod [options] user_name选项(options)-a|--append ##把用户追加 ...

  5. 新概念英语(1-129)Seventy miles an hour

    Lesson 129 Seventy miles an hour 时速70英里 Listen to the tape then answer this question. What does Ann ...

  6. docker实践

    我的docker 学习笔记2   ps axf docker run -d cyf:sshd /usr/sbin -D   docker  ps docker-enter.sh 686 ps axf ...

  7. Java-Maven(六):Eclipse中Maven插件的命令操作

    之前几个章节学习了maven的概念,及maven插件安装后如何创建工程,那么maven工程中是如何使用maven命令呢?本章节将会学习这个话题. 在pom.xml中配置maven命令插件 如果向在ma ...

  8. asp.net core 二 Nginx Supervisor 负载,监听

           ASP.NET Core负载均衡集群搭建(CentOS7+Nginx+Supervisor+Kestrel)          asp.net core在linux运行下,一但命令行退出 ...

  9. 自己使用Vue全家桶问题合集(很多eslint规范问题)

    遇到很多问题一一道来. 1.vue报错 Do not use built-in or reserved HTML elements as component id:header 组件,不能和html标 ...

  10. 再谈前端HTML模板技术

    在web2.0之前,写jsp的时候虽然有es和JSTL,但是还是坚持jsp.后面在外包公司为了快速交货,还是用了php Smart技术. web2.0后,前端模板技术风行. 代表有如下三大类: Str ...