一、数模转换原理
STM32的DAC模块是十二位数字输入,电压输出型的DAC,DAC可以配置为8位或12位模式,也可以与DMA控制器配合使用。DAC工作在12位模式时,数据可以设置成左对齐或者右对齐。DAC模块有2个输出通道,每个通道都有单独的转换器。在双DAC模式下,2个通道可以独立的进行转换,也可以同时进行转换并同步地更新2个通道的输出。DAC也可以通过引脚引入参考电压VREF-以获得更精确的转换结果。
STM32的DAC模块主要特点有:
1、2个DAC转换器:每个转换器对应1个输出通道。
2、8位或者12位单调输出。
3、12位模式下左对齐或者右对齐。
4、同步更新功能。
5、噪声波形生成。
6、三角波形生成。
7、双DAC通道同时或者分别转换。
8、每个通道都有DMA功能。
DAC模块方图:
VDDA和VSSA为DAC模块模拟部分的供电
Vref+则是DAC模块的参考电压
DAC_OUTx就是DAC的输出通道(对应PA4或者PA5引脚)
DAC引脚
DAC_OUT1-->PA4 DAC_OUT2-->PA5
DAC转换
DAC_DORx无法直接写入,任何数据都必须通过加载DAC_DHRx寄存器写入(写入DAC_DHR8Rx、DAC_DHR12Lx、DAC_DHR12Rx、DAC_DHR8RD、DAC_DHR12LD或DAC_DHR12LD)才能传输到DAC通道x。
如果未选择硬件触发(DAC_CR寄存器中的TENx位复位),那么经过一个APB1时钟周期后,DAC_DHRx寄存器中存储的数据将自动转移到DAC_DORx寄存器。但是,如果选择硬件触发(置位DAC_CR寄存器中的TENx位)且触发条件满足,将在三个APB1时钟周期后转移。
当DDAC_DORx加载了DAC_DHRx内容时,模拟输出电压将在一段时间t后可用,具体t取决于电源电压和模拟输出负载。
DAC数据格式
根据选择的配置模式,数据按照下文所述写入指定的寄存器:
单DAC通道x,有三种情况:
——8位数据右对齐:用户须将数据写入寄存器DAC_DHR8Rx[7:0]位,实际是存入寄存器DHRc[11:4]位)
——12位数据左对齐:用户须将数据写入寄存器DAC_DHR12Lx[15:4]位(实际是存入寄存器DHRx[11:0]位)
——12位数据右对齐:用户须将数据写入寄存器DAC_DHR12Rx[11:0]位(实际是存入寄存器DHRx[11:0]位)
DAC触发选择
如果TENx控制位置1,可通过外部事件(定时计数器、外部中断线)触发转换。TSELx[2:0]控制位将决定通过8个可能事件中的哪一个来触发转换。
DAC输出电压
经过线性转换后,数字输入会转换为0到Vref+之间的输出电压。
各DAC通道引脚大的模拟输出电压通过一下公式确定:
DACoutput=Vref*DOR/4095
DAC通道使能
将DAC_CR寄存器中的相应ENx位置1,即可接通对应DAC通道,经过一段启动时间t后,DAC通道被真正使能。
ENx位只会使能模拟DAC Channelx宏单元。即使ENx复位,DAC Channelx数字接口仍处于使能状态
DAC输出缓冲器使能
DAC集成了两个输出缓冲器,可用来降低输出阻抗并在不增加外部运算放大器的情况下直接驱动外部负载。通过DAC_CR寄存器中相应的BOFFx位,可使能或禁止各DAC通道输出缓冲器。
DAC相关寄存器
硬件连接
二、DAC配置步骤
1、开启PA口时钟,设置PA4为模拟输入
STM32F407ZGT6的DAC通道1是连接在PA4上的,所以要先使能GPIOA的时钟,然后设置PA44为模拟输入。
这里需要特别说明一下,虽然DAC引脚设置为输入,但是STM32F4内部会连接在DAC模拟输出上。
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
GPIO_InitABC.GPIO_Pin=GPIO_Pin_4;
GPIO_InitABC.GPIO_Mode=GPIO_Mode_AN;//模拟输入
GPIO_InitABC.GPIO_PuPd=GPIO_PuPd_DOWN;//下拉
GPIO_Init(GPIOA,&GPIO_InitABC);
2、使能DAC1时钟
同其他外设一样,须先开启相应的时钟。STM32F4的DAC模块时钟是由APB1提供的,所以挖煤先要在通过调用函数RCC_PeriphClockCmd来使能DAC1时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE);//使能DAC时钟
3、初始化DAC,设置DAC的工作模式
该部分设置全部通过DAC_CR设置实现,包括:DAC通道1使能、DAC通道1输出缓存关闭、不使用触发 、不使用波形发生器等设置。这里DAC初始化是通过函数DAC_Int完成的:
void DAC_Init(uint32_t DAC_Channel,DAC_InitTypeDef* DAC_InitStruct);
跟前面一样,首先看下参数设置结构体类型DAC_InitTypeDef的定义:
typedef struct
{
uint32_t DAC_Trigger;
uint32_t DAC_WaveGeneration;
uint32_t DAC_LFSRUnmask_TriangleAmplitude;
uint32_t DAC_OutputBuffer;
}DAC_InitTypeDef;
4、使能DAC转换通道
初始化DAC之后,须使能DAC转换通道:
DAC_Cmd(DAC_Channel_1,ENABLE);//使能DAC1通道1
5、设置DAC输出值
通过前面4个步骤的设置,DAC就可以开始工作,使用12位右对齐数据格式,通过设置DHR12R1就可以在DAC输出引脚(PA4)得到不同的电压值。设置DHR12R1的库函数是:
DAC_SetChannel1Data(DAC_Align_12b_R,0);//12位右对齐数据格式设置DAC值
第一个参数设置对齐方式,可以位12位右对齐DAC_Align_12b_R,12位左对齐DAC_Align_12b_L以及8位右对齐DAC_Align_8b_R方式。
第二个参数就是DAC输入值,初始化设置为0、
读出DAC对应通道最后一次转换的数值函数:
DAC_GetDataOutputValue(DAC_Channel_1);
本例程使用的是3.3V的参考电压,即Vref+连接VDDA。
三、实验例程部分代码(再写一遍之前的代码,巩固一下基础)
//DAC通道1输出初始化
void Dac1_Init(void)
{
GPIO_InitTypeDef GPIO_InitABC;
DAC_InitTypeDef DAC_InitABC;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//使能GPIOA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE);//使能DAC时钟
GPIO_InitABC.GPIO_Pin=GPIO_Pin_4;
GPIO_InitABC.GPIO_Mode=GPIO_Mode_AN;//模拟输入
GPIO_InitABC.GPIO_PuPd=GPIO_PuPd_DOWN;//下拉
GPIO_Init(GPIOA,&GPIO_InitABC);//初始化
DAC_InitABC.DAC_Trigger=DAC_Trigger_None;//不使用触发功能
DAC_InitABC.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
DAC_InitABC.DACLFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置
DAC_InitABC.DAC_OutputBuffer=DAC_OutputBuffer_Disable;//DAC1输出缓存关闭
DAC_Init(DAC_Channel_1,&DAC_InitABC);//初始化DAC通道1
DAC_Cmd(DAC_Channel,ENABLE);//使能DAC通道1
DAC_SetChannel1Data(DAC_Align_12b-R,0);//12位右对齐数据格式设置DAC值
}
//设置通道1输出电阻
//vol:0~3300,代表0~3.3V
void Dac1_Set_Vol(u16 vol)
{
double temp=vol;
temp/=1000;
temp=temp*4069/3.3;
DAC_SetChannel1Data(DAC_Align_12b_R,temp);//12位右对齐数据格式设置DAC值
}