之前已经简单论述过,根据我个人菜鸟的了解与认识,对之前的知识进行整理回顾:

DMA:我的理解就是一个通道,或者是一座桥梁。在静态内存到静态内存,或者外设到静态内存间的一个通讯的通道。建立这个通道的好处是:可以抛开CPU,不占用CPU的资源,直接使用这块内存的内容,速度也会加快。

DAC:STM32F103中有两个DAC,可以同时使用。DAC的作用就是将数字量转化为模拟量(电压),在这就不作太多的讲解。

TIMER:定时器。不作讲解。

那么对于使用DMA+DAC+TIMER产生正弦波的原理或过程,我有这样一个简单的理解:

  先将一个可以生成正弦波的数据表保存在静态内存中,然后在DAC以及这块内存中间使用DMA建立一个通道,经过以上步骤之后,DAC模块就可以通过DAM通道拿取静态内存中可以生成正弦波的数据,拿取数据,然后经过数模准换,在引脚进行输出就可以得到正弦波了。那么当然,这个速度是非常快的,如果没有一定的延时,那么得到的估计就是一个变化很快的模拟量。所以这个时候就需要使用定时器TIMER了。DAC在初始化的时候,可以设置成使用定时器触发,这就意味着,当定时器溢满的时候,就会触发DAC工作。这样一来,就可以通过改变定时器的定时时间来改变正弦波的周期了。

以上是我的一个简单的了解,应该会有很多不严谨不正确的地方,毕竟是一个新手菜鸟,以上见解也是方便自己学习,本人也会根据不断学习进行补充营养的。下面贴出一个例子进行分析:

1、初始化波形表以及输出的引脚

/********正弦波输出表***********/
void SineWave_Data( u16 cycle ,u16 *D)
{
u16 i;
for( i=0;i<cycle;i++)
{
D[i]=(u16)((Um*sin(( 1.0*i/(cycle-1))*2*PI)+Um)*4095/3.3);
}
} /******************正弦波形表***********************/
#ifdef Sine_WaveOutput_Enable
u16 SineWave_Value[256]; //用函数封装
#endif /******DAC寄存器地址声明*******/
#define DAC_DHR12R1 (u32)&(DAC->DHR12R1) //DAC通道1输出地址
#define DAC_DHR12R2 (u32)&(DAC->DHR12R2) //DAC通道2输出地址 /****************初始化引脚******************/
void SineWave_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开时钟
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出速率
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 ; //选择引脚
GPIO_SetBits(GPIOA,GPIO_Pin_5) ; //拉高输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化
}

 2、初始化DAC

/******************DAC初始化¯*************************/
void SineWave_DAC_Config( void)
{
DAC_InitTypeDef DAC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);//开DAC时钟 /**************DAC结构初始化*******************/
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;//DAC触发为定时器2触发
DAC_Init(DAC_Channel_1, &DAC_InitStructure);//初始化
DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC的通道1
DAC_DMACmd(DAC_Channel_1, ENABLE); //使能DAC通道1的DMA
}

  3、定时器配置

/*********定时器初始化************/
void SineWave_TIM_Config(u32 Wave1_Fre)
{
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_CounterMode = TIM_CounterMode_Up;//向上计数
TIM_TimeBaseStructure.TIM_Period = Wave1_Fre;//设置输出频率
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);//设置TIME输出触发为更新模式
}

 4、DMA配置 

/*********DMA配置***********/
void SineWave_DMA_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);//开启DMA2时钟 DMA_StructInit( &DMA_InitStructure); //DMA结构体初始化
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//从寄存器读数据
DMA_InitStructure.DMA_BufferSize = 256;//寄存器大小
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_VeryHigh;/优先级非常高
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//关闭内存到内存模式
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//循环发送模式

     DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR12R1;//外设地址为DAC通道1的地址
     DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SineWave_Value;//波形数据表内存地址

     DMA_Init(DMA2_Channel3, &DMA_InitStructure);//初始化
     DMA_Cmd(DMA2_Channel3, ENABLE); //使能DMA通道3    

}

 5、正弦波初始化

 

void SineWave_Init(u16 Wave1_Fre)
{
  u16 f1=(u16)(72000000/sizeof(SineWave_Value)*2/Wave1_Fre);//计算频率
 SineWave_Data( 256 ,SineWave_Value); //生成输出正弦波的波形表
  SineWave_GPIO_Config(); //初始化io
  SineWave_TIM_Config(f1); //初始化定时器
  SineWave_DAC_Config(); //配置DAC
  SineWave_DMA_Config(); //配置DMA
  TIM_Cmd(TIM2, ENABLE); //开启定时器
}

  经过以上的简单配置,就可以使得32板输出sin波形了。

STM32 使用DMA+DAC+TIMER 输出正弦波的更多相关文章

  1. STM32 基DMA的DAC波形发生器

    DAC是STM32系列的一个基本外设,可以将数字信号转化成模拟信号,这次我将使用DAC来输出一个特定波形. 首先确定工作方法,由于我目前在做的简易示波器在输出波形的同时还需要显示输入信号,所以不能占用 ...

  2. 【STM32】PWM DAC基本原理(实验:PWM实现DAC)

    虽然STM32F103ZET6具有内部DAC,但是也仅仅只有两条DAC通道,并且STM32还有其他的很多型号是没有DAC的.通常情况下,采用专用的D/A芯片来实现,但是这样就会带来成本的增加. 不过S ...

  3. STM32之DMA+ADC

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

  4. STM32的GPIO口的输出开漏输出和推挽输出

    本文来自cairang45的博客,讲述了STM32的GPIO口的输出开漏输出和推挽输出, 作者博客:http://blog.ednchina.com/cairang45 本文来自: 高校自动化网(Ww ...

  5. STM32之DMA

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

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

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

  7. STM32—驱动六轴MPU6050输出欧拉角

    文章目录 一.MPU6050介绍 1.MPU6050与陀螺仪.加速度计的关系: 2.整体概括 3.引脚说明 4.基本配置及相关寄存器 电源管理寄存器1 陀螺仪配置寄存器 加速度计配置寄存器 FIFO使 ...

  8. STM32:TIMER输出比较模式-PWM

    在自己小板子上移植PWM时候又重新学习了一下,加入两点:1,对各种输出比较模式的学习:2,输出模式时加入中断 先写出函数: //TIM4 PWM部分初始化 //PWM输出初始化 //period:输出 ...

  9. STM32的DMA

    什么是DMA?其全称是:Direct Memory Access:根据ST公司提供的相关信息,DMA是STM32中一个独立与Cortex-M3内核的模块,有点类似与ADC.PWM.TIMER等模块:主 ...

随机推荐

  1. linux 学习2 文件处理命令

    ____命令格式与目录处理命令 ____目录处理命令 ____文件处理命令 ____链接命令 ls list 菜单 命令 [-选项][参数] 选项:调整功能,多个选项可以写在一起,不分顺序. 简化选项 ...

  2. SQLserver 查看数据库包含指定数据的表(字段)

    找出所有字段 1 select a.name as columnname,object_name(a.id)as tablename into t from syscolumns a, sysobje ...

  3. lisp中的cons

    看到ANSI Common Lisp 第三章的游程编码时,就发现作者很准确的使用了list和cons来生成目标列表,虽然list是由cons扩展而来,区别也仅仅是最后一个元素的加入方式,于是勾起了之前 ...

  4. PPTP-VPN第三章——用户流量与并发数限制

    在前面两篇文章中详细介绍了pptp vpn的安装与使用,以及如何配置用户认证存入mysql数据库.本文将在前面两篇文章的基础上介绍如何对用户的流量做限制,同时限制相同账号的用户,同一时刻的在线数为1. ...

  5. 初学c# -- 学习笔记(七) RichTextBox支持GIF

    园子里许明吉博客写的一篇,刚好用到这个,写的非常好.转过来了 不过在应用中也有一些问题,win10下不能中文输入,凑合着进行了修改, 下面是原来的代码: private void button2_Cl ...

  6. 介绍开源的.net通信框架NetworkComms框架 源码分析(二十三 )TCPConnection

    原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架  作者是英国人  以前是收费的 目前作者已经开源  许可是 ...

  7. tcp/ip http socket笔记

    1.TCP/IP协议是传输层协议,主要解决数据如何在网络中传输 HTTP是应用层协议,主要解决如何包装数据 2.TCP连接的三次握手 第一次握手:客户端发送syn包到服务器,并进入SYN_SEND状态 ...

  8. 特殊字符(包含emoji)的梳理

    背景知识 emoji表情符号,是20世纪90年代由NTT Docomo栗田穣崇(Shigetaka Kurit)创建的,词义来自日语(えもじ,e-moji,moji在日语中的含义是字符).emoji可 ...

  9. laravel(二):laravel基本入门 看到Hello Laravel

    1.Hello World 首先,我们来添加一些文字,在页面中显示.为了能访问网页,要启动程序服务器. $ php artisan serve 上述命令会启动 PHP 内建的开发服务器,要查看程序,请 ...

  10. IIS内存溢出-设置IIS的应用程序池

    在ASP.NET Web服务器上,ASP.NET所能够用到的内存,通常不会等同于所有的内存数量.在machine.config(C:/WINDOWS/Microsoft.NET/Framework/v ...