【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结构框图
图片来源于STM32F1xx中文参考手册 DAC章节
五、DAC工作解析
由上面的结构图可以对DAC的结构进行依次分析,这部分的图片均来自STM32F1xx中文参考手册 DAC章节
1、电压输入部分
与ADC一样,VDDA与VSSA是DAC模块的供电引脚,而VREF+是DAC模块的参考电压,开发板上已经将VREF+连接到VDDA,VDDA接的是3.3V。所以参考电压范围是0-3.3V。
2、DAC转化部分
①
DAC 输出是受 DORx 寄存器直接控制的,但是我们不能直接往DORx 寄存器写入数据,而是通过 先写入DHRx, 在间接的传递 DORx 寄存器,实现对 DAC 输出的控制。
如果未选择硬件触发( DAC_CR 寄存器中的 TENx 位复位),那么经过一个 APB1 时钟周期后,DAC_DHRx 寄存器中存储的数据将自动转移到 DAC_DORx 寄存器。
如果选择硬件触发(置位 DAC_CR 寄存器中的 TENx 位)且触发条件到来,将在三个 APB1 时钟周期后进行转移。
当 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] 位。
③
每个 DAC 通道都具有 DMA 功能。两个 DMA 通道用于处理 DAC 通道的 DMA 请求。当 DMAENx 位置 1 时,如果发生外部触发(而不是软件触发),则将产生 DAC DMA 请求。
DAC_DHRx 寄存器的值随后转移到 DAC_DORx 寄存器。
在双通道模式下,如果两个 DMAENx 位均置 1,则将产生两个 DMA 请求。如果只需要一个DMA 请求,应仅将相应 DMAENx 位置 1。
这样,应用程序可以在双通道模式下通过一个DMA 请求和一个特定 DMA 通道来管理两个 DAC 通道。
3、DAC触发部分
如果DAC控制寄存器(DAC_CR)的TENx 控制位置 1,可通过外部事件(定时计数器、外部中断线)触发转换。TSELx[2:0]控制位将决定通过 8 个可能事件中的哪一个来触发转换。
如果选择软件触发,一旦SWTRIG位置’1’,转换即开始。在数据从DAC_DHRx寄存器传送到DAC_DORx寄存器后,SWTRIG位由硬件自动清’0’。
4、DAC输出部分
DAC_OUTx 就是 DAC 的输出通道,DAC1_OUT对应 PA4引脚,DAC2_OUT对应 PA5引脚。
要让DAC通道正常输出,需将 DAC_CR 寄存器中的ENx 位置 1。
12位模式下输出的电压=3.3*(DOR里的值)/4095。
六、标准库配置DAC输出电压
1、配置步骤
(1)使能端口及DAC时钟,设置引脚为模拟输入
(2)初始化DAC,设置DAC工作模式
(3)使能DAC的输出通道
(4)设置DAC的输出值
2、配置工程
(1)复制上一章的工程,并重命名为12、DAC输出电压。
(2)进入工程文件,进入APP文件,新建DAC文件夹用来存放与DAC相关的文件。
(3)打开工程,新建文件,并命名为dac.h与dac.c。
①
②
(4)添加文件到目录,并添加头文件路径。
①
②
(5)要使用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、实验效果
七、HAL库配置DAC输出电压
1、配置工程
(1) 打开cubemx,新建工程,选择自己的芯片。
(2) 配置RCC,选择外部高速时钟。
(3) 配置时钟树。
(4) 配置DAC。
(5) 工程文件配置并生成工程
①
②
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、实验程序
HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 1024); //设置DAC参数
HAL_DAC_Start(&hdac, DAC_CHANNEL_1); //打开DAC