【STM32】标准库与HAL库对照学习教程十二--DAC数模转换

【STM32】标准库与HAL库对照学习教程十二--DAC数模转换

一、前言

本篇使用的是STM32F1开发板进行DAC实验,本篇内容主要讲解了DAC的原理以及使用,通过标准库与HAL的对照学习,来让您更深入的了解DAC,您可以点击目录跳转到您想看的内容。

二、准备工作

  • STM32F103开发板(我用的是普中的STM32F103ZE开发板)
  • cubemx软件、keil 5(MDK)
  • 万用表

三、DAC介绍

1、DAC简介

DAC(Digital to analog converter)即数字模拟转换器,它可以将数字信号转换为模拟信号。它的功能与ADC相反。

2、STM32F1中的DAC介绍

STM32F1的DAC模块12 位电压输出数模转换器,它可以配置为 8 位或 12 位模式,也可以与DMA 控制器配合使用。

DAC工作在 12 位模式下,数据可以采用左对齐或右对齐。DAC工作在8位模式下,数据只有右对齐方式

DAC 有两个输出通道,每个通道各有一个转换器。在 DAC 双通道模式下,每个通道可以 单独进行转换;也可以同时进行转换

3、STM32F1中的DAC特性

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

四、DAC结构框图

【STM32】标准库与HAL库对照学习教程十二--DAC数模转换

图片来源于STM32F1xx中文参考手册 DAC章节

五、DAC工作解析

由上面的结构图可以对DAC的结构进行依次分析,这部分的图片均来自STM32F1xx中文参考手册 DAC章节

1、电压输入部分

与ADC一样,VDDA与VSSA是DAC模块的供电引脚,而VREF+是DAC模块的参考电压,开发板上已经将VREF+连接到VDDA,VDDA接的是3.3V。所以参考电压范围是0-3.3V
【STM32】标准库与HAL库对照学习教程十二--DAC数模转换

2、DAC转化部分


DAC 输出是受 DORx 寄存器直接控制的,但是我们不能直接往DORx 寄存器写入数据,而是通过 先写入DHRx, 在间接的传递 DORx 寄存器,实现对 DAC 输出的控制

如果未选择硬件触发DAC_CR 寄存器中的 TENx 位复位),那么经过一个 APB1 时钟周期后,DAC_DHRx 寄存器中存储的数据将自动转移到 DAC_DORx 寄存器

如果选择硬件触发置位 DAC_CR 寄存器中的 TENx 位)且触发条件到来,将在三个 APB1 时钟周期后进行转移。
【STM32】标准库与HAL库对照学习教程十二--DAC数模转换
【STM32】标准库与HAL库对照学习教程十二--DAC数模转换
DAC_DORx 加载了 DAC_DHRx 内容时,模拟输出电压将在一段时间后可用,具体时间取决于电源电压模拟输出负载



STM32F1 的 DAC 支持 8/12 位模式8 位模式的时候数据是固定的右对齐的,而 12 位模式数据可以设置左对齐/右对齐。对于DAC单通道 x,总共有 3 种情况

  • 8 位右对齐:用户必须将数据加载到 DAC_DHR8Rx[7:0] 位
  • 12 位左对齐:用户必须将数据加载到 DAC_DHR12Lx[15:4] 位
  • 12 位右对齐:用户必须将数据加载到 DAC_DHR12Rx[11:0] 位
    【STM32】标准库与HAL库对照学习教程十二--DAC数模转换
    【STM32】标准库与HAL库对照学习教程十二--DAC数模转换
    【STM32】标准库与HAL库对照学习教程十二--DAC数模转换


每个 DAC 通道都具有 DMA 功能。两个 DMA 通道用于处理 DAC 通道的 DMA 请求。当 DMAENx 位置 1 时,如果发生外部触发(而不是软件触发),则将产生 DAC DMA 请求。

DAC_DHRx 寄存器的值随后转移到 DAC_DORx 寄存器

在双通道模式下,如果两个 DMAENx 位均置 1,则将产生两个 DMA 请求。如果只需要一个DMA 请求,应仅将相应 DMAENx 位置 1

这样,应用程序可以在双通道模式下通过一个DMA 请求和一个特定 DMA 通道来管理两个 DAC 通道。
【STM32】标准库与HAL库对照学习教程十二--DAC数模转换


3、DAC触发部分

如果DAC控制寄存器(DAC_CR)的TENx 控制位1,可通过外部事件(定时计数器、外部中断线)触发转换TSELx[2:0]控制位将决定通过 8 个可能事件中哪一个来触发转换
【STM32】标准库与HAL库对照学习教程十二--DAC数模转换
【STM32】标准库与HAL库对照学习教程十二--DAC数模转换
如果选择软件触发,一旦SWTRIG位置’1’,转换即开始。在数据从DAC_DHRx寄存器传送到DAC_DORx寄存器后,SWTRIG位由硬件自动清’0’


4、DAC输出部分

DAC_OUTx 就是 DAC 的输出通道DAC1_OUT对应 PA4引脚DAC2_OUT对应 PA5引脚

要让DAC通道正常输出,需将 DAC_CR 寄存器中的ENx 位1
【STM32】标准库与HAL库对照学习教程十二--DAC数模转换
【STM32】标准库与HAL库对照学习教程十二--DAC数模转换
【STM32】标准库与HAL库对照学习教程十二--DAC数模转换
12位模式下输出的电压=3.3*(DOR里的值)/4095

六、标准库配置DAC输出电压

1、配置步骤

(1)使能端口及DAC时钟,设置引脚为模拟输入
(2)初始化DAC,设置DAC工作模式
(3)使能DAC的输出通道
(4)设置DAC的输出值

2、配置工程


(1)复制上一章的工程,并重命名为12、DAC输出电压
【STM32】标准库与HAL库对照学习教程十二--DAC数模转换


(2)进入工程文件,进入APP文件,新建DAC文件夹用来存放与DAC相关的文件。
【STM32】标准库与HAL库对照学习教程十二--DAC数模转换


(3)打开工程,新建文件,并命名为dac.h与dac.c

【STM32】标准库与HAL库对照学习教程十二--DAC数模转换

【STM32】标准库与HAL库对照学习教程十二--DAC数模转换


(4)添加文件到目录,并添加头文件路径

【STM32】标准库与HAL库对照学习教程十二--DAC数模转换

【STM32】标准库与HAL库对照学习教程十二--DAC数模转换


(5)要使用DAC需要添加相应的文件

【STM32】标准库与HAL库对照学习教程十二--DAC数模转换

【STM32】标准库与HAL库对照学习教程十二--DAC数模转换


3、实验程序

main.c

#include "Delay.h"
#include "usart.h"
#include "stdio.h"
#include "dac.h"


/*************************************************
*函数名:    main
*函数功能: 主函数
*输入:     无  
*返回值:   无
**************************************************/
int main()
{
	SysTick_Init(72);
	USART1_Init(9600); 
	DAC1_Vol_Init();  //DAC初始化
	DAC_SoftwareTriggerCmd(DAC_Channel_1, ENABLE);  //软件触发使能
	while(1)
	{
	
	}
}

dac.h

#ifndef DAC_H_
#define DAC_H_

#include "stm32f10x.h"

void DAC1_Vol_Init(void);  //DAC初始化函数


#endif

dac.c

#include "dac.h"



/*************************************************
*函数名:    DAC1_Vol_Init
*函数功能:  DAC1初始化函数
*输入:      无 
*返回值:    无 
**************************************************/
void DAC1_Vol_Init()
{
	GPIO_InitTypeDef GPIO_InitStruct;
	DAC_InitTypeDef DAC_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   //打开引脚时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);   //打开DAC时钟
	
	//引脚初始化
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;    //PA4引脚
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;  //模拟输入模式
	GPIO_Init(GPIOA, &GPIO_InitStruct);  //引脚初始化
	
	//DAC初始化
	DAC_InitStruct.DAC_Trigger = DAC_Trigger_Software;  //选择软件触发
	DAC_InitStruct.DAC_WaveGeneration = DAC_WaveGeneration_None; //不输出波形
	DAC_InitStruct.DAC_OutputBuffer = DAC_OutputBuffer_Disable; //输出缓存失能
	DAC_InitStruct.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095;  //输出最大阈值
	DAC_Init(DAC_Channel_1, &DAC_InitStruct); //DAC初始化

	DAC_Cmd(DAC_Channel_1, ENABLE);  //使能DAC
	
	DAC_SetChannel1Data(DAC_Align_12b_R, 2048); //设置12位右对齐与DHR的值
}

4、实验效果

【STM32】标准库与HAL库对照学习教程十二--DAC数模转换

七、HAL库配置DAC输出电压

1、配置工程


(1) 打开cubemx,新建工程,选择自己的芯片。
【STM32】标准库与HAL库对照学习教程十二--DAC数模转换


(2) 配置RCC,选择外部高速时钟
【STM32】标准库与HAL库对照学习教程十二--DAC数模转换


(3) 配置时钟树
【STM32】标准库与HAL库对照学习教程十二--DAC数模转换


(4) 配置DAC
【STM32】标准库与HAL库对照学习教程十二--DAC数模转换


(5) 工程文件配置并生成工程

【STM32】标准库与HAL库对照学习教程十二--DAC数模转换


【STM32】标准库与HAL库对照学习教程十二--DAC数模转换


2、常用函数

  • HAL_DAC_Start(DAC_HandleTypeDef* hdac, uint32_t Channel); //开启DAC输出。
  • HAL_DAC_Stop(DAC_HandleTypeDef* hdac, uint32_t Channel); //关闭DAC输出
  • HAL_DAC_Start_DMA(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t* pData, uint32_t Length, uint32_t Alignment); //需要函数中不断开启,开启DAC的DMA输出
  • HAL_DAC_Stop_DMA(DAC_HandleTypeDef* hdac, uint32_t Channel); //关闭DAC的DMA输出
  • HAL_DAC_SetValue(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data); //设置DAC输出值
  • HAL_DAC_GetValue(DAC_HandleTypeDef* hdac, uint32_t Channel); //获取DAC输出值

hdac:hdac
Channel:DAC_CHANNEL_1、DAC_CHANNEL_2
pData:输出值
Alignment:对齐方式,DAC_ALIGN_12B_R、DAC_ALIGN_12B_L、DAC_ALIGN_8B_R
Length:数据长度

3、实验程序

【STM32】标准库与HAL库对照学习教程十二--DAC数模转换

HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 1024);  //设置DAC参数
HAL_DAC_Start(&hdac, DAC_CHANNEL_1);  //打开DAC

4、实验效果

【STM32】标准库与HAL库对照学习教程十二--DAC数模转换

上一篇:基于STM32的FALSH读写与DAC功能播放音频


下一篇:瑞奇达CS5210 |Capstone CS5210规格书|低成本HDMI转VGA方案设计