STM32学习问题记录(12)- DAC(正弦波发生)

     DAC,与ADC相对,是数字量转模拟量,经常用来作为信号发生器,这里DAC一定要详细记录,但其实原理还是相对简单。首先我们看一下

DAC的触发源:

DAC的触发源有6个定时器的更新时间和一个外部触发,一般外部触发我们用于DAC的直流产生,所以我们这次使用的是定时器触发。

DAC的主要特性:(来自官方手册)

2个DAC转换器:1个输出通道对应1个转换器
● 8位或者12位单调输出
● 12位模式下数据左对齐或者右对齐
● 同步更新功能
● 噪声波形生成
● 三角波形生成
● 双DAC通道同时或者分别转换
● 每个通道都有DMA功能
● 外部触发转换
● 输入参考电压V REF+

DAC配置的特殊注意点:

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

代码讲解(带详细注解,将整个工程用到的函数分开讲解,更加清晰)

int main(void)
{
   DAC_Mode_Init();   //DAC模式初始化
   while(1);	 
}

const uint16_t Sine12bit[32] = {
	2448,2832,3186,3496,3751,3940,4057,4095,4057,3940,
	3751,3496,3186,2832,2448,2048,1648,1264,910,600,345,
	156,39,0,39,156,345,600,910,1264,1648,2048
};


uint32_t DualSine12bit[32];

void DAC_Mode_Init(void)
{
	uint32_t Idx = 0;  

	DAC_Config();   //DAC初始化
	DAC_TIM_Config();    //定时器触发配置
	DAC_DMA_Config();    //DMA配置
        for (Idx = 0; Idx < 32; Idx++)           //for循环给Dualsin12bit赋值,双通道输出原因看下图
  {
    DualSine12bit[Idx] = (Sine12bit[Idx] << 16) + (Sine12bit[Idx]);   //每次传输一个12位数值+该值左移16位从而得到一个32位数值
  }
}

这是一个32位的寄存器,我们每次都往里面写一次相应数值,循环输出,从而得到正弦波。看下图可加深理解

static void DAC_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  DAC_InitTypeDef  DAC_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	  //开启APB2的gpioa的时钟
	
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);   //开启APB1的DAC时钟,DAC挂载于APB1的通道4
	
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4 | GPIO_Pin_5;    //开启GPIOA4 和 A5
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;     //设置为模拟输入(看上面注意点,重要)
  GPIO_Init(GPIOA, &GPIO_InitStructure);     //写入结构体
	

  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;	  //设置为TIM2更新,即设置TIM2作为触发源					
  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;	//不使用波形发生器
  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;	//不适用输出缓冲,若如要输出电流可配置
  DAC_Init(DAC_Channel_1, &DAC_InitStructure);             //初始化通道一
  DAC_Init(DAC_Channel_2, &DAC_InitStructure);             //初始化通道二

  DAC_Cmd(DAC_Channel_1, ENABLE);    //使能通道一

  DAC_Cmd(DAC_Channel_2, ENABLE);   //使能通道二

  DAC_DMACmd(DAC_Channel_2, ENABLE);   //使能DAC对DMA的请求
}

static void DAC_TIM_Config(void)
{
	
  TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
	
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);    //使能定时器2
	
 // TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); 
  TIM_TimeBaseStructure.TIM_Period = 19;      //计时到20会更新一次   								
  TIM_TimeBaseStructure.TIM_Prescaler = 0x0;      // 内部1分频,也就是计数器时钟为72M  						
  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;    	//外部不分频(没用到)				
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  	//向上计数
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);   // 配置触发源
  TIM_Cmd(TIM2, ENABLE);   //使能 TIM2

}


static void DAC_DMA_Config(void)
{	
	DMA_InitTypeDef  DMA_InitStructure;

	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);  //使能DMA2
	
  DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR12RD_Address;      //定义为双通道模式,其他模式请看手册				
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&DualSine12bit ;    //定义的写入寄存器的32位数组			
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;	               //传输方向为内存到外设					
  DMA_InitStructure.DMA_BufferSize = 32;		               //缓存大小32位					
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;     //外设地址固定	
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;	       //内存地址自增	
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;	//外设传输一个字节
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;		//内存传输一个字节			
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;	                        //循环输出					
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;				//优先级为高					
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;					//禁止内存间传输					
  DMA_Init(DMA2_Channel4, &DMA_InitStructure);                                  //开启DMA通道4	
  DMA_Cmd(DMA2_Channel4, ENABLE);                                               //使能
}

#define DAC_DHR12RD_Address      0x40007420 //0x40007420    

DAC内存地址0x40007420,两位输出寄存器偏移20,其他模式地址请查找手册


DAC得到的信号频率:

流程总结:



猜你喜欢

转载自blog.csdn.net/vca821/article/details/80697776