当前位置: 首页 > news >正文

【STM32】DAC数字模拟转换

本篇博客重点在于标准库函数的理解与使用,搭建一个框架便于快速开发

目录

前言 

DAC简介

DAC配置

DAC时钟使能

GPIO初始化

DAC配置

DAC使能 

读写DAC值

驱动代码

MyDAC.h

MyDAC.c

main.c


前言 

大容量的STM32F101xx和STM32F103xx产品才有DAC外设

大容量产品是指闪存存储器容量在256K至512K字节之间的STM32F101xx和STM32F103xx微控制器。

DAC简介

数字/模拟转换模块(DAC)是12位数字输入(0~4096),电压输出的数字/模拟转换器。DAC可以配置为8位 或12位模式,也可以与DMA控制器配合使用。DAC工作在12位模式时,数据可以设置成左对齐 或右对齐。DAC模块有2个输出通道,每个通道都有单独的转换器。在双DAC模式下,2个通道可以独立地进行转换,也可以同时进行转换并同步地更新2个通道的输出。DAC可以通过引脚输入参考电压VREF+以获得更精确的转换结果

单个DAC通道的框图

DAC配置

DAC时钟使能

RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);	

GPIO初始化

GPIO的其它参数的理解可以阅读下方博客,这里不再赘述。

【STM32】GPIO和AFIO标准库使用框架_stm32中afio口-CSDN博客

注意: 一旦使能DACx通道,相应的GPIO引脚(PA4或者PA5)就会自动与DAC的模拟输出相连 (DAC_OUTx)。为了避免寄生的干扰和额外的功耗,引脚PA4或者PA5在之前应当设置成模拟输入(AIN) 

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	    	 GPIO_InitTypeDef GPIO_InitStructure;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);

DAC配置

波形生成

指定DAC是否产生噪声波或三角波,或不产生波。

DAC_InitType.DAC_WaveGeneration = DAC_WaveGeneration_None;//不使用波形发生

触发功能 

DAC_InitType.DAC_Trigger = DAC_Trigger_None;	//1.DAC_Trigger_None:一旦DAC1_DHRxxxx寄存器被加载,转换将自动进行,而不是由外部触发器进行 
//2.选择外部触发,定时器TRGO或EXTI_9事件
//3.DAC_Trigger_Software:转换由软件触发器启动,用于DAC通道

注意:如果要产生噪声三角波,则必须使能DAC触发,即设DAC_CR寄存器的TENx位为’1’。 

TSEL2[2:0],该3位只能在TEN2 = 1(DAC通道2触发使能)时设置,即DAC通道1触发使能后才可选择DAC通道1的外部触发事件

调用这个参数时,标准库函数内已经配置好了 

设置屏蔽/幅值选择器

指定噪声波产生的LFSR掩码或DAC通道的最大幅度三角形产生

失能DAC输出缓存

DAC集成了2个输出缓存,可以用来减少输出阻抗,无需外部运放即可直接驱动外部负载。每个 DAC通道输出缓存可以通过设置DAC_CR寄存器的BOFFx位来使能或者关闭

	DAC_InitTypeDef DAC_InitType;				DAC_InitType.DAC_Trigger = DAC_Trigger_None;	//不使用触发功能 TEN1=0DAC_InitType.DAC_WaveGeneration = DAC_WaveGeneration_None;//不使用波形发生DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置DAC_InitType.DAC_OutputBuffer = DAC_OutputBuffer_Disable ;	//DAC1输出缓存关闭 BOFF1=1DAC_Init(DAC_Channel_1, &DAC_InitType);	 //初始化DAC通道1

DAC使能 

将DAC_CR寄存器的ENx位置’1’即可打开对DAC通道x的供电。经过一段启动时间tWAKEUP, DAC通道x即被使能。

注意: ENx位只会使能DAC通道x的模拟部分,即便该位被置’0’,DAC通道x的数字部分仍然工作

	DAC_Cmd(DAC_Channel_1, ENABLE);  //使能DAC1

读写DAC值

根据对DAC_DHRyyyx寄存器的操作,经过相应的移位后,写入的数据被转存到DHRx寄存器中 (DHRx是内部的数据保存寄存器x)。随后,DHRx寄存器的内容或被自动地传送到DORx寄存器,或通过软件触发或外部事件触发被传送到DORx寄存器。

    DAC_SetChannel1Data(DAC_Align_12b_R, 0);  //12位右对齐数据格式设置DAC值 0~4096DAC_GetDataOutputValue(DAC_Channel_1);//读取前面设置DAC的值 

DAC输出电压 

数字输入经过DAC被线性地转换为模拟电压输出,其范围为0到VREF+(一般为3.3V)。

任一DAC通道引脚上的输出电压满足下面的关系: DAC输出 = VREF x (DOR / 4095)。

驱动代码

MyDAC.h

#ifndef __MYDAC_H
#define __MYDAC_H	 	    void MyDAC_Init(void);		 	 
void MyDAC_SetVol(float voltage);#endif

MyDAC.c

#include "stm32f10x.h"                  // Device header
#include "MyDAC.h"//DAC通道1输出初始化
void MyDAC_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);	 GPIO_InitTypeDef GPIO_InitStructure;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);DAC_InitTypeDef DAC_InitType;				DAC_InitType.DAC_Trigger = DAC_Trigger_None;	//不使用触发功能 TEN1=0DAC_InitType.DAC_WaveGeneration = DAC_WaveGeneration_None;//不使用波形发生DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置DAC_InitType.DAC_OutputBuffer = DAC_OutputBuffer_Disable ;	//DAC1输出缓存关闭 BOFF1=1DAC_Init(DAC_Channel_1, &DAC_InitType);	 //初始化DAC通道1DAC_Cmd(DAC_Channel_1, ENABLE);  //使能DAC1DAC_SetChannel1Data(DAC_Align_12b_R, 0);  //12位右对齐数据格式设置DAC值}//设置通道1输出电压
//voltage:0~3.3V
void MyDAC_SetVol(float voltage)
{uint16_t temp;temp = voltage * 4096 / 3.3;DAC_SetChannel1Data(DAC_Align_12b_R, temp);//12位右对齐数据格式设置DAC值
}

main.c

#include "stm32f10x.h"                  // Device header
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"	 	 
#include "MyDAC.h"
#include "adc.h"
#include "OLED.h"uint16_t adcx;
float temp;
uint8_t t=0;	 
uint16_t dacval=0;
uint8_t key;int main(void)
{	 delay_init();	    	 //延时函数初始化	  KEY_Init();			  //初始化按键程序Adc_Init();		  		//ADC初始化MyDAC_Init();				//DAC初始化OLED_Init();									      OLED_ShowString(1, 1, "DAC VAL:");	      OLED_ShowString(2, 1, "DAC:0.000V");	      OLED_ShowString(3, 1, "ADC:0.000V");DAC_SetChannel1Data(DAC_Align_12b_R, 0);//初始值为0	    	      while(1){t++;key = KEY_Scan(0);			  if(key == WKUP_PRES){		 if(dacval < 4000)dacval+=200;DAC_SetChannel1Data(DAC_Align_12b_R, dacval);//设置DAC值	}else if(key == KEY1_PRES)	{if(dacval > 200) dacval-=200;else dacval = 0;DAC_SetChannel1Data(DAC_Align_12b_R, dacval);//设置DAC值}if(t==10||key == KEY1_PRES||key == WKUP_PRES) //WKUP/KEY1按下了,或者定时时间到了{	  adcx = DAC_GetDataOutputValue(DAC_Channel_1);//读取前面设置DAC的值OLED_ShowNum(1, 9, adcx, 4);     	//显示DAC寄存器值temp = (float)adcx*(3.3/4096);			//得到DAC电压值adcx = temp;OLED_ShowNum(2, 5, temp, 1);     	//显示电压值整数部分temp-=adcx;temp*=1000;OLED_ShowNum(2, 7, temp, 3); 	//显示电压值的小数部分adcx = Get_Adc_Average(ADC_Channel_1, 10);		//得到ADC转换值	  temp = (float)adcx * (3.3 / 4096);			//得到ADC电压值adcx = temp;OLED_ShowNum(3, 5, temp, 1);     	//显示电压值整数部分temp-=adcx;temp*=1000;OLED_ShowNum(3, 7, temp, 3); 	//显示电压值的小数部分LED0=!LED0;	   t = 0;}	    delay_ms(10);	}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【BurpSuite】Cross-site scripting (XSS 学徒部分:1-9)
  • Go 并发模式:扩展与聚合的高效并行
  • GPT对话知识库——将寄存器中的一位数据读到变量中需要什么步骤?C语言中掩码的作用。
  • SpringBoot使用@Async注解,实现异步任务
  • 硬件工程师笔试面试——无线通讯模块
  • Go并发编程的高级技巧——请求复制与限流
  • 数据结构之二叉树的暴力删除
  • Golang | Leetcode Golang题解之第415题字符串相加
  • 直播音频解决方案
  • 牛客周赛 Round 60(思维、逆元、组合数、概率DP)
  • Java 入门指南:JVM(Java虚拟机)—— Java 类加载器详解
  • 【iOS】单例模式
  • 基于python+django+vue的图书管理系统
  • 传输层协议 —— TCP协议(上篇)
  • 学习Java(一)类和对象
  • 11111111
  • 2017前端实习生面试总结
  • canvas 五子棋游戏
  • create-react-app做的留言板
  • echarts花样作死的坑
  • ECMAScript6(0):ES6简明参考手册
  • express如何解决request entity too large问题
  • Js实现点击查看全文(类似今日头条、知乎日报效果)
  • Mithril.js 入门介绍
  • SpingCloudBus整合RabbitMQ
  • Vue官网教程学习过程中值得记录的一些事情
  • vue学习系列(二)vue-cli
  • 百度小程序遇到的问题
  • 复杂数据处理
  • 力扣(LeetCode)357
  • Hibernate主键生成策略及选择
  • hi-nginx-1.3.4编译安装
  • linux 淘宝开源监控工具tsar
  • 交换综合实验一
  • ​探讨元宇宙和VR虚拟现实之间的区别​
  • #《AI中文版》V3 第 1 章 概述
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • #预处理和函数的对比以及条件编译
  • $分析了六十多年间100万字的政府工作报告,我看到了这样的变迁
  • ()、[]、{}、(())、[[]]命令替换
  • (¥1011)-(一千零一拾一元整)输出
  • (2)空速传感器
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (web自动化测试+python)1
  • (WSI分类)WSI分类文献小综述 2024
  • (笔记)M1使用hombrew安装qemu
  • (二)Linux——Linux常用指令
  • (附源码)php投票系统 毕业设计 121500
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (推荐)叮当——中文语音对话机器人
  • (自适应手机端)响应式新闻博客知识类pbootcms网站模板 自媒体运营博客网站源码下载
  • .Net Attribute详解(上)-Attribute本质以及一个简单示例
  • .NET Standard 支持的 .NET Framework 和 .NET Core
  • .net经典笔试题