1、准备材料

开发板(正点原子stm32f407探索者开发板V2.4

STM32CubeMX软件(Version 6.10.0

keil µVision5 IDE(MDK-Arm

ST-LINK/V2驱动

野火DAP仿真器

XCOM V2.6串口助手

2、实验目标

使用STM32CubeMX软件配置STM32F407开发板的DAC OUT1实现输出0-3.3V任意模拟电压,然后用ADC1_IN5单通道采集DAC输出的电压,并利用USART1输出信息用于验证

3、实验流程

3.0、前提知识

STM32F407有一个DAC,该DAC拥有两个输出通道OUT1/2,每个通道均可以输出0~VREF+范围内电压、噪声波或三角波型

DAC集成了两个输出缓冲器,可用来降低输出阻抗并在不增加外部运算放大器的情况下直接驱动外部负载,该参数可以在STM32CubeMX中DAC参数配置页面配置,一般选择Enable

DAC输出的触发源一共有8个触发源,可以通过设置DAC控制寄存器DAC_CR的TSEL[2:0]位来决定触发源,其中外部引脚触发源在STM32CubeMX中需要勾选Mode中的External Trigger才可以选择,具体如下表所示 (注释1)

DAC的数字转模拟主要是利用片上的12位电压输出数模转换器来实现的,而这个12位电压输出数模转换器的输入数据为数据输出寄存器DORx中的内容,但是用户不能直接将数据写入数据输出寄存器DORx中,而是需要将数据输入数据保持寄存器DHRx中,然后等待触发源到来/一个时钟周期后,数据将自动从DHRx中转移到DORx中

由于DHRx寄存器位32位寄存器,而我们写入的数据为8/12位的,因此存在数据对齐的问题,采用不同的对齐方式需要将数据写入对应对齐方式的数据保存寄存器中,如下图所示为DAC单/双通道模式下的数据对齐模式,每种模式对应1/2个寄存器(注释1)

举个例子:

本实验采取DAC1单通道模式12位右对齐,因此笔者需要将数据写入 DAC_DHR12R1 寄存器中,而该寄存器的偏址从手册上可以看到为0x80

我们写入DAC寄存器数据时使用的函数为HAL_DAC_SetValue(&hdac,DAC_CHANNEL_1,DAC_ALIGN_12B_R,DacValue),其中DAC_ALIGN_12B_R值为0,因此最后将DacValue值写入了地址为DAC基址+0x00000008UL偏址的 DAC_DHR12R1 寄存器,上述描述如下图所示

DAC输出引脚输出的电压值由DACoutput = VREF+ * DOR / 4095公式计算,通常 VREF+直接与VDDA短接,因此DAC通道输出的电压范围为0-3.3V,如下图所示为DAC通道框图 (注释1)

3.1、CubeMX相关配置

3.1.0、工程基本配置

打开STM32CubeMX软件,单击ACCESS TO MCU SELECTOR选择开发板MCU(选择你使用开发板的主控MCU型号),选中MCU型号后单击页面右上角Start Project开始工程,具体如下图所示

开始工程之后在配置主页面System Core/RCC中配置HSE/LSE晶振,在System Core/SYS中配置Debug模式,具体如下图所示

详细工程建立内容读者可以阅读“STM32CubeMX教程1 工程建立

3.1.1、时钟树配置

系统时钟使用8MHz外部高速时钟HSE,HCLK、PCLK1和PCLK2均设置为STM32F407能达到的最高时钟频率,具体如下图所示

3.1.2、外设参数配置

本实验需要需要初始化开发板上KEY2和KEY0用户按键,具体配置步骤请阅读“STM32CubeMX教程3 GPIO输入 - 按键响应

本实验需要需要初始化USART1作为输出信息渠道,具体配置步骤请阅读“STM32CubeMX教程9 USART/UART 异步通信

本实验需要配置TIM3 100ms更新事件作为ADC1_IN5通道采集触发源的ADC采集,因此需要初始化TIM3和ADC1_IN5,具体配置步骤请阅读“STM32CubeMX教程13 ADC - 单通道转换”,如下图所示为配置简图

接下来配置DAC OUT1,在Pinout & Configuration页面左边功能分类栏目Analog中单击其中DAC,在Mode中勾选OUT1 Configuration

在DAC Out1 Settings中使能 Output Buffer , Trigger 选择默认None,这里不需要触发源,也就是说当DAC启动后DAC就会一直输出下去而不是在每次一触发源来到的时候才输出,具体配置如下图所示

3.1.3、外设中断配置

DAC只有两个关于DMA的下溢事件的中断源,本实验尚不设计DMA,因此这里无需开启DAC的任何中断

但是DAC的输出电压需要由ADC1_IN5来采集,因此这里勾选ADC的全局中断,并设置合适的中断优先级,具体配置如下图所示

3.2、生成代码

3.2.0、配置Project Manager页面

单击进入Project Manager页面,在左边Project分栏中修改工程名称、工程目录和工具链,然后在Code Generator中勾选“Gnerate peripheral initialization as a pair of 'c/h' files per peripheral”,最后单击页面右上角GENERATE CODE生成工程,具体如下图所示

详细Project Manager配置内容读者可以阅读“STM32CubeMX教程1 工程建立”实验3.4.3小节

3.2.1、外设初始化调用流程

在生成的工程代码主函数中增加了MX_DAC_Init()函数,该函数对启用的DAC触发方式、输出缓存进行了配置

然后调用HAL_DAC_Init()函数对DAC进行了初始化,并调用了HAL_DAC_MspInit()函数

在HAL_DAC_MspInit()函数中对DAC OUT1的输出引脚PA4做了引脚复用配置,并且使能了DAC的时钟,如果配置了中断,在该函数中还会出现中断优先级及中断使能相关代码

上述DAC初始化调用流程如下图所示

3.2.2、外设中断调用流程

本实验只开启了ADC的全局中断,ADC全局中断调用流程请阅读“STM32CubeMX教程13 ADC - 单通道转换”4.2.2小节

3.2.3、添加其他必要代码

在adc.c中重新实现ADC采集完毕中断回调函数HAL_ADC_ConvCpltCallback(),与”STM32CubeMX教程13 ADC - 单通道转换”实验内容一致,目的就是获取ADC1_IN5通道采集值并通过USART1输出,具体代码如下所示

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
if(hadc->Instance == ADC1)
{
uint32_t val=HAL_ADC_GetValue(&hadc1);
uint32_t Volt=(3300*val)>>12;
printf("val:%d, Volt:%d\r\n",val,Volt);
}
}

在主函数中启动DAC输出,并设置默认的DAC输出值,然后启动定时器和ADC采集,并在主循环中实现按下按键KEY2将DAC输出值增加500,按下按键KEY0将DAC输出值减少500,具体代码如下图所示

源代码如下所示

/*主循环外代码*/
printf("Reset\r\n");
HAL_DAC_Start(&hdac,DAC_CHANNEL_1);
uint32_t DacValue=1000;
HAL_DAC_SetValue(&hdac,DAC_CHANNEL_1,DAC_ALIGN_12B_R,DacValue);
HAL_ADC_Start_IT(&hadc1);
HAL_TIM_Base_Start(&htim3); /*主循环中代码*/
/*按键KEY2被按下*/
if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin) == GPIO_PIN_RESET)
{
HAL_Delay(50);
if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin) == GPIO_PIN_RESET)
{
printf("---now DacValue is: %d---\r\n", DacValue);
DacValue += 500;
if(DacValue>4095) DacValue=4095;
HAL_DAC_SetValue(&hdac,DAC_CHANNEL_1,DAC_ALIGN_12B_R,DacValue);
while(!HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin));
}
} /*按键KEY0被按下*/
if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == GPIO_PIN_RESET)
{
HAL_Delay(50);
if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) == GPIO_PIN_RESET)
{
printf("---now DacValue is: %d---\r\n", DacValue);
DacValue -= 500;
HAL_DAC_SetValue(&hdac,DAC_CHANNEL_1,DAC_ALIGN_12B_R,DacValue);
while(!HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin));
}
}

值得提醒的是本实验使用DAC1_IN5(PA5)采集DAC OUT1(PA4)输出值,需要使用跳线帽/杜邦线将PA5和PA4两个引脚短接

4、常用函数

/*DAC软件启动输出函数*/
HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef *hdac, uint32_t Channel) /*DAC软件停止输出函数*/
HAL_StatusTypeDef HAL_DAC_Stop(DAC_HandleTypeDef *hdac, uint32_t Channel) /*DAC输出值设置*/
HAL_StatusTypeDef HAL_DAC_SetValue(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data)

5、烧录验证

烧录程序,开发板上电后打开串口助手,可以看到间隔100ms输出一次采集到的DAC OU1输出值,默认输出值为1000,按下KEY2按键后输出值增加500,按下KEY0按键后输出值减少500,可以从串口输出信息看到采集到的值和我们预想的效果一致,如下图所示为整个过程串口输出信息

6、注释详解

注释1:图片来源STM32F4xx 中文参考手册

更多内容请浏览 STM32CubeMX+STM32F4系列教程文章汇总贴

STM32CubeMX教程16 DAC - 输出3.3V内任意电压的更多相关文章

  1. stm32 DAC输出音频

    #define DAC_DHR8R1_Address 0x40007410 // Init Structure definition DAC_InitTypeDef DAC_InitStructure ...

  2. [ASP.NET MVC2 系列] ASP.Net MVC教程之《在15分钟内用ASP.Net MVC创建一个电影数据库应用程序》

    [ASP.NET MVC2 系列]      [ASP.NET MVC2 系列] ASP.Net MVC教程之<在15分钟内用ASP.Net MVC创建一个电影数据库应用程序>       ...

  3. node-webkit教程(16)调试typescript

    原文链接:node-webkit教程(16)调试typescript 本文所讲的内容同样适用于chrome浏览器. 在chrome的开发人员工具的配置项中,有一个sourcemap的选项,用来配置ja ...

  4. testng入门教程16数据驱动(把数据写在xml)

    testng入门教程16数据驱动(把数据写在xml) testng入门教程16数据驱动(把数据写在xml)把数据写在xml文件里面,在xml文件右键选择runas---testng执行 下面是case ...

  5. [译]Vulkan教程(16)图形管道基础之总结

    [译]Vulkan教程(16)图形管道基础之总结 Conclusion 总结 We can now combine all of the structures and objects from the ...

  6. Directx11教程(16) D3D11管线(5)

    原文:Directx11教程(16) D3D11管线(5) 本章我们学习VS中具体做些什么事情? 首先再看看我们的VS shader代码: Clolor.vs - PixelInputType Col ...

  7. hdu 4630 查询[L,R]区间内任意两个数的最大公约数

    No Pain No Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  8. 简明Python3教程 16.标准库

    简介 python标准库作为python标准安装的一部分,其自身包含数量庞大的实用模块, 因此熟悉python标准库非常重要,因为很多问题都能利用python标准库快速解决. 下面我们将研究标准库中的 ...

  9. 《Genesis-3D开源游戏引擎完整实例教程-跑酷游戏篇02:内购如何实现》

    2.内购如何实现 内购概述: 游戏内购是指玩家在游戏中,用金钱获取游戏道具的一种方式.开发者从玩家内购之中获得开发游戏的收益,因此大量游戏都有内购模块.下面我们以在手机IOS平台实现跑酷游戏内购为例, ...

  10. Kendo UI开发教程(16): Kendo MVVM 数据绑定(五) Events

    本篇和Kendo UI开发教程(14): Kendo MVVM 数据绑定(三) Click类似,为事件绑定的一般形式.Events绑定支持将ViewModel的方法绑定到DOM元素的事件处理(如鼠标事 ...

随机推荐

  1. AI歌姬,C位出道,基于PaddleHub/Diffsinger实现音频歌声合成操作(Python3.10)

    懂乐理的音乐专业人士可以通过写乐谱并通过乐器演奏来展示他们的音乐创意和构思,但不识谱的素人如果也想跨界玩儿音乐,那么门槛儿就有点高了.但随着人工智能技术的快速迭代,现在任何一个人都可以成为" ...

  2. 《最新出炉》系列初窥篇-Python+Playwright自动化测试-29-处理日历时间控件-中篇

    1.简介 上一篇的日历时间控件宏哥介绍的比较传统也是很常见的.宏哥不能说它很low,但是相比较一些高端.大气.上档次的日历时间控件,结果就一目了然了:确实很low. 2.被测网站 2.1高大上日历时间 ...

  3. logstash 配置文件语法介绍

    大家好,我是蓝胖子,之前在构建服务监控实践那个系列里,有提到用logstash来做日志的收集,但是对于logstash的配置文件语法没有做很详细的介绍,今天就来详细聊聊logstash配置文件的语法. ...

  4. 文心一言 VS 讯飞星火 VS chatgpt (146)-- 算法导论12.2 1题

    一.用go语言,假设一棵二叉搜索树中的结点在1到 1000 之间,现在想要查找数值为 363 的结点.下面序列中哪个不是查找过的序列? a.2,252,401,398,330,344,397,363. ...

  5. 一文带你掌握C语言的分支结构

    C语言分支结构详解 1. if 语句 在本篇博客文章中,我们将深入探讨C语言中的if语句及其相关用法.if语句是一种用于条件判断的分支语句,它允许我们根据条件的真假来执行不同的代码块. 1.1 if ...

  6. 记一次逆向分析解密还原Class文件

    前言 前阵子我的一位朋友发来一份代码让我帮忙看看.具体就是所有的jsp文件内容和大小都一样,漏洞挖掘无从下手.经过分析发现所有的Class都使用了自定义的加密工具加密,经过逆向分析,顺利解密,因而有了 ...

  7. # [AI]多模态聚类能力助力AI完成自主意识测试

    引言 探讨人工智能是否能形成自我意识,是一个当前AI领域一个重要而又复杂的问题.随着深度学习和强化学习技术的不断进步,计算机在视觉识别.语音识别和控制机器人等方面都已取得长足的进展,模拟和超越人类的一 ...

  8. Chrome扩展的核心:manifest 文件(上)

    大家好,我是dom哥.我正在写关于 Chrome 扩展开发的系列文章,感兴趣的可以点个小星星. Chrome 在全球浏览器市场份额独占 6 成,无论是对普通用户还是开发者,都是电脑里的必备利器.Chr ...

  9. Mongodb安装篇+可视化工具篇

    下载MongoDB 官网下载地址:Download MongoDB Community Server | MongoDB   Version 选择:稳定版4.4.2 Mongo的版本分为稳定版和开发版 ...

  10. Oracle重做、归档日志

    日志文件 oracle日志文件分为两种: 重做日志文件(redo),或者称为"在线重做日志" 归档日志文件(arch),或者称为"归档重做日志" 在线重做日志文 ...