STM32CubeMX教程16 DAC - 输出3.3V内任意电压

目录

1、准备材料

2、实验目标

3、实验流程

3.0、前提知识

3.1、CubeMX相关配置

3.1.0、工程基本配置

3.1.1、时钟树配置

3.1.2、外设参数配置

3.1.3、外设中断配置

3.2、生成代码

3.2.0、配置Project Manager页面

3.2.1、外设初始化调用流程

3.2.2、外设中断调用流程

3.2.3、添加其他必要代码

4、常用函数

5、烧录验证

6、注释详解


读者可访问 GitHub - lc-guo/STM32CubeMX-Series-Tutorial 获取原始工程代码


1、准备材料

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

STM32CubeMX软件(Version 6.10.0

野火DAP仿真器

keil µVision5 IDE(MDK-Arm

CH340G Windows系统驱动程序(CH341SER.EXE

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 中文参考手册

  • 35
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
您好!对于STM32F407和ETH LWIP,我可以为您提供一些关于TCP client客户端的开发方面的信息。 首先,您需要使用STM32CubeMX软件来配置STM32F407的ETH和LWIP库。在STM32CubeMX中,您可以配置以太网接口和选择使用LWIP协议栈。确保在配置期间启用TCP/IP协议。 一旦配置完成并生成代码,您可以在生成的代码中找到LWIP库的API函数以及以太网驱动程序的相关函数。在这里,您将能够设置和管理TCP连接。 以下是一个简单的TCP客户端示例代码,用于向服务器发送数据: ```c #include "lwip/api.h" #define SERVER_IP "192.168.0.100" #define SERVER_PORT 8080 void tcp_client_task(void *arg) { struct netconn *conn; err_t err; // 创建TCP连接 conn = netconn_new(NETCONN_TCP); if (conn != NULL) { ip_addr_t server_addr; // 设置服务器IP地址和端口 IP4_ADDR(&server_addr, 192, 168, 0, 100); // 连接服务器 err = netconn_connect(conn, &server_addr, SERVER_PORT); if (err == ERR_OK) { const char *data = "Hello, server!"; struct netbuf *send_buf; // 创建发送数据包 send_buf = netbuf_new(); if (send_buf != NULL) { // 将数据添加到发送数据包中 netbuf_ref(send_buf, data, strlen(data)); // 发送数据包 err = netconn_send(conn, send_buf); // 释放发送数据包 netbuf_delete(send_buf); } } // 关闭连接 netconn_close(conn); netconn_delete(conn); } vTaskDelete(NULL); } ``` 请注意,此示例代码仅用于演示目的,您可能需要根据您的具体需求进行修改。另外,还要确保正确初始化LWIP协议栈和以太网接口。 希望这些信息对您有所帮助!如果您有任何进一步的问题,请随时提问。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值