DAC数模转换:将数字信号转换成模拟信号
特性:2个DAC转换器每个都拥有一个转换通道
8位或12位单调输出(8位右对齐;12位左对齐右对齐)
双ADC通道同时或者分别转换
外部触发中断
- 电压源
- 控制部分(外部触发3个APB1;不使用1个APB1)
- 外部触发
- 输出:DAC1-PA4;DAC2-PA5
软件设计流程:
- 使能端口以及DAC时钟;设置引脚为模拟输入
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);//使能DAC时钟
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;//模拟量输入
- 初始化DAC,设置DAC工作模式(触发选择;DAC波形发生;屏蔽\幅值选择器;DAC输出)
typedef struct
{
uint32_t DAC_Trigger; /*!< 指定所选DAC通道的外部触发源
此参数可以是 @ref DAC_trigger_selection 中的一个值 */
uint32_t DAC_WaveGeneration; /*!< 指定是否生成DAC通道的噪声波或三角波,或不生成任何波形
此参数可以是 @ref DAC_wave_generation 中的一个值 */
uint32_t DAC_LFSRUnmask_TriangleAmplitude; /*!< 指定噪声波生成的LFSR掩码或DAC通道的三角波最大生成幅度
此参数可以是 @ref DAC_lfsrunmask_triangleamplitude 中的一个值 */
uint32_t DAC_OutputBuffer; /*!< 指定是否启用或禁用DAC通道的输出缓冲器
此参数可以是 @ref DAC_output_buffer 中的一个值 */
}DAC_InitTypeDef;
- 使能DAC输出通道
DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC通道1
- 设置DAC输出值
/**
* @brief 设置DAC通道1的转换数据
* @param DAC_Align: 指定数据对齐方式
* 该参数可以是 @ref DAC_data_align 中的一个值,例如:
* - DAC_Align_8b_R: 8位右对齐
* - DAC_Align_12b_L: 12位左对齐
* - DAC_Align_12b_R: 12位右对齐
* @param Data: 要转换的数字值
* - 对于8位右对齐,有效范围为0~255(0x00~0xFF)
* - 对于12位右对齐,有效范围为0~4095(0x000~0xFFF)
* - 对于12位左对齐,有效范围同样为0~4095,但数据需左移4位
* @retval 无
* @note 写入的数据将在下次触发事件(如软件触发或定时器触发)时转换为模拟电压
* 转换后的电压值 = (Data / 满量程值) × VREF+
* 例如,对于12位DAC且VREF+=3.3V,Data=2048对应电压1.65V
*/
void DAC_SetChannel1Data(uint32_t DAC_Align, uint16_t Data)
代码如下:
#include "dac.h"
/*******************************************************************************
* 函 数 名 : DAC1_Init
* 函数功能 : DAC1初始化函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void DAC1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
DAC_InitTypeDef DAC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);//使能DAC时钟
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;//DAC_1
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;//模拟量输入
GPIO_Init(GPIOA,&GPIO_InitStructure);
DAC_InitStructure.DAC_Trigger=DAC_Trigger_None; //不使用触发功能 TEN1=0
DAC_InitStructure.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置
DAC_InitStructure.DAC_OutputBuffer=DAC_OutputBuffer_Disable ; //DAC1输出缓存关闭 BOFF1=1
DAC_Init(DAC_Channel_1,&DAC_InitStructure); //初始化DAC通道1
DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值
DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC通道1
}
主函数代码:(按键按下,DAC写入转换值)
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "usart.h"
#include "key.h"
#include "dac.h"
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
u8 i=0;
u8 key;
int dac_value=0;
u16 dacval;
float dac_vol;
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2组
LED_Init();
USART1_Init(115200);
KEY_Init();
DAC1_Init();
while(1)
{
key=KEY_Scan(0);//单次按下
if(key==KEY_UP_PRESS)
{
dac_value+=400;
if(dac_value>=4000)
{
dac_value=4095;
}
DAC_SetChannel1Data(DAC_Align_12b_R,dac_value);//写入4095
}
else if(key==KEY1_PRESS)
{
dac_value-=400;
if(dac_value<=0)
{
dac_value=0;
}
DAC_SetChannel1Data(DAC_Align_12b_R,dac_value);
}
i++;
if(i%20==0)
{
LED1=!LED1;
}
if(i%50==0)
{
dacval=DAC_GetDataOutputValue(DAC_Channel_1);
dac_vol=(float)dacval*(3.3/4096);
printf("输出DAC电压值为:%.2fV\r\n",dac_vol);
}
delay_ms(10);
}
}