STM32f429 DAC的结构、功能及应用

发布时间:2024-04-01  

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]);

}

}

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


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    器读指令。 芯片实物图片芯片引脚功能 4、可编程输入/输出引脚(32根) AT89S51单片机有4组8位的可编程I/O口,分别位P0、P1、P2、P3口,每个口有8位(8根引脚),共32根。每一根引脚......
    、德国益驰CAN通信一致性测试、德国C&S兼容性测试。相比第一代基础SIT1040Q和第二代CAN FD SIT1042Q CAN收发器,此芯片引脚更多功能更全。SIT1043Q在实现基本CAN......
    和1mA。该器件通过I2C总线接口进行操作,这里就不再对IIC做详细介绍了,具体可见外设系列OLED篇。 二、AT24C02引脚 AT24C02引脚定义 三、AT24C02寻址 使能芯片......
    。         芯片引脚功能 在设计STM32系统时,我们需要根据芯片数据手册来确认需要使用的引脚,例如我们需要外接低速外部晶振时,我们需要在芯片手册上找到外接晶振引脚。本文......
    (见前面的引脚功能图)是以GPIO0_x的形式来描述的,即GPIO0_x是固定不动的。以GPIO0_13端口为例,它在HVQFN33的封装中位于芯片第1号引脚上,这是固定不变的,即不......
    单片机外部结构的引脚功能的简介和使用资料概述;一、教学目的:掌握单片机的引脚功能 二、教学重点:单片机的P0、P1、P2、P3口的使用和区别 三、教学步骤: (1) 单片机(AT89S51)外观......
    苾片的结构和引脚功能。MSC51架构的芯片种类很多,具体特点和功能不尽相同(在以后编写的附录中会加入常用的一些51芯片的资料列表),在此后的教程中就以Atmel公司的AT89C51和AT89C2051......
    手册在我们光盘“6--芯片资料开发板芯片数据手册”内,里面有一个STC89CXX 数据手册.pdf。里面的第23 页中就有介绍,我们截取了一部分内容如下图所示: 从上图中我们可以获取引脚的名字和引脚功能......
    改善,也是近16个月来首次实现同比增长。其中,多芯片封装的存储芯片引领出口反弹,同比增长12.2%,DRAM芯片......
    、PSRAM,还是NOR Flash; ②存储芯片的地址和数据引脚是否复用(MUXEN),FSMC可以直接与AD0~AD15复用的存储器相连,不需要增加外部器件; ③存储芯片的数据线宽度(MWID......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>