【STM32】DAC数字模拟转换

news2024/11/15 3:29:50

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

目录

前言 

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=0
	DAC_InitType.DAC_WaveGeneration = DAC_WaveGeneration_None;//不使用波形发生
	DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置
	DAC_InitType.DAC_OutputBuffer = DAC_OutputBuffer_Disable ;	//DAC1输出缓存关闭 BOFF1=1
    DAC_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~4096
    DAC_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=0
	DAC_InitType.DAC_WaveGeneration = DAC_WaveGeneration_None;//不使用波形发生
	DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置
	DAC_InitType.DAC_OutputBuffer = DAC_OutputBuffer_Disable ;	//DAC1输出缓存关闭 BOFF1=1
    DAC_Init(DAC_Channel_1, &DAC_InitType);	 //初始化DAC通道1

	DAC_Cmd(DAC_Channel_1, ENABLE);  //使能DAC1
  
    DAC_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.coloradmin.cn/o/2139139.html

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

相关文章

几种mfc140u.dll常见错误情况,以及mfc140u.dll文件修复的方法

如果你遇到与mfc140u.dll 文件相关的错误&#xff0c;这通常指的是该mfc140u.dll文件可能丢失、损坏或与您的应用程序不兼容。详细分析关于mfc140u.dll文件错误会对系统有什么影响&#xff0c;mfc140u.dll文件处于什么样的位置&#xff1f;以下是几种常见的错误情况及其修复方法…

R语言统计分析——功效分析(作图)

参考资料&#xff1a;R语言实验【第2版】 假设对于相关系数统计显著性检验&#xff0c;我们想计算一系列效应值和功效水平下所需的样本量&#xff0c;此时可用pwr.r.test()函数和for循环来完成任务。 # 加载pwr包 library(pwr) # 设置各效应值 r<-seq(0.1,0.5,0.01) # 计算…

基于JAVA的实验室智慧管理平台的设计与实现

大型管理系统用传统的手工操作方式进行信息管理容易出现数据丢失&#xff0c;统计错误等问题&#xff0c;而且劳动强度高&#xff0c;速度慢&#xff0c;耗费人力&#xff0c;物力。使用计算机可以高效、准确地完成以上工作。因此&#xff0c;用计算机的高速度和自动化来替代手…

蓝牙模块—BLE-CC41-A

1. 蓝牙的特点 蓝牙模块采用的 TI 公司设计的 CC2541芯片&#xff0c;主要面向低功耗蓝牙通信方案&#xff0c;该模块的工作频段为 2.4Ghz&#xff0c;这个频段属于国际通用频段 注意&#xff1a;蓝牙集成了一个状态指示灯&#xff0c;LED灯如果均匀慢速闪烁&#xff0c;就表示…

接口测试从入门到精通项目实战

视频网址&#xff1a;2024最新接口测试从入门到精通项目实战&#xff08;全套接口测试教程&#xff09;_哔哩哔哩_bilibili 接口架构设计分析 http协议详解 JMeter 目录介绍 常用组件 执行接口测试 接口文档&#xff1a;tlias智能学习辅助系统接口文档-V1.0-CSDN博客 实战 前…

HTB-Lame(msf利用)

前言 各位师傅大家好&#xff0c;我是qmx_07&#xff0c;今天给大家讲解 初学者渗透路径 第一个靶机Lame 渗透过程 信息搜集 服务器开放了21FTP端口、22SSH端口、445SMB端口 利用MSF模块 登录主机 工具介绍&#xff1a;Metasploit Framework&#xff08;简称 MSF&#xf…

RK3562/3588系列之6—yolov5模型的部署

RK3562/3588系列之6—yolov5模型的部署 1.yolov5模型训练2.训练好的模型转成onnx格式3.模型从onnx格式转RKNN3.1 onnx2rknn.py3.2 onnx2rknn.py3.3 直接使用rknn.api3.4 rknn_model_zoo中的转换代码3.5 LubanCat-RK系列板卡官方资料4.RK NPU c++推理4.1交叉编译4.2 开发板执行编…

校园失物招领小程序

校园失物招领小程序 weixin167校园失物招领小程序ssm 目 录 目 录 I 摘 要 III ABSTRACT IV 1 绪论 1 1.1 课题背景 1 1.2 研究现状 1 1.3 研究内容 2 2 系统开发环境 3 2.1 JSP技术 3 2.2 JAVA技术 3 2.3 MYSQL数据库 3 2.4 B/S结构 4 2.5 SSM框架技术 4 3 系…

清理C盘缓存,如何针对Windows10系统,专业地调整和优化C盘缓存设置

在Windows10系统中&#xff0c;合理地管理C盘&#xff08;通常是系统盘&#xff09;的缓存设置&#xff0c;对于保持系统性能、提升响应速度以及避免磁盘空间不足等问题至关重要。缓存主要涉及到系统文件、临时文件、应用程序缓存等多个方面。下面将详细介绍如何针对Windows10系…

【webpack4系列】webpack进阶用法(三)

文章目录 自动清理构建目录产物PostCSS插件autoprefixer自动补齐CSS3前缀移动端CSS px自动转换成rem静态资源内联多页面应用打包通用方案使用sourcemap提取页面公共资源基础库分离利⽤ SplitChunksPlugin 进⾏公共脚本分离利⽤ SplitChunksPlugin 分离基础包利⽤ SplitChunksPl…

UVA1395 Slim Span(最小生成树)

*原题链接*(洛谷) 非常水的一道题。看见让求最小边权差值的生成树&#xff0c;很容易想到kruskal。 一个暴力的想法是以每条边为最小边跑一遍kruskal&#xff0c;然后统计答案。时间复杂度&#xff0c;再看题中很小的数据范围和3s的时限。最后还真就过了。 不过我天真的想了…

【机器学习】11——矩阵求导

机器学习11——矩阵求导 打公式不太好标注&#xff0c;全图警告&#xff01;&#xff01;&#xff01; 文章目录 机器学习11——矩阵求导1.1标量对向量1.2标量对矩阵2.1向量对标量2.2向量对向量2.3向量对矩阵 1.1标量对向量 1.2标量对矩阵 X是m*n的矩阵&#xff0c;不严谨&am…

代码随想录Day 44|leetcode题目:1143.最长公共子序列、1035.不相交的线、53. 最大子序和、392.判断子序列

提示&#xff1a;DDU&#xff0c;供自己复习使用。欢迎大家前来讨论~ 文章目录 题目题目一&#xff1a;1143.最长公共子序列解题思路&#xff1a; 题目二&#xff1a; 1035.不相交的线解题思路&#xff1a; 题目三&#xff1a;53. 最大子序和解题思路 题目四&#xff1a;392.判…

【白话树】之 二叉树

快速导航 一、二叉树的基本概念1、 二叉树定义2、常见术语3、基本操作1&#xff09;创建&#xff1a;2&#xff09;插入与删除&#xff1a; 4、常见类型1&#xff09;满二叉树&#xff08;完美二叉树&#xff09;2&#xff09;完全二叉树3&#xff09;完满二叉树4&#xff09;平…

Mysql InnoDB 存储引擎简介

InnoDB 存储引擎是 Mysql 的默认存储引擎&#xff0c;它是由 Innobase Oy 公司开发的 Mysql 为什么默认使用 InnoDB 存储引擎 InnoDB 是一款兼顾高可靠性和高性能的通用存储引擎 在 Mysql 5.5 版本之前&#xff0c;默认是使用 MyISAM 存储引擎&#xff0c;在 5.5 及其之后版…

WEB打点

目录 web打点概述打点流程打点中的问题getshell手法汇总web打点批量检测端口扫描POC扫描指纹识别漏洞扫描 手工检测开源框架漏洞通用框架漏洞基础web漏洞商用系统漏洞 WAF绕过waf分类常见waf拦截界面WAF绕过思路侧面绕&#xff1a;适合云WAF直面WAF web打点概述 打点流程 资产…

远程Linux网络连接( Linux 网络操作系统 04)

接下来我们准备开始进入Linux操作系统的第二个模块的学习&#xff0c;不过在学习之前我们需要对如下进行简单的配置&#xff0c;通过外接辅助软件MobaXterm来进行虚拟操作系统的访问。接下来的课程我们会一直在MobaXterm中进行命令和相关知识的学习。 一、准备阶段 1.1 软件 …

安装配置filebrowser

安装配置filebrowser ​ 这章就简单搞个工具用一下&#xff0c;这个工具就是一个像安卓软件一样的文件浏览器&#xff0c;可以设置用户权限啥的&#xff0c;挺好用的下面直接粘的安装步骤&#xff0c;注意一下配置别错了就行&#xff0c;json文件和命令配置要一样。访问效果放…

逻辑回归原理

本文主要介绍了逻辑回归的原理和应用&#xff0c;包括从线性回归到逻辑回归的转换、二元逻辑回归的模型和损失函数、优化方法以及正则化等内容。以下是内容的详细叙述&#xff1a; 1. 从线性回归到逻辑回归 线性回归模型&#xff1a;线性回归是找出输出特征向量Y与输入样本矩阵…

无线通信感知/雷达系统算法专业技术栈

无论是在工业界还是在学业界&#xff0c;无线通信感知一体化都是一个热门的方向&#xff0c;作为一个24届毕业生&#xff0c;刚好处于行业当中&#xff0c;就总结一下自己浅薄认知下&#xff0c;自己觉得已经掌握或者应该掌握的技术栈和专业能力&#xff0c;与大家共勉。 Rada…