STM32f429 DAC的结构、功能及应用

发布者:BlissfulAura最新更新时间:2024-04-01 来源: elecfans关键字:STM32f429  DAC 手机看文章 扫描二维码
随时随地手机看文章

13.1 介绍一下

数字量转换成模拟量的过程叫做数模转换,完成这种功能的电路叫做数模转换器。说白了就是将离散的数字信号转换为连续变量的模拟信号的一种器件。


这玩意主要由数字寄存器、模拟电子开关、位权网络、求和运算放大器基准电压源(或恒流源)等组成的。主要用存于数字寄存器的数字量的各位数码,分别控制对应位的模拟电子开关,使数码为1的位在位权网络上产生与其位权成正比的电流值,再由运算放大器对各电流值求和,并转换成电压值 。


换成图也就是下面这个小东西:

在这里插入图片描述

13.2 STM32f429 DAC结构

STM32F429内部含有两个12 位电压输出数模转换器。DAC 可以按 8 位或 12 位模式进行配置,而且也是可以和DMA配合使用的,在12位模式中,数据可以是左对齐也可以是右对齐。

DAC 有两个输出通道,每个通道各有一个转换器。

两个 DAC 转换器:各对应一个输出通道:

12 位模式下数据采用左对齐或右对齐

生成噪声波、生成三角波

DAC 双通道单独或同时转换

每个通道都具有 DMA 功能

通过外部触发信号进行转换

DAC 各个引脚功能定义:

13.3 STM32f429 DAC功能

1、DAC 转换

两个DAC分别对应一个独立的通道,当使用时需要将 DAC_CR 寄存器中的相应 ENx 位置 1,即可使能对应 DAC 通道。

在使能DAC通道之后,可以通过写DAC_DHRx 寄存器或通过触发信号来启动一次DAC转换。

(1)写DAC_DHRx 寄存器启动DAC转换

如果未选择硬件触发(DAC CR中的TENx位复位),那么经过一个APB1时钟周期后,DAC_DHRx中存储的数据将自动转移到DAC_DORx。当DAC_DORx加载了DAC_DHRx内容时,模拟输出电压将在一段时间t_SETTING后可用,具体时间取决于电源电压和模拟输出负载。

DAC_DORx 无法直接写入,任何数据都必须通过加载DAC_DHRx 寄存器才能传输到 DAC 通道x。

DAC转换过程

(2)硬件触发启动DAC转换

如果选择硬件触发(置位 DAC_CR 寄存器中的 TENx 位)可通过外部事件(定时计数器、外部中断线)触发转换。

当触发条件到来,将在三个APB1时钟周期后,将DAC_DHRx 寄存器的内容转移到DAC_DORx寄存器。

DAC外部触发源:

DAC外部触发源

2、DAC 数据格式

1)对于 DAC 单通道 x,有三种可能的方式:

8位右对齐:软件必须将数据加载到 DAC_DHR8Rx [7:0] 位(存储到DHRx[11:4] 位)。

12位左对齐:软件必须将数据加载到 DAC_DHR12Lx [15:4] 位(存储到DHRx[11:0] 位)。

12 位右对齐:软件必须将数据加载到 DAC_DHR12Rx [11:0] 位(存储到DHRx[11:0] 位)。

DAC单通道数据对齐方式(下图):

2)对于 DAC双通道 x,有三种可能的方式:

8 位右对齐:将 DAC 1 通道的数据加载到 DAC_DHR8RD [7:0] 位(存储到DHR1[11:4] 位),将 DAC 2 通道的数据加载到 DAC_DHR8RD [15:8] 位(存储到 DHR2[11:4] 位)

12 位左对齐:将 DAC 1 通道的数据加载到 DAC_DHR12RD [15:4] 位(存储到 DHR1[11:0] 位),将 DAC 2 通道的数据加载到 DAC_DHR12RD [31:20] 位(存储到 DHR2[11:0] 位)

12 位右对齐:将 DAC 1 通道的数据加载到 DAC_DHR12RD [11:0] 位(存储到 DHR1[11:0] 位),将 DAC 2 通道的数据加载到 DAC_DHR12RD [27:16] 位(存储到 DHR2[11:0] 位)

3、DMA 请求

每个 DAC 通道都具有 DMA 功能。两个 DMA 通道用于处理 DAC 通道的 DMA 请求。

4、生成噪声

将 WAVEx[1:0] 置为 “01”即可选择生成噪声,使用 LFSR(线性反馈移位寄存器)可以生成可变振幅的伪噪声。

LFSR中的预加载值为0xAAA。

5、生成三角波

将 WAVEx[1:0] 置为“10”即可选择 DAC 生成三角波。

6、DAC 双通道转换

DAC控制器有三个双寄存器:DHR8RD、DHR12RD 和 DHR12LD,可以访问一个寄存器同时驱动两个 DAC 通道,从而有效利用两个 DAC 通道总线带宽。通过两个DAC 通道和这三个双寄存器可以实现 11 种转换模式:

独立触发(不产生波形)

独立触发(生成单个 LFSR)

独立触发(生成不同 LFSR)

独立触发(生成单个三角波)

独立触发(生成不同三角波)

同步软件启动

同步触发(不产生波形)

同步触发(生成单个 LFSR)

同步触发(生成不同 LFSR)

同步触发(生成单个三角波)

同步触发(生成不同三角波)

13.4 DAC典型应用步骤

1、使能DAC时钟:

开启PA口时钟和ADC1时钟,设置PA1为模拟输入。

RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);

使能模拟信号输入GPIO时钟,假设是GPIOA,根据实际情况调整:

RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE);

2、初始化模拟信号输入的GPIO引脚为模拟方式:

GPIO_Init();

3、初始化DAC通道参数。

void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct) ;

4、使能DAC通道

void DAC_Cmd(uint32_t DAC_Channel, FunctionalState NewState);

5、启动DAC转换

(1)通过写DAC_DHRx 寄存器启动DAC转换:

void DAC_SetChannel1Data(uint32_t DAC_Align, uint16_t Data) ;

或void DAC_SetChannel2Data(uint32_t DAC_Align, uint16_t Data) ;

或void DAC_SetDualChannelData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1) ;

或者通过触发信号启动DAC转换

13.5 常用库函数

DAC相关的函数和宏都被定义在两个文件中:

头文件:stm32f4xx_dac.h

源文件:stm32f4xx_dac.c

1、DAC初始化函数

void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct);

参数1:uint32_t DAC_Channel,是DAC通道宏定义,定义在stm32f4xx_dac.h中:

#define DAC_Channel_1 ((uint32_t)0x00000000) //通道1

#define DAC_Channel_2 ((uint32_t)0x00000010) //通道2

参数2:DAC_InitTypeDef* DAC_InitStruct,是DAC初始化结构体指针,自定义的结构体定义在stm32f4xx_dac.h中:

typedef struct

{

uint32_t DAC_Trigger; //设置触发方式

uint32_t DAC_WaveGeneration; // 设置波形生成

uint32_t DAC_LFSRUnmask_TriangleAmplitude; //设置LFSR掩码值或三角波最大振幅

uint32_t DAC_OutputBuffer; //设置输出缓冲器

}DAC_InitTypeDef;

例如:

DAC_InitTypeDef DAC_InitStructure;

DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;//不使用触发方式,软件启动转换

DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; //不使用波形发生器

DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; //不使用DAC输出缓冲

DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽幅值

DAC_Init(DAC_Channel_1, &DAC_InitStructure);

2、DAC使能函数

void DAC_Cmd(uint32_t DAC_Channel, FunctionalState NewState);

参数1:uint32_t DAC_Channel,DAC通道宏定义。

参数2:FunctionalState

NewState,使能或禁止ADC,定义如下:

ENABLE:使能ADC;

DISABLE:禁止ADC。

3、单通道输出,写DAC通道1输出数据寄存器函数

void DAC_SetChannel1Data(uint32_t DAC_Align, uint16_t Data) ;

参数1:uint32_t DAC_Align, DAC数据对齐方式,定义如下:

#define DAC_Align_12b_R ((uint32_t)0x00000000)//12位右对齐形式

#define DAC_Align_12b_L ((uint32_t)0x00000004) //12位左对齐形式

#define DAC_Align_8b_R ((uint32_t)0x00000008) //8位右对齐形式

参数2:uint16_t Data,DAC输出的数据。

4、单通道输出,写DAC通道2输出数据寄存器函数

void DAC_SetChannel1Data(uint32_t DAC_Align, uint16_t Data) ;

void DAC_Cmd(uint32_t DAC_Channel, FunctionalState NewState);

5、双通道输出,写DAC输出数据寄存器函数

void DAC_SetDualChannelData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1) ;

参数1:同单通道输出定义形式。

参数2和参数3:DAC通道2和DAC通道1输出数据。

6、DAC软件触发函数

void DAC_SoftwareTriggerCmd(uint32_t DAC_Channel, FunctionalState NewState)

参数1:uint32_t DAC_Channel,DAC通道宏定义。

参数2:FunctionalState NewState,使能或禁止ADC。

13.6 应用

使用DAC通道1生成一个频率为1KHz的正弦波。

使用定时器T2,在每次定时溢出中断中采样数组数据,并写入DAC_DHRx,定时溢出频率为20KHz。

DAC使用单通道模式,输出不使用触发,使能输出缓冲功能。在每次将数据写入DAC_DHRx后,经过一个APB1 时钟周期,DAC_DHRx 寄存器中存储的数据将自动转移到DAC_DORx,经输出缓冲器,在PA4引脚上产生对应输出电压。

1、编程要点

(1)、使能DAC和复用引脚GPIO的工作时钟。

(2)、初始化DAC通道1相关GPIO引脚为模拟方式。

(3)、根据要求,初始化ADC1。

(4)、初始化定时器

(5)、使能DAC。

(6)、在定时器一处中断中写DAC_DHRx。

2、DAC初始化功能

#include //因为要使用sin函数生成正弦表,需要包含math.h头文件

#define Pi 3.1415926

#define f 1000//正弦波频率 1KHz

#define fs 20000//采样频率 20KHz

uint16_t Sine_Table[20];

void DAC_Config (void)

{

uint16_t i = 0;

/* 生成正弦波形数据,右对齐*/

for (i = 0; i < 20; i++)

{

Sine_Table [i] = (uint16_t )((float)4095*(1+sin(2iPi* f /fs))/2);

}

DAC_Mode_Init ();//配置DAC功能

TIM_Config();//配置定时器功能

}

3、DAC配置程序

static void DAC_Mode_Config(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

DAC_InitTypeDef DAC_InitStructure;

/ -------------------第1步-------------------- /

/* 使能GPIOA时钟 */

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

/* 使能DAC时钟 */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);

/ -------------------第2步-------------------- /

/* DAC的GPIO配置,模拟 */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_Init(GPIOA, &GPIO_InitStructure);

/ -------------------第3步-------------------- /

/* 配置DAC 通道1 */

DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;//不使用触发

DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; //不使用波形发生器

DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; //使用DAC输出缓冲

DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0; //屏蔽幅值 设置

DAC_Init(DAC_Channel_1, &DAC_InitStructure);

/ -------------------第4步-------------------- /

/* 使能通道1 由PA4输出 */

DAC_Cmd(DAC_Channel_1, ENABLE);

}

4、定时器配置程序

static void TIM_Config(void)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

NVIC_InitTypeDef NVIC_InitStructure;

/* 使能TIM2时钟,TIM2CLK 为90M */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

/* TIM2基本定时器配置 */

// TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

TIM_TimeBaseStructure.TIM_Period = 4500-1; //采样频率 = 20KHz

TIM_TimeBaseStructure.TIM_Prescaler = 0x0; //预分频,不分频 90M / (0+1) = 90M

TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; //时钟分频系数

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

/* 配置TIM2中断 */

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;

NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

NVIC_Init(&NVIC_InitStructure);

TIM_ITConfig(TIM2, TIM_IT_Update,ENABLE);

/* 使能TIM2 */

TIM_Cmd(TIM2, ENABLE);

}

5、定时器中断服务程序

void TIM2_IRQHandler(void)

{

static u16 Index;

if(TIM_GetITStatus(TIM2, TIM_IT_Update)==SET)

{

TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

if(Index <19)//采样边界控制

Index ++;

else

Index =0;

//写DAC通道1的12位右对齐数据寄存器,从而启动一次DAC转换

DAC_SetChannel1Data(DAC_Align_12b_R, Sine_Table [Index]);

}

}

具体的可以参考其他官方或个人优秀的代码。


关键字:STM32f429  DAC 引用地址:STM32f429 DAC的结构、功能及应用

上一篇:STM32入门学习笔记之SysTick时钟
下一篇:STM32嵌入式开发中的RTOS应用分析

推荐阅读最新更新时间:2026-03-25 10:56

STM32F429定时器4生成PWM,转化为DAC
STM32F429时钟树 原文地址 定时器PWM 从STM32F4的内部时钟树可知, (1)高级定时器timer1, timer8以及通用定时器timer9, timer10, timer11的时钟来源是APB2总线 (2)通用定时器timer2-timer5,通用定时器timer12-timer14以及基本定时器timer6,timer7的时钟来源是APB1总线 (3)当APB1和APB2分频数为1的时候,TIM1、TIM8-TIM11的时钟为APB2的时钟,TIM2-TIM7、TIM12-TIM14的时钟为APB1的时钟; (4)而如果APB1和APB2分频数不为1,那么TIM1、TIM8-TIM11的时钟为APB2的时钟
[单片机]
第1章 初学STM32F429的准备工作
1.1 初学者重要提示 关于学习方法问题,可以看附件章节A。 学会 STM32F429相关资源的获取方法,做到心中有数,否则心里老是没底。 关于MDK和IAR两种编译器,推荐都掌握,以其中一个为主,另一个为辅。因为很多时候我们需要参考的工程代码不是自己熟悉的编译器,就会很被动。 这几年涌现出好几款非常棒的调试工具(如Event Recoder,SEGGER RTT),教程的后面章节会为大家做讲解。 1.2 开发环境说明 1、 IDE:支持两种IDE开发环境,MDK和IAR MDK推荐使用MDK5.26正式版及其以上版本。 IAR固定使用IAR8.3版本,由于IAR向下兼容性稍差,其它版本未做支持。 2
[单片机]
第1章 初学<font color='red'>STM32F429</font>的准备工作
第6章 STM32F429工程模板建立(IAR8)
6.1 初学者重要提示 IAR的工程创建过程还是比较重要的,务必实际上手操作一遍。 6.2 第1步,创建工程文件夹 创建一个文件夹,里面包含如下文件(直接将跑马灯例子的Project文件里面内容全部删除,然后整个工程复制进来即可)。 Doc文件夹 用于记录例程的修改记录和例子简介。 Libraries文件夹 在第一章详细介绍从官网的下载方法。 Project文件夹 这个是本章的重点,在这个文件夹里面再建立两个文件夹,EWARMv8文件夹用于存放IAR工程,MDK-ARM(uV5)文件夹里面用于存放MDK工程,方便以后创建MDK的工程。 User文件夹 这个是要用户提供的,开发板已经都提供好,bsp文件夹里面
[单片机]
第6章 <font color='red'>STM32F429</font>工程模板建立(IAR8)
第21章 STM32F429的NVIC中断分组和配置(重要)
21.1 NVIC基础知识 NVIC的全称是Nested vectored interrupt controller,即嵌套向量中断控制器。 对于M3/M4/M7内核的MCU,每个中断的优先级都是用寄存器中的8位来设置的。8位的话就可以设置2^8 = 256级中断,实际中用不了这么多,所以芯片厂商根据自己生产的芯片做出了调整。比如ST的STM32F1xx,F4xx和H7只使用了这个8位中的高四位 ,低四位取零,这样2^4=16,只能表示16级中断嵌套。 对于这个NVIC,有个重要的知识点就是优先级分组、抢占优先级和子优先级。STM32F1xx,F4xx和H7都是只使用了这个8位寄存器的高四位 。 从上面的表格可以看出
[单片机]
第21章 <font color='red'>STM32F429</font>的NVIC中断分组和配置(重要)
第28章 STM32F429的系统bootloader基础知识
28.1 初学者重要提示 本章主要为大家介绍系统bootloader的理论知识,下个章节为大家实战。 更多系统bootloader的基础知识看本帖的AN2606应用笔记:http://www.armbbs.cn/forum.php?mod=viewthread&tid=96573 28.2 系统bootLoader基础知识 STM32的系统存储区自带bootloader,此程序是ST在芯片出厂时烧录进去的,主要用于将用户应用程序下载到芯片内部Flash。支持USB,SPI,I2C,CAN,UART等接口方式下载。如果大家的应用程序打算采用这种接口方式进行升级,可以考虑采用系统bootloader,简单易用,无需用户自己写b
[单片机]
第28章 <font color='red'>STM32F429</font>的系统bootloader基础知识
第30章 STM32F429的系统bootloader之串口IAP固件升级
30.1 初学者重要提示 学习本章节前,务必优先学习第28章。 本章用到的相关软件和文档下载:http://www.armbbs.cn/forum.php?mod=viewthread&tid=96573 。 本章节的串口IAP下载软件使用STM32CubeProg,此软件实现了之前的DfuSe,STLINK小软件和Flashloader三合一,并且支持外部EEPROM,NOR Flash,SPI Flash,NAND Flash等烧写,也支持OTA编程。 使用系统bootloader做串口IAP升级时,MicroUSB接口不要接线到电脑端,因为这会导致系统bootloader工作在USB DFU模式,无法再使用串口I
[单片机]
第30章 <font color='red'>STM32F429</font>的系统bootloader之串口IAP固件升级
第42章 STM32F429的LTDC应用之点阵字体和字符编码(重要)
42.1 初学者重要提示 本章节讲解的GB2312和GBK比较容易理解,而Unicode是全球统一码,所以涉及到的知识点比较多,也复杂些。 当前Windows系统字符管理已经全部采用Unicode字符集,编码形式是UTF-16 LE (LE表示小端格式)编码。比如我们通过记事本保存的时候选择编码类型Unicode,其实就是选择的UTF-16 LE。而我们平时所说的中文版Windows系统是指用户在选择不支持Unicode的程序中显示文本时所使用的语言。 区分清楚什么是字符,字符集。字符(Character)是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。字符集(Character set)是多个字符的集
[单片机]
第42章 <font color='red'>STM32F429</font>的LTDC应用之点阵字体和字符编码(重要)
STM32F429学习笔记(一)触屏工程Keil建立
由于原来的STM32F103ZET6的flash坏掉了,所以又买了一块STM32F429DISCOVERY,这块板子非常不错,基于Cortex-M4内核,自带一块2.4寸TFT触屏,主频为180M,且内置了ST-Link下载器,使用非常的方便。 近期参加校赛,用它的触屏写了个上位机,当时我是在实验室的电脑和我的平板电脑之间相互拷贝工程,由于ST官方的工程都是公用库文件,所以独立性不强,想要拷贝就得拷贝整个目录,为了解决这个问题,我仔细学习了官方工程的组成与调用,并成功的将所有文件分离出来,建立了一个独立的工程文件夹,以后再拷贝时,只需要将这单个工程拷贝出来,即可方便的移植,其间有不少小插曲,下面就对具体步骤进行详述。
[单片机]
<font color='red'>STM32F429</font>学习笔记(一)触屏工程Keil建立
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved