记录一下,方便以后翻阅~
主要内容:
1) DAC数模转换原理;
2) 寄存器和库函数介绍;
3) 相关实验代码解读。
实验功能:系统启动后,按WK_UP键,输出电压加200点,对应电压值200*3.3/4096,按KEY1,输出电压值减200点,每次按键,输出电压值会传至串口调试助手上。
官方资料:《STM32中文参考手册V10》第12章——数字模拟转换DAC
硬件连接
1. 数模转换原理
STM32的DAC模块是12位数字输入,电压输出型的DAC。DAC可以配置为8位或12位模式,也可与DMA控制器配合使用。DAC工作在12位模式时,数据可以设置成左对齐或右对齐。DAC模块有2个输出通道,每个通道有单独的转换器。在双DAC模式下,2个通道可以独立地进行转换,也可以同时进行转换并同步地更新2个通道的输出。DAC可通过引脚输入参考电压VREF+以获得更精确的转换结果。
2. DAC模块特点
2.1 2个DAC转换器,每个转换器对应1个输出通道;
2.2 8位或者12位单调输出;
2.3 12位模式下数据左对齐或者右对齐;
2.4 同步更新功能;
2.5 噪声波形生成;
2.6 三角波形生成;
2.7 双DAC通道同时或者分别转换;
2.8 每个通道都有DMA功能。
3. DAC模块框图
3.1 VDDA和VSSA为DAC模块模拟部分的供电;
3.2 Vref+则是DAC模块的参考电压;
3.3 数字不是写入DORx寄存器里,是写入在DHRx寄存器里;
3.4 DAC_OUTx就是DAC的输出通道了(对应PA4或PA5引脚)。
DAC_OUT1 ->PA4
DAC_OUT2 ->PA5
4. DAC转换
5. DAC数据格式
6. 选择DAC触发
7. DAC输出电压
8. 使能DAC通道
9. 使能DAC输出缓存
如果使能DAC输出缓存的话,虽然输出能力强一点,但是输出没法到0。
10. DAC相关寄存器一览
10.1 DAC控制寄存器DAC_CR
10.2 DAC通道1的12位右对齐数据保持寄存器DAC_DHR12R1
10.3 DAC通道1的12位左对齐数据保持寄存器DAC_DHR12L1
10.4 DAC通道1的8位右对齐数据保持寄存器DAC_DHR8R1
10.5 DAC通道1数据输出寄存器DAC_DOR1
11. DAC一般配置步骤
11.1 使能PA口时钟,设置PA4为模拟输入;
11.2 使能DAC1时钟;
11.3 初始化DAC,设置DAC工作模式;
11.4 使能DAC转换通道;
11.5 设置DAC输出值。
12. 相关实验代码解读
12.1 adc.h头文件代码解读
#ifndef __ADC_H
#define __ADC_H
#include "sys.h"
//申明三个函数//
void Adc_Init(void);
u16 Get_Adc(u8 ch);
u16 Get_Adc_Average(u8 ch,u8 times);
#endif
12.2 adc.c文件代码解读
#include "adc.h"
#include "delay.h"
//配置ADC1一般步骤://
//1)开启PA口时钟和ADC1时钟,设置PA1为模拟输入;//
//2)复位ADC1,同时设置ADC1分频因子;//
//3)初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息;//
//4)使能ADC并校准;//
//5)配置规则通道参数;//
//6)开启软件转换;//
//7)等待转换完成,读取ADC值。//
//编写Adc_Init初始化函数//
void Adc_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
//使能GPIOA和ADC1通道时钟//
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE );
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M//
//配置GPIO参数,引脚1,模拟输入//
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值//
//配置ADC_Init参数//
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立模式//
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //单通道模式//
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //单次转换模式//
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //软件触发启动//
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐//
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1//
//以下四个函数用于校准//
ADC_ResetCalibration(ADC1); //使能复位校准//
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束//
ADC_StartCalibration(ADC1); //开启AD校准//
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束//
}
u16 Get_Adc(u8 ch)
{
//设置指定ADC的规则组通道,四个入口参数//
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能//
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC )); //等待转换结束//
return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果//
}
u16 Get_Adc_Average(u8 ch,u8 times)
{
u32 temp_val=0;
u8 t;
for(t=0;t<times;t++)
{
temp_val+=Get_Adc(ch);
delay_ms(5);
}
return temp_val/times;
}
12.3 dac.h头文件代码解读
#ifndef __DAC_H
#define __DAC_H
#include "sys.h"
//申明两个函数//
void Dac1_Init(void);
void Dac1_Set_Vol(u16 vol);
#endif
12.4 dac.c文件代码解读
#include "dac.h"
//DAC1配置步骤包括://
//1)使能PA口时钟,设置PA4为模拟输入;//
//2)使能DAC1时钟//
//3)初始化DAC,设置DAC工作模式//
//4)使能DAC转换通道//
//5)设置DAC输出值//
//DAC通道1输出初始化函数//
void Dac1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
DAC_InitTypeDef DAC_InitType;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); //使能GPIOA通道时钟//
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE ); //使能DAC通道时钟//
//GPIOA配置,引脚4,模拟输入//
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //引脚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初始化配置//
DAC_InitType.DAC_Trigger=DAC_Trigger_None; //不使用触发功能//
DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None; //不使用波形发生//
DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0; //屏蔽、幅值设置,通常配合波形发生使用//
DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; //DAC1输出缓存关闭//
DAC_Init(DAC_Channel_1,&DAC_InitType);
DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC1转换通道//
DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值//
}
//设置通道1输出电压,vol:0~3300,代表0~3.3V//
void Dac1_Set_Vol(u16 vol)
{
float temp=vol;
temp/=1000;
temp=temp*4096/3.3;
DAC_SetChannel1Data(DAC_Align_12b_R,temp); //12位右对齐数据格式设置DAC值//
}
12.5 main.c文件代码解读
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "dac.h"
#include "adc.h"
int main(void)
{
u16 adcx;
float temp;
u16 dacval=0;
u8 key;
delay_init(); //延时函数初始化//
uart_init(115200); //串口初始化为115200//
KEY_Init(); //初始化按键程序//
LED_Init(); //LED端口初始化//
LED0=1;
LED1=1;
Adc_Init(); //ADC初始化//
Dac1_Init(); //DAC初始化//
DAC_SetChannel1Data(DAC_Align_12b_R, 0);
while(1)
{
key=KEY_Scan(0);
if(key==WKUP_PRES)
{
if(dacval<4000)
{
dacval+=200;
LED0=0; //加电压时,LED0亮//
}
DAC_SetChannel1Data(DAC_Align_12b_R, dacval); //dacval值<4000时,DAC输出值加200,否则输出值为4000//
}else if(key==KEY1_PRES)
{
if(dacval>200)
{
dacval-=200;
LED1=0; //减电压时,LED1亮//
}
else dacval=0;
DAC_SetChannel1Data(DAC_Align_12b_R, dacval); //dacval值>200时,DAC输出值减200,否则输出值为0//
}
if(key==KEY1_PRES||key==WKUP_PRES) //WKUP或KEY1按下了//
{
adcx=DAC_GetDataOutputValue(DAC_Channel_1); //读取DAC传至ADC的值//
printf("电压原始值:%d\n",adcx);
temp=(float)adcx*(3.3/4096); //归一化电压值//
printf("电压实际值:%f\n",temp);
}
delay_ms(500);
LED0=1;
LED1=1;
}
}
13. 实验结果
旧知识点
1)复习如何新建工程模板,可参考STM32学习心得二:新建工程模板;
2)复习基于库函数的初始化函数的一般格式,可参考STM32学习心得三:GPIO实验-基于库函数;
3)复习寄存器地址,可参考STM32学习心得四:GPIO实验-基于寄存器;
4)复习位操作,可参考STM32学习心得五:GPIO实验-基于位操作;
5)复习寄存器地址名称映射,可参考STM32学习心得六:相关C语言学习及寄存器地址名称映射解读;
6)复习时钟系统框图,可参考STM32学习心得七:STM32时钟系统框图解读及相关函数;
7)复习延迟函数,可参考STM32学习心得九:Systick滴答定时器和延时函数解读;
8)复习ST-LINK仿真器的参数配置,可参考STM32学习心得十:在Keil MDK软件中配置ST-LINK仿真器;
9)复习ST-LINK调试方法,可参考STM32学习心得十一:ST-LINK调试原理+软硬件仿真调试方法;
10)复习如何对GPIO进行复用,可参考STM32学习心得十二:端口复用和重映射;
11)复习串口通信相关知识,可参考STM32学习心得十四:串口通信相关知识及配置方法;
12)复习ADC原理及一般配置步骤,可参考STM32学习心得二十三:ADC转换原理及模数转换实验和STM32学习心得二十四:内部温度传感器原理及实验和STM32学习心得二十五:光敏传感器原理及实验。