【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);	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/141540.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

基于SpringBoot的在线考试系统【附源码】

基于SpringBoot的在线考试系统&#xff08;源码L文说明文档&#xff09; 目录 4 系统设计 4.1 系统概述 4.2系统功能结构设计 4.3.2 数据库表结构设计 5 系统实现 5.1管理员功能介绍 5.1.1管理员登录 5.1.2 试卷管理 5.1.3 公告信息管理 5.1.…

_Array类,类似于Vector,其实就是_string

例子&#xff1a; using namespace lf; using namespace std;int main() {_Array<int> a(10, -1);_Array<_string> s { _t("one"), _t("two") };_pcn(a);_pcn(s);} 结果&#xff1a; 源代码_Array.h&#xff1a; /***********************…

基础物理-直线运动2

2-1 位置、位移和平均速度 位置与位移 为了确定物体的位置&#xff0c;通常需要相对于某个参考点来测量&#xff0c;这个参考点通常是某个坐标轴的原点&#xff08;或零点&#xff09;&#xff0c;如图 2-1 中的 x 轴。坐标轴的正方向是坐标增大的方向&#xff0c;在图 2-1 中…

掌握远程管理的艺术:揭秘Python的pywinrm库

文章目录 &#x1f525; 掌握远程管理的艺术&#xff1a;揭秘Python的pywinrm库 &#x1f525;背景&#xff1a;为何选择pywinrm&#xff1f;pywinrm库简介安装pywinrm库简单库函数使用方法场景应用常见问题与解决方案总结 &#x1f525; 掌握远程管理的艺术&#xff1a;揭秘Py…

【ARM】Cache深度解读

Cache的基本概念和使用场景 不同的Master硬件共享数据时—invalid cache 外设和DDR之间没有cache&#xff0c;所以外设直接把数据写入DDR中&#xff0c;但是cpu和DDR之间有cache&#xff0c;cpu会首先访问cache&#xff0c;如果命中直接从cache中拿数据&#xff0c;但是此时的…

浪潮信息首推3秒智能控温!告别服务器开机噪音

在当前的数据中心运维实践中&#xff0c;运维人员在部署服务器时常被“飞机起飞”般的开机噪音所困扰。服务器刚刚接通电源&#xff0c;其内部元件尚处于预热待命状态&#xff0c;而风扇却已全速运转&#xff0c;这不仅加剧了噪音污染&#xff0c;还拖慢了启动速度&#xff0c;…

[数据集][目标检测]智慧交通铁路人员危险行为躺站坐检测数据集VOC+YOLO格式3766张4类别

图片数量(jpg文件个数)&#xff1a;3766 标注数量(xml文件个数)&#xff1a;3766 标注数量(txt文件个数)&#xff1a;3766 标注类别数&#xff1a;4 标注类别名称:["sitting","sleeping","standing","track"] 每个类别标注的框数&…

OpenCore Legacy Patcher 2.0.0 发布,83 款不受支持的 Mac 机型将能运行最新的 macOS Sequoia

在不受支持的 Mac 上安装 macOS Sequoia (OpenCore Legacy Patcher v2.0.0) Install macOS on unsupported Macs 请访问原文链接&#xff1a;https://sysin.org/blog/install-macos-on-unsupported-mac/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主…

《深度学习》PyTorch 手写数字识别 案例解析及实现 <下>

目录 一、回顾神经网络框架 1、单层神经网络 2、多层神经网络 二、手写数字识别 1、续接上节课代码&#xff0c;如下所示 2、建立神经网络模型 输出结果&#xff1a; 3、设置训练集 4、设置测试集 5、创建损失函数、优化器 参数解析&#xff1a; 1&#xff09;para…

一篇文章带你入门机器学习 Part1 -->Machine Learning from Scratch

学习网站&#xff1a;Machine Learning from Scratch Machine Learning from Scratch (Part1神经网络&#xff09; 神经网络——Neural Networks神经网络是如何工作的&#xff1f;训练神经网络 神经网络——Neural Networks 在人工神经网络的背景下&#xff1a;一个神经元是一…

全面理解tensor编程中矩阵的行和列

经常会在编程中遇到理解矩阵行和列的事情。 1、要明确无论这个张量有多少维度&#xff0c;它的矩阵乘法都只能作用于最后两个维度。 例如&#xff1a; import torcha torch.rand([64, 32, 3, 4]) b torch.rand([64, 32, 3, 4])c torch.matmul(a, b.transpose(2, 3)) # 交…

备战软考Day02-数据结构与算法

1.基本概念与三要素 1.什么是数据 数据是信息的载体&#xff0c;是描述客观事物属性的数、字符及所有能输入到计算机中并被计算机程序识别和处理的符号的集合。数据是计算机程序加工的原料。 2.数据元素、数据项 数据元素是数据的基本单位&#xff0c;通常作为一个整体进行…

18062 二维数组每行中的最大值

### 思路 1. 使用指针变量遍历二维数组的每一行。 2. 对于每一行&#xff0c;找到该行的最大值。 3. 输出每一行的最大值。 ### 伪代码 1. 定义一个指向二维数组的指针变量 p。 2. 遍历二维数组的每一行&#xff1a; - 将 p 指向当前行。 - 初始化 max 为当前行的第一个…

探索Python轻量级数据库:TinyDB的奇妙之旅

文章目录 探索Python轻量级数据库&#xff1a;TinyDB的奇妙之旅背景&#xff1a;为何选择TinyDB&#xff1f;什么是TinyDB&#xff1f;如何安装TinyDB&#xff1f;简单库函数使用方法场景应用常见Bug及解决方案总结 探索Python轻量级数据库&#xff1a;TinyDB的奇妙之旅 背景&…

10.4K Star,高性能富文本编辑器

Hi&#xff0c;骚年&#xff0c;我是大 G&#xff0c;公众号「GitHub 指北」会推荐 GitHub 上有趣有用的项目&#xff0c;一分钟 get 一个优秀的开源项目&#xff0c;挖掘开源的价值&#xff0c;欢迎关注。 在现代 Web 开发中&#xff0c;富文本编辑器是不可或缺的一部分&…

Java设计模式—面向对象设计原则(六) ----->合成复用原则(CRP) (完整详解,附有代码+案例)

文章目录 3.6 合成复用原则(CRP)3.6.1 概述3.6.2 案列 3.6 合成复用原则(CRP) 合成复用原则(CRP)&#xff1a;Composite Reuse Principle&#xff0c;CRP 又叫&#xff1a; 组合/聚合复用原则&#xff08;Composition/Aggregate Reuse Principle&#xff0c;CARP&#xff09;…

java中的注解原理是什么?

Java中的注解&#xff08;Annotations&#xff09;是一种用于提供元数据的机制。它可以通过在代码中添加注解的形式&#xff0c;将一些额外的信息嵌入到代码里。注解本质上不会改变程序的实际逻辑行为&#xff0c;但是可以帮助开发工具、编译器、框架等获取这些元数据&#xff…

信息学奥赛初赛天天练-90-CSP-S2023基础题2-离散数学、染色、完全三叉树、平面图、边双连通图、欧拉图、最长公共子序列、快速排序

PDF文档公众号回复关键字:20240915 2023 CSP-S 选择题 1单项选择题&#xff08;共15题&#xff0c;每题2分&#xff0c;共计30分&#xff1a;每题有且仅有一个正确选项&#xff09; 6 以下连通无向图中&#xff0c;( )一定可以用不超过两种颜色进行染色 A 完全三叉树 B 平面图…

Vue2学习笔记(01计算属性和监视属性)

1、事件修饰符 2、计算属性-computed 要显示的数据不存在&#xff0c;要通过计算得来。在computed对象中定义计算属性。在页面中使用{{方法名}}来显示计算的结果。 3、监视属性-watch 通过vm对象的$watch()或watch配置来监视指定的属性当属性变化时,回调函数自动调用,在函数内…

一文速通calcite结合flink理解SQL从文本变成执行计划详细过程

文章目录 你可以学到啥测试代码背景知识SQL转变流程图问题 你可以学到啥 SQL如何一步步变成执行计划的有哪些优化器&#xff0c;哪些优化规则calcite 和flink 如何结合的 测试代码 EnvironmentSettings settings EnvironmentSettings.inBatchMode(); TableEnvironment tabl…