STM32f4_DAC

DAC 简介

Stm32f4内嵌的DAC是12位数字输入,电压输出的数模转换器。DAC可以配置为8位或12位模式,也可以与DMA控制器配合使用。DAC工作在12位模式时,数据可以设置成左对齐或右对齐。DAC模块有2个输出通道,每个通道都有单独的转换器。在双DAC模式下,2个通道可以独立地进行转换,也可以同时进行转换并同步地更新2个通道的输出。DAC可以通过引脚输入参考电压VREF+以获得更精确的转换结果。
主要特点:
2个DAC转换器:每个转换器对应1个输出通道
8位或者12位单调输出
12位模式下数据左对齐或者右对齐
同步更新功能
噪声波形生成
三角波形生成
双DAC通道同时或者分别转换
每个通道都有DMA功能
外部触发转换
输入参考电压VREF+

DAC框图

在这里插入图片描述 VDDA:模拟电源输入
VSSAL:模拟电源接地输入
Vref+:正模拟参考电压输入
DORx:输入数字寄存器
DAC_OUT:模拟输出通道
DAC_OUT1 ->PA4
DAC_OUT2 ->PA5

寄存器

在这里插入图片描述### 过程
软件将数据加载到DAC_DHRx寄存器
写入的数据将移位并存储到相应的 DHRx(数据保 持寄存器 x,即内部非存储器映射寄存器)
根据是否选择硬件触发,DHRx 寄存器将被自动加载,或者通过软件或外部事件触发加载到
DORx 寄存器的数据在 t SETTLING 时间后给模拟输出电压

时序:

如果未选择硬件触发:
(DAC_CR 寄存器中的 TENx 位复位)
经过一个 APB1 时钟周期后, DAC_DHRx寄存器中存储的数据将自动转移到 DAC_DORx 寄存器。
如果选择硬件触发
(置位 DAC_CR 寄存器中的 TENx位)且触发条件到来
将在三个 APB1 时钟 周期后进行转移。
当 DAC_DORx 加载了 DAC_DHRx内容时,模拟输出电压将在一段时间 t SETTLING 后可用,具体时间取决于电源电压和模拟输出负载。
在这里插入图片描述

数据保持寄存器

对于 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 输出电压
经过线性转换后,数字输入会转换为 0 到 VREF+ 之间的输出电压。
各 DAC 通道引脚的模拟输出电压通过以下公式确定:

在这里插入图片描述

代码配置

设置步骤:
设置相关GPIO(PA4、5)。
若时钟源为TIMx更新事件,则设置TIMx。
使能DAC时钟
设置触发源,开启相关触发通道,如果用DMA,是否允许数据错误中断。
如果用DMA。配置相关DMA数据流。

#include"stm32f4xx.h"
#include"sys.h"
#include<stdio.h>
static GPIO_InitTypeDef 		GPIO_InitStructure;
static NVIC_InitTypeDef			NVIC_InitStructure;
static USART_InitTypeDef 		USART_InitStructure;
static ADC_InitTypeDef       	ADC_InitStructure;
static ADC_CommonInitTypeDef 	ADC_CommonInitStructure;
static DAC_InitTypeDef 			DAC_InitStructure;
void delay_ms(uint32_t n)
{
	while(n--)
	{
		SysTick->CTRL = 0; 				// Disable SysTick,关闭系统定时器
		SysTick->LOAD = (168000)-1; 	// 配置计数值(168000)-1 ~ 0
		SysTick->VAL  = 0; 		// Clear current value as well as count flag
		SysTick->CTRL = 5; 		// Enable SysTick timer with processor clock
		while ((SysTick->CTRL & 0x10000)==0);// Wait until count flag is set
	}
	
	SysTick->CTRL = 0; 		// Disable SysTick	

}


void delay_us(uint32_t n)
{
	while(n--)
	{
		SysTick->CTRL = 0; 				// Disable SysTick,关闭系统定时器
		SysTick->LOAD = (168)-1; 	// 配置计数值(168000)-1 ~ 0
		SysTick->VAL  = 0; 		// Clear current value as well as count flag
		SysTick->CTRL = 5; 		// Enable SysTick timer with processor clock
		while ((SysTick->CTRL & 0x10000)==0);// Wait until count flag is set
	}
	
	SysTick->CTRL = 0; 		// Disable SysTick	

}
void usart1_init(uint32_t baud)
{
	//端口A硬件是能

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	//串口硬件是能
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

	
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF ;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
	
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	//PF9应交连接到串口
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
	
	
	//配置串口
	
	USART_InitStructure.USART_BaudRate = baud;//波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//数据为
    USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位
    USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶效验为
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件流控制
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//串口方式 允许收发数据
    USART_Init(USART1, &USART_InitStructure);
	
	
	//配置中断触发方式
	
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
		
	//配置终端优先级
	
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

	NVIC_Init(&NVIC_InitStructure);
	//使能串口工作
	USART_Cmd(USART1, ENABLE);


}
void dac_init()
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE);//使能
	
	DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;//dac出发模式,不需要脉冲触发工作
    DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;//不输出波形
    DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;//应许输出电压
    DAC_Init(DAC_Channel_1, &DAC_InitStructure);
	DAC_Cmd(DAC_Channel_1, ENABLE);//使能adc输出


}

void adc_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//使能ADC
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
	
	//配置端口模式
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_4;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AN;
	GPIO_InitStructure.GPIO_PuPd= GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//独立工作模式
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;//分屏
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;//不需要映射数据
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
    ADC_CommonInit(&ADC_CommonInitStructure);
	
	ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//精度
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;//单通道,否则为多通道
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//不断的转换
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//不需要内部脉冲出发
  //  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐存储
    ADC_InitStructure.ADC_NbrOfConversion = 1;//几个转换通道
	ADC_Init(ADC1,&ADC_InitStructure);
	//通道链接PA5
	ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_56Cycles);
	ADC_Cmd(ADC1,ENABLE);

}
struct __FILE{int handle;};
FILE __stdout;
FILE __stdin;

int fputc(int ch,FILE *f)
{
	USART_SendData(USART1,ch);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
	return ch;
}



int main(void)
{
	uint16_t adc_val,adc_v;
	//波特率为115200
	usart1_init(115200);
	
	printf("ADC test\r\n");
	adc_Init();
	dac_init();
	DAC_SetChannel1Data(DAC_Align_12b_R,1650*4095/3300);
	//out=vcc(3300)*ODR/4095
	ADC_SoftwareStartConv(ADC1);//启动ADC1转换
	delay_ms(1000);
	while(1)
	{
		//等待转换完毕
		while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);
		ADC_ClearFlag(ADC1,ADC_FLAG_EOC);
		adc_val=ADC_GetConversionValue(ADC1);
		adc_v=adc_val*3300/4095;
		printf("电压为:%dmv\r\n",adc_v);
		printf("剩余点亮%d%% \r\n",adc_v/33);
		delay_ms(1000);
		
	}
}

void USART1_IRQHandler(void)
{
	uint8_t d=0;  
	//判断标志位i
	if(USART_GetFlagStatus(USART1,USART_IT_RXNE)==SET)
	{
		d=USART_ReceiveData(USART1);
		//
		if(d==0x01)PFout(10)=0;
		if(d==0xf1)PFout(10)=1;
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);
	}
		
	
	//清空标志位

}  

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值