STM32F103 DAC实验

实验目的

通过本实验学习STM32的DAC数模转换器的使用,利用DAC输出电压,再用ADC采集,通过串口打印出来,数据手册请参看第12章。

实验简介

DAC数模转换器的作用就是将数字输入转换成模拟信号输出,比如音频播放就是通过DAC 将数字信号转换成模拟信号实现的。

STM32的DAC模块是12位数字输入,电压输出的数字/模拟转换器。DAC可以配置为8位或12位模式,也可以与DMA控制器配合使用。DAC工作在12位模式时,数据可以设置成左对齐或右对齐。DAC模块有2个输出通道,每个通道都有单独的转换器。在双DAC模式下,2个通道可以独立地进行转换,也可以同时进行转换并同步地更新2个通道的输出。DAC可以通过引脚输入参考电压VREF+
以获得更精准的转换结果。

STM32的DAC模块主要特点有

  1. 2个DAC转换器:每个转换器对应1个输出通道。
  2. 8位或12位单调输出
  3. 12位模式下数据左对齐或右对齐
  4. 同步更新功能
  5. 噪声波形形成
  6. 三角波形形成
  7. 双DAC通道同时或者分别转换
  8. 在这里插入图片描述
  9. 在这里插入图片描述

电路设计

用跳帽就将DAC输出引脚PA4连接到ADC1的采集引脚PA6,将DAC生成的电压通过ADC再采集回来,通过串口打印出来。

代码

main.c

#include "MyIncludes.h"

char buff[100];
uint16_t DAC_Vol = 1500;
uint16_t Vol;

u16 sys_cnt = 0;
void systick_isr(void)
{
  if(sys_cnt < 1000)
  {
    sys_cnt++;
  }
  else
  {
    sys_cnt = 0;
    HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_4|GPIO_PIN_5);
  }
} 

int main()
{
  System_Init();
  LED_Init();
  SysTick_Init(systick_isr);
  Key_Init();
  USART1_Init(115200,NULL,NULL);
  STM32_ADC_Init(ADC1,ADC_CHANNEL_6,NULL);
  Stm32DAC_Init();
   
  DAC_SetVoltage(DAC_Vol);
  delay_ms(100);
  sprintf(buff,"Expected Voltage: %d.%d%dV, ",DAC_Vol/1000,DAC_Vol%1000/100,DAC_Vol%100/10);
  printf(buff);
   
  Vol = Vol_Sample();
  sprintf(buff,"ADC VOL: %d.%d%dV\r\n",Vol/1000,Vol%1000/100,Vol%100/10);
   
  printf(buff);
  while(1)
  {
     Key_Read();
     if(Key_Info.Num_Last != Key_Info.Num)
     {
       Key_Info.Num_Last = Key_Info.Num;
       if(Key_Info.Num != 0)
       {
         switch(Key_Info.Num)
         {
          case KEY_ONE:
          if( DAC_Vol <3200 )
          DAC_Vol += 100; 
          break;
          
          case KEY_TWO:
          if(DAC_Vol > 100)
          DAC_Vol -=100;
          break;
          default:break;
         }
         DAC_SetVoltage(DAC_Vol);
         sprintf(buff,"Expected Voltage: %d.%d%dV, ",DAC_Vol/1000,DAC_Vol%1000/100,DAC_Vol%100/10);
         printf(buff);
          
         Vol = Vol_Sample();
         sprintf(buff,"ADC VOL: %d.%d%dV\r\n",Vol/1000,Vol%1000/100,Vol%100/10);
         printf(buff);
       }
     }
  }
  
}

dac.h

#ifndef __DAC_H_
#define __DAC_H_

#include "stm32f1xx.h"
#include "stm32_types.h"
#include "stm32f1xx_hal.h"

//#define DAC_USE_DMA 
//DAC使用DMA,打开此定义

#define DACx_CHANNEL_PIN GPIO_PIN_4 
//DAC输出引脚
#define DACx_CHANNEL     DAC_CHANNEL_1
//DAC转换通道

//DAC2
//#define DACx_CHANNEL_PIN GPIO_PIN_5
//DAC输出引脚
//#define DACx_CHANNEL     DAH_CHANNEL_2
//DAC转换通道PA5

#define DACx_DMA_INSTANCE DMA2_Channe13
#define DACx_DMA_IRQn   DMA_Channe13_IRQn
#define DACx_DMA_IRQHandler DMA2_Channel13_IRQHandler

void Stm32DAC_Init(void);
//DA转化器初始化
void DAC_SetVal(uint32_t Data);
//设置DAC值
void DAC_SetVoltage(uint32_t vol);
//DAC转换生成电压(0-3.3V)
//vol:0~3300,电压放大1000倍
void DAC_TriangleInit(void);
//三角波生成初始化
void DAC_NoiseWaveConfig(void);
//噪声波生成
void DAC_EscalatorConfig(uint32_t *data,uint32_t len);
//
void DAC_DMA_Init(void);
void DAC_DMA_Start(uint32_t* pData,uint32_t Length);
void DAC_DMA_Stop(void);
void DAC_TriangleInit(void);
void DAC_NoiseWaveInit(void);
#endif

dac.c

#include "dac.h"

DAC_HandleTypeDef    DacHandle;
//DAC句柄结构变量声明
static DAC_ChannelConfTypeDef sConfig;
//DAC配置常规通道结构变量声明

void Stm32DAC_Init(void)
//DA转化器初始化
{
	GPIO_InitTypeDef   GPIO_InitStruct;
    //GIPIO初始化结构变量声明

	__HAL_RCC_GPIOA_CLK_ENABLE();
	//使能DAC输出端口时钟
	__DAC_CLK_ENABLE();
    //使能DAC时钟
	
	//PA4配置为DAC输出
	GPIO_InitStruct.Pin = DACx_CHANNEL_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
	//模拟模式
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	//DAC转换器配置
	DacHandle.Instance = DAC;
	HAL_DAC_Init(&DacHandle);

    //DAC通道配置
	sConfig.DAC_Trigger = DAC_TRIGGER_NONE;  
	//不使用通道触发器            
	sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE;
	//DAC输出缓冲器禁止

	HAL_DAC_ConfigChannel(&DacHandle, &sConfig, DACx_CHANNEL);
	//配置选定DAC通道
	HAL_DAC_SetValue(&DacHandle, DACx_CHANNEL, DAC_ALIGN_12B_R, 0x00);  
	//12位右对齐,初始值为0
	
	HAL_DAC_Start(&DacHandle, DACx_CHANNEL);  
	//启动DAC
}


//启动DAC值
void DAC_SetVal(uint32_t Data)
{
	HAL_DAC_SetValue(&DacHandle, DACx_CHANNEL, DAC_ALIGN_12B_R, Data);
}


//DAC转换生成电压(0~3.3V)
//vol:0~3300,电压放大1000倍
void DAC_SetVoltage(uint32_t vol)
{
	uint32_t val;
	
	val = vol * 4096 / 3300;
	
	DAC_SetVal(val);
}


//三角波生成
void DAC_TriangleConfig(void)
{	
	//DAC转换器配置
	DacHandle.Instance = DAC;
	HAL_DAC_Init(&DacHandle);

	//DAC通道配置
	sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO; 
	//定时器6触发        
	sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
	//DAC输出缓冲器使能
	HAL_DAC_ConfigChannel(&DacHandle, &sConfig, DACx_CHANNEL);
	//配置选定DAC通道
	
	HAL_DACEx_TriangleWaveGenerate(&DacHandle, DACx_CHANNEL, DAC_TRIANGLEAMPLITUDE_1023);
	//配置三角波生成,最大转换值1023

	
	HAL_DAC_Start(&DacHandle, DACx_CHANNEL);
    //启动DAC
	
	HAL_DAC_SetValue(&DacHandle, DACx_CHANNEL, DAC_ALIGN_12B_R, 0x100);
	//12位右对齐,初始值为0x100
}


void DAC_NoiseWaveConfig(void)
//噪声波生成
{	
	//DAC转换器配置
	DacHandle.Instance = DAC;
	HAL_DAC_Init(&DacHandle);

	//DAC通道配置
	sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;    
	//定时器6触发     
	sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; 
	//DAC输出缓冲器使能
	HAL_DAC_ConfigChannel(&DacHandle, &sConfig, DACx_CHANNEL);
	//DAC通道配置
	

	HAL_DACEx_NoiseWaveGenerate(&DacHandle, DACx_CHANNEL, DAC_TRIANGLEAMPLITUDE_1023);
    //配置噪声波生成,最大转换值1023
	
	HAL_DAC_Start(&DacHandle, DACx_CHANNEL);
    //启动DAC
	
	HAL_DAC_SetValue(&DacHandle, DACx_CHANNEL, DAC_ALIGN_12B_R, 0x100);
	//12位右对齐,初始值为0x100
}


void DAC_EscalatorConfig(uint32_t *data, uint32_t len)
//自定义波形生成,需要开启DMA
{
    //DAC转换器配置
	DacHandle.Instance = DAC;
	HAL_DAC_Init(&DacHandle);
	
	//DAC通道配置
	sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO; 
	//定时器6触发        
	sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
	//DAC输出缓冲器使能
	HAL_DAC_ConfigChannel(&DacHandle, &sConfig, DACx_CHANNEL);
    //DAC通道配置
	
	HAL_DAC_Start_DMA(&DacHandle, DACx_CHANNEL, (uint32_t *)data, len, DAC_ALIGN_8B_R);
	//启动DMA
}


void TIM6_Config(uint32_t Period)
//定时器6配置,用于触发DAC转换
{
	static TIM_HandleTypeDef  htim;
	//TIM句柄结构变量声明
	TIM_MasterConfigTypeDef sMasterConfig;
	//主配置结构变量声明
	uint32_t uwPrescalerValue = 0;
	

	uwPrescalerValue = (uint32_t) ((SystemCoreClock) / 1000000) - 1;  
	//1us计数的分频系统
	
	__HAL_RCC_TIM6_CLK_ENABLE();
	//开启定时钟

	
	htim.Instance = TIM6;
	//配置定时器6

	htim.Init.Period            = Period;
	//自动重装值
	htim.Init.Prescaler         = uwPrescalerValue;
	//设置计数频率为0.1ms计一次数
	htim.Init.ClockDivision     = 0;
	//时钟不分频,来自RCC
	htim.Init.CounterMode       = TIM_COUNTERMODE_UP;
	//递增计数
	htim.Init.RepetitionCounter = 0;
	//指定重复计数值
	HAL_TIM_Base_Init(&htim);
    //初始化定时器参数
	
	sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
	
	sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
	//从模式禁止
	
	HAL_TIMEx_MasterConfigSynchronization(&htim, &sMasterConfig);
    //在主模式下配置TIME。
    
	//启动定时器
	HAL_TIM_Base_Start(&htim);
}


void DAC_ConvertFreqConfig(uint32_t Freq)
//DAC转换频率设置,利用定时器触发
//DAC转换频率,即多久转换一次,但位HZ
{
	TIM6_Config(1000000/Freq - 1);
}

//在HAL_DAC_Init中调用
void HAL_DAC_MspInit(DAC_HandleTypeDef *hdac)
{
	GPIO_InitTypeDef          GPIO_InitStruct;
	//GPIO句柄结构变量声明
	static DMA_HandleTypeDef  hdma_dac1;
	//DMA基础结构变量声明

	
	__HAL_RCC_GPIOA_CLK_ENABLE();
	//使能DAC输出端口时钟
	__DAC_CLK_ENABLE();
    //使能DAC时钟
	
	//PA4配置为DAC输出
	GPIO_InitStruct.Pin = DACx_CHANNEL_PIN;
	GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	#ifdef DAC_USE_DMA
	//配置DMA1
	//使能DMA时钟
	__HAL_RCC_DMA1_CLK_ENABLE();
	
	hdma_dac1.Instance = DACx_DMA_INSTANCE;

	hdma_dac1.Init.Direction = DMA_MEMORY_TO_PERIPH;
	hdma_dac1.Init.PeriphInc = DMA_PINC_DISABLE;
	hdma_dac1.Init.MemInc = DMA_MINC_ENABLE;
	hdma_dac1.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;   
	//DAC播放音频可以字节传输,也可以半字传输
	hdma_dac1.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
//	hdma_dac1.Init.PeriphDataAlignment = DMA_MDATAALIGN_HALFWORD;
//	hdma_dac1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
	
//	hdma_dac1.Init.Mode = DMA_CIRCULAR;
	hdma_dac1.Init.Mode = DMA_NORMAL;
	hdma_dac1.Init.Priority = DMA_PRIORITY_HIGH;

	HAL_DMA_Init(&hdma_dac1);

    //初始化DMA句柄为DAC
	__HAL_LINKDMA(hdac, DMA_Handle1, hdma_dac1);

    //配置NVIC
	HAL_NVIC_SetPriority(DACx_DMA_IRQn, 3, 0);
	HAL_NVIC_EnableIRQ(DACx_DMA_IRQn);
	
	#endif
}



void HAL_DAC_ConvHalfCpltCallbackCh1(DAC_HandleTypeDef* hdac)
//DAC通道1 DMA数据流一半转换完成回调,在DAC_DMAHalfConvCpltCh1中调用
{
	
}


void HAL_DAC_ErrorCallbackCh1(DAC_HandleTypeDef *hdac)
//DAC通道1 DMA转换错误回调,在DAC_DMAErrorCh1中调用
{
	
}


void DAC_DMA_Init(void)
{	
	//DAC转换器配置
	DacHandle.Instance = DAC;
	HAL_DAC_Init(&DacHandle);
     
	
	//DAC通道配置
	//语音播放需要修改定时器6的触发频率和音频文件
	sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO; 
	//定时器6触发        
	sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; 
	//DAC输出缓冲器
	HAL_DAC_ConfigChannel(&DacHandle, &sConfig, DACx_CHANNEL);
	//DAC通道配置
}

//DMA中断
void DACx_DMA_IRQHandler(void)
{
	HAL_DMA_IRQHandler(DacHandle.DMA_Handle1);
}


void DAC_DMA_Start(uint32_t* pData, uint32_t Length)
//DAC DMA功能启动,播放音频要注意,采用8位对齐或12位左对齐
{
	HAL_DAC_Start_DMA(&DacHandle,DACx_CHANNEL, pData, Length, DAC_ALIGN_8B_R);
}


void DAC_DMA_Stop(void)
//DAC DMA功能禁止
{
	HAL_DAC_Stop_DMA(&DacHandle,DACx_CHANNEL);
	//终止DMA传输,DAC
}

void DAC_TriangleInit(void)
//三角波生成初始化
{
	DAC_ConvertFreqConfig(1000); 
	//数据转换频率1KHz
	DAC_TriangleConfig();
}

void DAC_NoiseWaveInit(void)
//噪声波生成初始化
{
	DAC_ConvertFreqConfig(1000);  
	//数据转换频率1KHz
	DAC_NoiseWaveConfig();
}


  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值