前言
本系列,将stm32常用片上外设进行整理,包括大致原理和代码,主要是熟悉如何根据手册去编写代码。便于以后需要做实验时,能够快速编写基本的驱动,然后编写应用代码。
本系列基于“标准库”整理,开发板用的是正点原子精英版V1.5,单片机是STM32F103ZET6。开发工具KEIL。主要参考资料有《STM32F103xCDE中文参考手册》《STM32F103xCDE中文数据手册》、《CM3权威指南》、《STM32F103xCDE闪存编程手册》、《精英版原理图V1.5》。
》《STM32F1xx Cortex-M3编程手册-英文版》
本文用到的手册有《STM32F103xCDE中文参考手册》《STM32F103xCDE中文数据手册》,讲解STM32F1的DAC框图和配置实验,实现配置DAC1,在PA4上输出不同电压。至于双DAC、产生噪声,三角波等功能暂时不说。
一、DAC介绍
DAC是数字转模拟量的模块,通过软件写入数字,输出对应的电压。STM32F1的DAC的数字部分支持8位或者12位,由于12位是放在32位的低16位里面的寄存器里面的,STM32的寄存器只支持字操作,或者半字操作,所以12位放在了16位的内存里面,从而有左对齐和右对齐的区别,这个也就是软件写数据寄存器时有区别,影响不大。
二、STM32F1的DAC框图
在《STM32F103xCDE中文参考手册》的12.2DAC主要特征,有如下框图,此框图在一眼看去,比ADC框图简单了不少,事实上也确实简单了很多,选择好触发源,配置好控制寄存器,就可以往DHRx中写入数字量,从而DAC_OUTx引脚上就会出现相应的电平。
如上图中备注,只能写DHRx而不能直接写DORx,硬件会自动延时后传入DORx,此说明在《STM32F103xCDE中文参考手册》12.3.3DAC数据格式,有如下说明。
三、DAC实验
1.查找资料
在《STM32F103xCDE中文数据手册》的引脚定义一节,通过Ctrl+F,搜索DAC得知, DAC_OUT1是映射到PA4,DAC_OUT1是映射到PA5。
在《STM32F103xCDE中文参考手册》的8.1.11外设的GPIO配置,表29ADC/DAC配置,知道PA4需要配置为模拟输入模式。
2.编码
查看DAC寄存器,发现主要介绍SWTRIG一个软件触发使能寄存器,CR控制寄存器,其余的都是DHR寄存器,即我们将数字量写入DHR中,从而在PA4或者PA5上输出对应的电压。
CR寄存器如下:TSEL1是DAC1的触发源选择位,TEN1是DAC1的触发使能位,BOFF1是DAC1的通道输出缓存使能位,EN1是DAC1的使能DAC1位。
SWTRIG软件触发使能寄存器如下图:本次实验就是使用软件触发,所以需要置位SWTRIG1。
本次实验初始化DAC1后,在PA4上输出想要的电压。
void dac1_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
DAC_InitTypeDef DAC_InitType;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); //使能PORTA通道时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE ); //使能DAC通道时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_4) ;//PA.4 输出高
DAC_InitType.DAC_Trigger=DAC_Trigger_None; //不使用触发功能 TEN1=0
DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置
DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; //DAC1输出缓存关闭 BOFF1=1
DAC_Init(DAC_Channel_1,&DAC_InitType); //初始化DAC通道1
DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC1
DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值
}
int main(void)
{
uint32_t dacval = 0;
dac1_init();
while(1)
{
if(dacval == 0)
{
dacval = 1234;
DAC_SetChannel1Data(DAC_Align_12b_R, dacval);//设置DAC值,模拟量 = 数字量*分辨率。
}
}
}
计算公式:模拟量 = 数字量*分辨率。分辨率=Vref/2^DAC位数-1,如我们这里板子上一般Vref接3.3V的参考电压,DAC使用12位,那么分辨率=3.3/4095。除以4095而不是4096是因为寄存器是12位的最大只能表示4095,当数字量=4095时,模拟量=3.3刚好是最大值,当数字量=0时,模拟量=0。刚好数字量从0增加到4095时,模拟量从0V上升到3.3V。
四、总结
DAC但输出还是挺简单的,要用来输出三角波,双DAC,还得做具体实验时再来研究。总体来说比ADC简单许多,转换公式一点要记住。模拟量 = 数字量*分辨率,这个公式在ADC里面是一样。ADC是读取出数字量来计算模拟量,而DAC知道模拟量来计算数字量。