STM32 HAL库 STM32CubeMX -- DAC


一、DAC 简介

DAC(Digital-to-Analog Converter),即为数字/模拟转换模块,又称D/A转换器;

作用就是把输入的数字编码,转换成对应的模拟电压输出,它的功能与ADC 相反。即为输出波形和输出固定电压
例如:将一定比例电压值的数字信号转换为模拟信号。

在常见的数字信号系统中,大部分传感器信号被化成电压信号,而ADC 把电压模拟信号转换成易于计算机存储、处理的数字编码,由计算机处理完成后,再由DAC 输出电压模拟信号,该电压模拟信号常常用来驱动某些执行器件,使人类易于感知。

STM32 具有片上DAC 外设,它的分辨率可配置为8 位或12 位的数字输入信号,具有两个DAC输出通道,这两个通道互不影响,每个通道都可以使用DMA 功能,都具有出错检测能力,可外部触发
在双DAC模式下,2个通道可以独立地进行转换,也可以同时进行转换并同步地更新2个通道的输出。DAC可以通过引脚输入参考电压VREF+ 以获得更精确的转换结果。

DAC工作在12位模式时,数据可以设置成左对齐或右对齐

二、DAC的功能框图

DAC
整个DAC 模块围绕框图下方的“数字至模拟转换器x”展开,它的左边分别是参考电源的引脚:VDDA、VSSA 及Vref+,其中STM32 的DAC 规定了它的参考电压Vref+ 输入范围为2.4——3.3V。

“数字至模拟转换器x”的输入为DAC 的数据寄存器“DORx”的数字编码,经过它转换得的模拟信号由图中右侧的“DAC_OUTx”输出。而数据寄存器“DORx”又受“控制逻辑”支配,它可以控制数据寄存器加入一些伪噪声信号或配置产生三角波信号。

图中的左上角为DAC 的触发源,DAC根据触发源的信号来进行DAC 转换,其作用就相当于DAC 转换器的开关,它可以配置的触发源为外部中断源触发、定时器触发或软件控制触发。

参考电压

与ADC 外设类似,DAC 也使用VREF+ 引脚作为参考电压,在设计原理图的时候一般把VSSA 接地,把VREF+ 和VDDA 接3.3V,可得到DAC 的输出电压范围为:0~3.3V。

如果想让输出的电压范围变宽,可以在外部加一个电压调理电路,把0~3.3V 的DAC 输出抬升到特定的范围即可。

数模转换及输出通道

框图中的“数字至模拟转换器x”是核心部件,整个DAC 外设都围绕它而展开。它以左边的VREF+作为参考电源,以DAC 的数据寄存器“DORx”的数字编码作为输入,经过它转换得的模拟信号由右侧的“DAC_OUTx”通道输出。

其中各个部件中的“x”是指设备的标号,在STM32 中具有2 个这样的DAC 部件,每个DAC 有1 个对应的输出通道连接到特定的引脚,即:PA4-通道1,
PA5-通道2,为避免干扰,使用DAC 功能时,DAC 通道引脚需要被配置成模拟输入功能(AIN)。

触发源及DHRx 寄存器

在使用DAC 时,不能直接对上述DORx 寄存器写入数据,任何输出到DAC 通道x 的数据都必须写入到DHRx 寄存器中(其中包含DHR8Rx、DHR12Lx 等,根据数据对齐方向和分辨率的情况写入到对应的寄存器中)。

数据被写入到DHRx 寄存器后,DAC 会根据触发配置进行处理,若使用硬件触发,则DHRx 中的数据会在3 个APB1 时钟周期后传输至DORx,DORx 随之输出相应的模拟电压到输出通道;

若DAC 设置为外部事件触发,可以使用定时器(TIMx_TRGO)、EXTI_9 信号或软件触发(SWTRIGx)这几种方式控制数据DAC 转换的时机,例如使用定时器触发,配合不同时刻的DHRx 数据,可实现DAC 输出正弦波的功能。

三、STM32Cube MX配置

基础STM32Cube MX的配置可以参考这篇博客:STM32 CubeMx教程 – 基础知识及配置使用教程

这里讲一下DAC的一些通用配置介绍,具体使用在第四部分

配置RCC,使用外部晶振模式

RCC

配置SYS,debug模式选择使用Serial Wire

SYS

配置DAC,

DAC

OUT1 Configuration:使能DAC通道1输出
OUT2 Configuration:使能DAC通道2输出
External Trigger 外部中断EXTI9 触发
(使用外部中断来触发ADC)

Output Buffer:输出缓存
Enable:使能输出缓存,DAC的输出阻抗会降低,无需外部运放即可直接驱动外部负载。但是输出的电压没法低于20mv。如果不需要输出小于20mv的信号,一般开启输出缓存。
Disable:不使能输出缓存,那么DAC可以输出低于20mv的信号。

Trigger:触发源选择。

trigger

Wave generation mode(波形生成模式) :
可以选择三角波发生器(Triangle wave generation)和噪声波形(noise wave generation)

Maximum Triangle Amplitude(最大三角波幅) :
DAC12位数据存储,最大为4095
0-4095 对应 0V~3.3V

配置时钟树

时钟树

四、代码详解


HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef* hdac, uint32_t Channel);     //开启DAC输出
//	参数1:DAC结构体名字 ;参数2:DAC所用的通道
示例:HAL_DAC_Start(&hdac,DAC_CHANNEL_1);


HAL_StatusTypeDef HAL_DAC_Stop(DAC_HandleTypeDef* hdac, uint32_t Channel);   //关闭DAC输出
//	参数1:DAC结构体名字 ;参数2:DAC所用的通道
示例:HAL_DAC_Stop(&hdac,DAC_CHANNEL_1);


HAL_StatusTypeDef HAL_DAC_Start_DMA(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t* pData, uint32_t Length, uint32_t Alignment);  //开启DAC的DMA输出
// 参数1:DAC结构体名字;参数2:DAC所用的通道;参数3:数据的地址;参数4:数据的个数;参数5:数据的对齐方式  需要函数中不断开启
示例:HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t *)SineWaveTable, POINTS, DAC_ALIGN_12B_R);


HAL_StatusTypeDef HAL_DAC_Stop_DMA(DAC_HandleTypeDef* hdac, uint32_t Channel); //关闭DAC的DMA输出
// 参数1:DAC结构体名字;参数2:DAC所用的通道;
示例:HAL_DAC_Stop_DMA(&hdac, DAC_CHANNEL_1);


HAL_StatusTypeDef HAL_DAC_SetValue(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data);  //设置DAC输出值
// 参数1:DAC结构体名字;参数2:DAC所用的通道;参数3:DAC对齐方式;参数4:设置的电压数值 0 ~ 4095
示例:HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 2048);


uint32_t HAL_DAC_GetValue(DAC_HandleTypeDef* hdac, uint32_t Channel);  //获取DAC输出值
// 参数1:DAC结构体名字;参数2:DAC所用的通道;
示例:HAL_DAC_GetValue(&hdac, DAC_CHANNEL_1);

在这里举三个DAC例子:
(1)输出额定电压
(2)输出三角波 + 定时器
(3)输出正弦波 + DMA + 定时器

输出额定电压

由于只是用来输出一定的额定电压,所以打开DAC就行,不用配置

DAC

	/* 在main 函数里面初始化 */
	/* 输出一定的额定电压 */
	HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 4095);  //输出数据为右对齐12位,电压为3.3
	HAL_DAC_Start(&hdac,DAC_CHANNEL_1);			//打开DAC(1)

输出三角波

配置TIM;
使用内部时钟源;
设置预分频系数、重装载值、自动重装载;
设置为Update Event

TIM

配置DAC;
使用通道1;
使用定时器2触发;
触发产生三角波;
峰值为2047,取值范围0 ~ 4095 对应 0 ~ 3.3

DAC

  /* USER CODE BEGIN 2 */
	/* 在main 函数里面初始化 */
	/* 输出三角波 */
	HAL_TIM_Base_Start(&htim2);			//开启定时器2
  HAL_DAC_Start(&hdac, DAC_CHANNEL_1);		//打开DAC(1)
  /* USER CODE END 2 */

输出正弦波 + DMA + TIM

配置TIM;
使用内部时钟源;
设置预分频系数、重装载值、自动重装载;
设置为Update Event

TIM

配置DAC;
配置使用定时器2触发;
由于产生正弦波,所以不使用波形产生器;

DAC
配置DAC的DMA模式;
使用循环模式;

DAC DMA

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#include "math.h"
#define POINTS 2048
uint16_t SineWaveTable[POINTS] = {0};
/* USER CODE END PD */
  /* USER CODE BEGIN 2 */
	/* 在main 函数里面初始化 */
	/* 输出正弦波 */
	 HAL_TIM_Base_Start(&htim2);			//开启定时器
	 HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_2, (uint32_t *)SineWaveTable, POINTS, DAC_ALIGN_12B_R);  //产生正弦波
	
  /* USER CODE END 2 */
/* USER CODE BEGIN 4 */
/**
 * 生成正弦波数据点函数
 * @param NPoints       一个周期内的点数
 * @param VMaxRange     输出的电压最大值,取值范围0~3.3V
 * @param SineWaveTable 存放生成的数据点
 */
void SineWaveGen(uint32_t NPoints, float VMaxRange, uint16_t* SineWaveTable)
{
#ifndef PI
#define PI 3.14159265358979323846
#endif

	int    i       = 0;
	double radian  = 0;  // 弧度
	double setup   = 0;  // 弧度和弧度之间的大小
	double voltage = 0;  // 输出电压

	setup = (2 * PI) / NPoints;  // 两点之间的间距

	while (i < NPoints)
	{
		voltage = VMaxRange / 2.0 * (sin(radian) + 1.0);              // 计算电压
		SineWaveTable[i] = (uint16_t)(voltage * 4096 / 3.3);          // 电压转为DAC数值
		radian += setup;                                              // 下一个点的弧度
		i++;
	}
}

/* USER CODE END 4 */

附录

本文涉及的代码:STM32 HAL库 DAC例程(设置的0积分,如果无法下载,留言我发给你)

  • 8
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值