STM32 基DMA的DAC波形发生器
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波形发生器的更多相关文章
- 【STM32H7教程】第60章 STM32H7的DAC应用之定时器触发实现DMA方式双通道波形
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第60章 STM32H7的DAC应用之定时器触发实 ...
- STM32之DMA+ADC
借用小甲鱼的经典:各位互联网的广大网友们.大家早上中午晚上好..(打下小广告,因为小甲鱼的视频真的很不错).每次看小甲鱼的视频自学都是比较轻松愉快的..我在想,如果小甲鱼出STM32的视频,我会一集不 ...
- STM32之DMA
一.DMA简介 1.DMA简介 DMA(Direct Memory Access:直接内存存取)是一种可以大大减轻CPU工作量的数据转移方式. CPU有转移数据.计算.控制程序转移等很多功能,但其实转 ...
- 基于FPGA的DDS任意波形发生器设计
一.简介 DDS技术最初是作为频率合成技术提出的,由于其易于控制,相位连续,输出频率稳定度高,分辨率高, 频率转换速度快等优点,现在被广泛应用于任意波形发生器(AWG).基于DDS技术的任 ...
- STM32使用DMA发送串口数据
1.概述 上一篇文章<STM32使用DMA接收串口数据>讲解了如何使用DMA接收数据,使用DMA外设和串口外设,使用的中断是串口空闲中断.本篇文章主要讲解使用DMA发送数据,不会讲解基础的 ...
- (DDS)正弦波形发生器——幅值、频率、相位可调(二)
(DDS)正弦波形发生器--幅值.频率.相位可调(二) 主要关于调相方面 一.项目任务: 设计一个幅值.频率.相位均可调的正弦波发生器. 频率每次增加10kHz 相位每次增加 PI/2 幅值每次增加两 ...
- (DDS)正弦波形发生器——幅值、频率、相位可调(一)
(DDS)正弦波形发生器--幅值.频率.相位可调 一.项目任务: 设计一个幅值.频率.相位均可调的正弦波发生器. 频率每次增加1kHz. 相位每次增加 2*PI/256 幅值每次增加两倍 二.文章内容 ...
- STM32 使用DMA+DAC+TIMER 输出正弦波
之前已经简单论述过,根据我个人菜鸟的了解与认识,对之前的知识进行整理回顾: DMA:我的理解就是一个通道,或者是一座桥梁.在静态内存到静态内存,或者外设到静态内存间的一个通讯的通道.建立这个通道的好处 ...
- stm32 DMA+timer+DAC
是有延迟的:
随机推荐
- python 中os.path.join 双斜杠的解决办法
这两天在写东西的时候遇到了这个问题,主要是上传图片之后,无法在页面展示,原因就出在用join 拼接的路径中出现了"\"而造成的. >>> import os &g ...
- Python内置函数(3)——max
英文文档: max(iterable, *[, key, default]) max(arg1, arg2, *args[, key]) Return the largest item in an i ...
- ELK学习总结(4-2)关于导入数据
用REST API的_bulk来批量插入,可以达到5到10w条每秒 把数据写进json文件,然后再通过批处理,执行文件插入数据: 1.先定义一定格式的json文件,文件不能过大,过大会报错 2.后用c ...
- 在ABPZERO中,扩展实体的方法。
内容 介绍 扩展的抽象实体 将新属性添加给用户 添加迁移 在界面上显示地址 在用户编辑/添加功能中添加地址 扩展的非抽象类实体 获得版本的派生实体 添加迁移 在界面上添加价格 在创建/编辑版本功能中加 ...
- io使用的设计模式
File f = new File("c:/a.txt"); 1. FileInputStream fis = new FileInputStream(f); 2. Reader ...
- jq中的表单验证插件------jquery.validate
今天我们来说一下表单验证,有人说我们在进行表单验证的时候使用正则来验证是非常麻烦的,现在我来给大家介绍一下表单验证的插件:jquery.validate.min.js 它是与jquery一起结合用来使 ...
- 南京邮电大学java第一次实验报告
实 验 报 告 ( 2017 / 2018学年 第2学期) 课程名称 JAVA语言程序设计 实验名称 Java集成开发环境的安装与使用. Java变量.表达式与控制结构 实验时间 2018 年 4 月 ...
- POJ-2421 Constructing Roads---确定部分边的MST
题目链接: https://vjudge.net/problem/POJ-2421 题目大意: 还是给你n个点,然后求最小生成树.特殊之处在于有一些点之间已经连上了边. 思路: 和POJ-1751一样 ...
- [论文阅读] MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications (MobileNet)
论文地址:MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications 本文提出的模型叫Mobi ...
- js 常用数组和字符串方法
javascript数组与字符串常用方法总结 最近在梳理js的基础,首先从数组和字符串开始. string 常用方法: 1.substring(start开始位置的索引,end结束位置索引) 截取的位 ...