GD32F103的DAC1

news2024/11/23 13:14:21

GD32F103的DAC1采用定时器1触发,DMA传输,将数据转换为电压输出到PA5引脚。

GD32F103的DAC为12位DA转换器,可以将12位的数据转换为电压,从外部引脚上输出;
DAC_OUT0映射到PA4,DAC_OUT1映射到PA5;

DACx引脚上的模拟输出电压:
DACoutput =DAC_DO *  Vref+/4096

DAC触发:
DTSELx[2:0]=000,触发源为TIMER5_TRGO,属于内部片上信号;
DTSELx[2:0]=001,互联型产品的触发源为TIMER2_TRGO;非互联型产品的触发源为TIMER7_TRGO,属于内部片上信号;
DTSELx[2:0]=010,触发源为TIMER6_TRGO,属于内部片上信号;
DTSELx[2:0]=011,触发源为TIMER4_TRGO,属于内部片上信号;
DTSELx[2:0]=100,触发源为TIMER1_TRGO,属于内部片上信号;
DTSELx[2:0]=101,触发源为TIMER3_TRGO,属于内部片上信号;
DTSELx[2:0]=110,触发源为EXTI9,属于外部信号触发;
DTSELx[2:0]=111,触发源为SWTRIG,属于软件触发;

DAC数据格式
根据选择的配置模式,数据按照下文所述写入指定的寄存器:
8位数据右对齐:用户须将数据写入寄存器DACx_R8DH [7:0]位
12位数据左对齐:用户须将数据写入寄存器DACx_L12DH[15:4]位
12位数据右对齐:用户须将数据写入寄存器DACx_R12DH[11:0]位

DAC0的DAC_CH0映射到DMA1通道2;
DAC1的DAC_CH1映射到DMA1通道3;

 

 

#include "DAC1.h"
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()

/*
GD32F103的DAC为12位DA转换器,可以将12位的数据转换为电压,从外部引脚上输出;
DAC_OUT0映射到PA4,DAC_OUT1映射到PA5;

DACx引脚上的模拟输出电压:
DACoutput =DAC_DO *  Vref+/4096

DAC触发:
DTSELx[2:0]=000,触发源为TIMER5_TRGO,属于内部片上信号;
DTSELx[2:0]=001,互联型产品的触发源为TIMER2_TRGO;非互联型产品的触发源为TIMER7_TRGO,属于内部片上信号;
DTSELx[2:0]=010,触发源为TIMER6_TRGO,属于内部片上信号;
DTSELx[2:0]=011,触发源为TIMER4_TRGO,属于内部片上信号;
DTSELx[2:0]=100,触发源为TIMER1_TRGO,属于内部片上信号;
DTSELx[2:0]=101,触发源为TIMER3_TRGO,属于内部片上信号;
DTSELx[2:0]=110,触发源为EXTI9,属于外部信号触发;
DTSELx[2:0]=111,触发源为SWTRIG,属于软件触发;

DAC数据格式
根据选择的配置模式,数据按照下文所述写入指定的寄存器:
8位数据右对齐:用户须将数据写入寄存器DACx_R8DH [7:0]位
12位数据左对齐:用户须将数据写入寄存器DACx_L12DH[15:4]位
12位数据右对齐:用户须将数据写入寄存器DACx_R12DH[11:0]位

DAC0的DAC_CH0映射到DMA1通道2;
DAC1的DAC_CH1映射到DMA1通道3;
*/

#define  DAC1_Buff_Size 32
uint16_t DAC1_Buff[DAC1_Buff_Size]=\
{2048,128,256,384,512,640,768,896,\
1024,1152,1280,1408,1536,1664,1792,1920,\
2048,2176,2304,2432,2560,2688,2816,2944,\
3072,3200,3328,3456,3584,3712,3840,3968};

void DAC1_Receive_DMA1_DMA_CH3_config(void);
void DAC1_Init(void);
void Timer1_Initializtion(uint16_t arr,uint16_t psc);

void DAC1_Receive_DMA1_DMA_CH3_config(void)
{
	dma_parameter_struct dma_init_struct;

	rcu_periph_clock_enable(RCU_DMA1);//使能DMA1时钟

	dma_deinit(DMA1,DMA_CH3);//复位DAM1的通道3

	dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;//DMA传送方向:从内存到外设
	dma_init_struct.memory_addr = (uint32_t)(&DAC1_Buff[0]);   //源数据首地址为:DAC1_Buff[]
	dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;//源数据块地址递增
  dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;//源数据块的数据宽度为16位
	dma_init_struct.number = DAC1_Buff_Size;//源数据块的数据长度

	dma_init_struct.periph_addr = ((uint32_t)(&DAC1_R12DH));//目的数据首地址为:DAC数据寄存器
	dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;//目的数据块地址不递增
	dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;//目的据块的数据宽度为8位

	dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;//超高的优先级
	dma_init(DMA1,DMA_CH3,&dma_init_struct);//使用dma_init_struct数据结构初始化DMA1通道3

	dma_circulation_enable(DMA1,DMA_CH3);//使能"DMA1通道3循环工作模式"
//	dma_circulation_disable(DMA1,DMA_CH3);//不使能"DMA1通道3循环工作模式"
	dma_memory_to_memory_disable(DMA1,DMA_CH3);//不使能"DMA1通道3内存到内存传输模式"

  dma_channel_enable(DMA1,DMA_CH3);

	dac_dma_enable(DAC1);
	//使能DMA和DAC之间的传输,enable DAC DMA function
	//这个必须要
}

void DAC1_Init(void)
{
	rcu_periph_clock_enable(RCU_GPIOA);//使能GPIOA时钟
	rcu_periph_clock_enable(RCU_DAC);  //使能DAC时钟

	gpio_init(GPIOA,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ,GPIO_PIN_5);
	//将GPIOA5设置为模拟输出口,最大输出速度为50MHz

	dac_deinit();//复位DAC

	dac_trigger_source_config(DAC1,DAC_TRIGGER_T1_TRGO);
	//设置触发源:定时器1触发
	dac_trigger_enable(DAC1);//打开DAC1触发功能
//  dac_trigger_disable(DAC1);//关闭DAC1触发功能

	dac_wave_mode_config(DAC1,DAC_WAVE_DISABLE);//DAC_WAVE_DISABLE表示不使用波形发生器

	dac_output_buffer_disable(DAC1);
	//不允许"直接将DAC1数据寄存器的值转换为电压输出"
	//需要通过触发源触发,才可以输出电压值
//	dac_output_buffer_enable(DAC1);
	//不用通过触发源触发,直接将DAC1数据寄存器的值转换为电压输出

  dac_enable(DAC1);//使能DAC1

  DAC1_Receive_DMA1_DMA_CH3_config();

  Timer1_Initializtion(50000,6480);//当arr=50000,psc=6480时,则为3000ms,误差为10us;
//  Timer1_Initializtion(19,0);//当arr=50000,psc=6480时,则为3000ms,误差为10us;
}

//函数功能:通用定时器1更新事件作为DAC1的触发源
//arr:自动重装值。
//psc:时钟预分频数
//Timer1_Initializtion(50000,6480);//当arr=50000,psc=6480时,则为3000ms,误差为10us;
//Timer1_Initializtion(50000,1080);//当arr=50000,psc=1080时,则为500ms,误差为10us;
void Timer1_Initializtion(uint16_t arr,uint16_t psc)
{
	timer_parameter_struct TimerParameterStruct;

	rcu_periph_clock_enable(RCU_TIMER1);
	nvic_irq_enable(TIMER1_IRQn, 2U, 0U);  //设置TIMER1_IRQn的中断优先级,抢占优先级为2,子优先级为0

	timer_deinit(TIMER1);//复位TIMER1

	TimerParameterStruct.period            = arr-1;//设置在下一个更新事件装入活动的自动重装载寄存器周期的值
	TimerParameterStruct.prescaler         = psc-1;//设置用来作为TIMx时钟频率除数的预分频值(APB2时钟分频值)
  TimerParameterStruct.clockdivision     = TIMER_CKDIV_DIV1;//设置时钟分母值为1
	//计算公式:arr*psc/108000000/1,当arr=250,psc=108时,则为0.25ms,误差为1us;
	TimerParameterStruct.counterdirection  = TIMER_COUNTER_UP;//设置计数方向为"向上计数"
	TimerParameterStruct.alignedmode       = TIMER_COUNTER_EDGE;//设置为无中央对齐计数模式(边沿对齐模式)
	timer_init(TIMER1, &TimerParameterStruct);

	timer_master_output_trigger_source_select(TIMER1,TIMER_TRI_OUT_SRC_UPDATE);
	//输出的更新事件作为触发器输出,update event as trigger output
	timer_update_event_enable(TIMER1);//定时器更新事件使能

	timer_counter_value_config(TIMER1,0);//设置TIMERx的计数器初始值为0
	//timer_counter_read(timer_periph);//读取TIMERx的计数器值

  timer_auto_reload_shadow_enable(TIMER1);//使能TIMERx自动重装载

	timer_flag_clear(TIMER1,TIMER_FLAG_UP);               //清除"TIMERx更新标志位"
	timer_interrupt_flag_clear(TIMER1,TIMER_INT_FLAG_UP); //清除"TIMERx更新中断标志位"
	timer_interrupt_enable(TIMER1,TIMER_INT_UP);          //使能"TIMERx更新"产生中断

  timer_internal_clock_config(TIMER1);//设置"内部时钟"作为定时器时钟
	//timer_slave_mode_select(timer_periph,TIMER_SLAVE_MODE_DISABLE);
	//设置"关闭从模式",如果TIMER计数器使能,则预分频器直接由内部时钟驱动

	timer_enable(TIMER1);//TIMERx计数器使能,开始工作
}

//函数功能:TIMER1更新中断服务程序
void TIMER1_IRQHandler(void)
{
	uint16_t d;

	if( timer_interrupt_flag_get(TIMER1,TIMER_INT_FLAG_UP) )// 读取更新中断标志位
	{
		d=dac_output_value_get(DAC1);//读取DAC1的值
		printf("\r\nd=%f v",3.3*( (float)d/4096 ));

		timer_flag_clear(TIMER1,TIMER_FLAG_UP);//清除"TIMER1更新标志位"
	}
  timer_interrupt_flag_clear(TIMER1,TIMER_INT_FLAG_UP); //清除"更新中断标志位"
}

 

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

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

相关文章

Git命令详解

1 常用命令 1&#xff09;初始化本地仓库 git init <directory> 是可选的&#xff0c;如果不指定&#xff0c;将使用当前目录。 2&#xff09;克隆一个远程仓库 git clone <url> 3&#xff09;添加文件到暂存区 git add <file> 要添加当前目录中的所…

概念解析 | 长尾分布:从无处不在的‘少数派’中挖掘价值

注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:长尾分布(Long-Tail Distribution)。 揭秘长尾分布:从无处不在的‘少数派’中挖掘价值 What is a Long Tail Distribution? (Definition & Example) - Statology 一、背…

Neo4j的使用场景_以及Windows版安装_欺诈检测_推荐_知识图谱---Neo4j图数据库工作笔记0003

可以看到使用场景,比如欺诈检测, 要建立图谱,才能进行,欺诈人员检测 可以看到图谱的各种应用场景 然后推荐引擎也需要,可以看到 在金融,旅行,求职招聘,保健,服务,媒体娱乐,都可以进行推荐 然后还有知识图谱 身份访问管理,这里,可以进行安全管理,可以挖掘出潜在关系,分析, 某…

Android学习之路(4) UI控件之Button (按钮)与 ImageButton (图像按钮)

本节引言&#xff1a; 今天给大家介绍的Android基本控件中的两个按钮控件&#xff0c;Button普通按钮和ImageButton图像按钮&#xff1b; 其实ImageButton和Button的用法基本类似&#xff0c;至于与图片相关的则和后面ImageView相同&#xff0c;所以本节 只对Button进行讲解&am…

Spring Security实现办公系统权限控制(含认证和授权流程、底层分析)

一、Spring Security介绍 1、Spring Security简介 Spring 是非常流行和成功的 Java 应用开发框架&#xff0c;Spring Security 正是 Spring 家族中的成员。Spring Security 基于 Spring 框架&#xff0c;提供了一套 Web 应用安全性的完整解决方案。 正如你可能知道的关于安全…

stop job is running for Advanced key-value store

今天虚拟机磁盘撑满了&#xff0c;本来还能凑合运行&#xff0c;结果重启了下&#xff0c;就报了这个 stop job is running for Advanced key-value store (1min 59s / no limit) 解决方式很简单&#xff0c; 1、虚拟机关电源&#xff0c;任务管理器&#xff0c;关闭VM&#x…

Spring Security用户授权

用户认证在上一篇用户认证 用户授权 总体流程&#xff1a; 在SpringSecurity中&#xff0c;会使用默认的FilterSecurityInterceptor来进行权限校验。在FilterSecurityInterceptor中会从SecurityContextHolder获取其中的Authentication&#xff0c;然后获取其中的权限信息。…

Linux(进程控制)

进程控制 进程创建fork函数初识fork函数返回值写时拷贝fork常规用法fork调用失败的原因 进程终止进程退出码进程常见退出方法 进程等待进程等待必要性获取子进程status进程等待的方法 阻塞等待与非阻塞等待阻塞等待非阻塞等待 进程替换替换原理替换函数函数解释命名理解 做一个…

Java 并发编程--Volatile、Synchronized和锁

一、Java内存模型&#xff08;JMM&#xff09; Java内存模型即Java Memory Model&#xff0c;简称JMM。JMM定义了Java 虚拟机(JVM)在计算机内存(RAM)中的工作方式。JVM是整个计算机虚拟模型&#xff0c;所以JMM是隶属于JVM的。 从抽象的角度来看&#xff0c;JMM定义了线程和主…

react-native-webview使用postMessage后H5不能监听问题(iOS和安卓的兼容问题)

/* 监听rn消息 */ const eventListener nativeEvent > {//解析数据actionType、extraconst {actionType, extra} nativeEvent.data && JSON.parse(nativeEvent.data) || {} } //安卓用document&#xff0c;ios用window window.addEventListener(message, eventLis…

verilog学习笔记6——锁存器和触发器

文章目录 前言一、锁存器1、基本SR锁存器——或非门实现2、基本SR锁存器——与非门实现3、门控SR锁存器4、门控D锁存器 二、触发器1、 电平触发的RS触发器/同步SR触发器2、电平触发的D触发器/D型锁存器3、边沿触发的D触发器4、脉冲触发的RS触发器 三、边沿触发、脉冲触发、电平…

LVS-DR集群(一台LVS,一台CIP,两台web,一台NFS)的构建

一.构建环境 1.五台关闭防火墙&#xff0c;关闭selinux&#xff0c;拥有固定IP&#xff0c;部署有http服务的虚拟机&#xff0c;LVS设备下载ipvsadm工具&#xff0c;NFS 设备需要下载rpcbind和nfs-utils 2.实现功能 3.ipvsadm命令部分参数介绍 二.配置和测试 1.LVS设备 &…

re学习(32)【绿城杯2021】babyvxworks(浅谈花指令)

链接&#xff1a;https://pan.baidu.com/s/1msA5EY_7hoYGBEema7nWwA 提取码&#xff1a;b9xf wp:首先找不到main函数&#xff0c;然后寻找特殊字符串&#xff0c; 交叉引用 反汇编 主函数在sub_3D9当中&#xff0c;但是IDA分析错了 分析错误后&#xff0c;删除函数 创建函数 操…

Python学习笔记_基础篇(六)_Set集合,函数,深入拷贝,浅入拷贝,文件处理

1、Set基本数据类型 a、set集合&#xff0c;是一个无序且不重复的元素集合 class set(object):"""set() -> new empty set objectset(iterable) -> new set objectBuild an unordered collection of unique elements."""def add(self, *a…

人工智能时代的科学探索 | 《自然》评述

人工智能(AI)正越来越多地融入科学发现&#xff0c;以增强和加速研究&#xff0c;帮助科学家提出假设、设计实验、收集和解释大型数据集&#xff0c;并获得仅靠传统科学方法可能无法实现的洞察力。 过去十年间&#xff0c;AI取得了巨大的突破。其中就包括自监督学习和几何深度学…

LabVIEW开发最小化5G系统测试平台

LabVIEW开发最小化5G系统测试平台 由于具有大量存储能力和数据的应用程序的智能手机的激增&#xff0c;当前一代产品被迫提高其吞吐效率。正交频分复用由于其卓越的品质&#xff0c;如单抽头均衡和具有成本效益的实施&#xff0c;现在被广泛用作物理层技术。这些好处是以严格的…

Image Super-Resolution Using Deep Convolutional Networks-SRCNN

Some words&#xff1a; 这里是一些阅读文章的笔记&#xff0c;这篇文章是第一篇将深度学习应用于超分领域的文章&#xff0c;具有较为重要的意义。 &#xff08;一&#xff09;Abstract&#xff1a; 我们提出一个对于单图像超分的深度学习方法&#xff0c;端到端地学习高低分…

C语言编程:最小二乘法拟合直线

本文研究通过C语言实现最小二乘法拟合直线。 文章目录 1 引入2 公式推导3 C语言代码实现4 测试验证5 总结 1 引入 最小二乘法&#xff0c;简单来说就是根据一组观测得到的数值&#xff0c;寻找一个函数&#xff0c;使得函数与观测点的误差的平方和达到最小。在工程实践中&…

无线液位传感器VS有线液位传感器,优点在哪里?

无线技术在催生新行业诞生的同时&#xff0c;也在不断促使着很多传统设备做出新的改变&#xff0c;包括在工业领域中常用到的液位传感器。 无线液位传感器与有线液位传感器相比&#xff0c;最大的优点就在于使用方便。 在传输上做到无线&#xff1a;无线液位传感器可以选择两…

Acwing C++

756. 蛇形矩阵 题解&#xff1a; 蛇形矩阵走法&#xff1a;右 -> 下 ->左 ->上 坐标变化&#xff1a;(x2,y2) (x1,y1) (dx[d] dy[d]) d步数变化&#xff1a;d (d 1)%4 dx[4],dy[4] 分别用来存放xy偏移量&#xff0c;d初始值为0&#xff0c;在两种情况下会1&#…