【STM32C5教程】(9)DAC 模拟量信号输出实验

欢迎关注 youcans@xidian【嵌入式软件AI编程】专栏

【STM32C5教程】(4)GPIO 外部中断实验

【STM32C5教程】(5)定时器周期中断实验

【STM32C5教程】(6)定时器 PWM 输出实验

【STM32C5教程】(7)TIM1 互补 PWM 输出实验

【STM32C5教程】(8)ADC 模拟量数据采集实验

【STM32C5教程】(9)DAC 模拟量信号输出实验

1. 项目简介

1.1 实验目标

本实验在 NUCLEO-C542RC 开发板上,使用 STM32C542RCT6 的 DAC1 通道 1 经 PA4 引脚输出模拟电压:周期性更新 DAC 转换值以生成锯齿波,并通过 PA5 引脚指示锯齿波的输出周期。

功能需求:

  • 使用 DAC1 通道 1 经 PA4 输出模拟电压(0 ~ 3.3 V,对应 12 位数值 0 ~ 4095)
  • 采用无触发(软件触发)方式,由程序周期性更新 DAC 转换值生成锯齿波
  • 通过 PA5 引脚指示锯齿波的输出周期:在锯齿波达到最大值(回绕)时翻转 PA5,输出与锯齿波同步的方波
  • 锯齿波与周期指示均为纯软件实现,无中断、无 DMA 参与

开发板和 MCU 型号: NUCLEO-C542RC 开发板,搭载 STM32C542RCT6 MCU。

1.2 实验条件

硬件:

  • NUCLEO-C542RC 开发板
  • 支持数据传输的 USB Type-C 线(用于连接 ST-LINK 接口)
  • 示波器(用于观测 PA4 与 PA5 的输出波形)

软件:

  • STM32CubeMX2(用于引脚、时钟、ADC 配置与代码生成)
  • VS Code + STM32Cube 插件(用于编译、烧录、调试)

2. 硬件说明

2.1 NUCLEO-C542RC 开发板

NUCLEO-C542RC 是 ST 基于 STM32C542RCT6 推出的 Nucleo-64 开发板。主要特性:

  • MCU:STM32C542RCT6,Arm Cortex-M33 内核,最高主频 144 MHz,256 KB Flash,64 KB RAM
  • 调试器:板载 STLINK-V3EC,支持大容量存储、虚拟串口和调试端口三种功能
  • 用户 LED:LD1,连接 PA5
  • 用户按键:B1,连接 PC13
  • 扩展接口:Arduino Uno V3 和 ST morpho 连接器

本实验使用 PA4 作为 DAC 模拟输出,PA5 作为周期指示信号,通过示波器观测。

2.2 引脚说明

引脚 功能 说明
PA4 DAC1_OUT1 DAC1 通道 1,模拟输出
PA5 LD1 板载用户 LED,GPIO 推挽输出,作为周期指示

PA4(DAC1_OUT1):配置为模拟输出。DAC1 通道 1 固定在 PA4 上,这是芯片引脚复用决定的。

PA5(LD1):配置为 GPIO 推挽输出。作为周期指示信号,与 DAC 输出是两路相互独立的信号。

3. STM32CubeMX2 工程配置

3.1 新建工程

本实验采用 MCU 方式创建工程,即以芯片型号 STM32C542RC 为起点,而非开发板方式。

  1. 进入 MCU 选择界面

    启动 STM32CubeMX2,在首页点击 MCU,进入芯片型号选择列表。

  2. 搜索并选中芯片

    在 MCU name 输入框中输入 STM32C542RC(或完整型号 STM32C542RCT6),从筛选出的列表中选择对应型号。

  1. 填写项目信息
    输入项目名称 DAC_Output 和项目保存路径。项目名称避免使用特殊字符,路径建议使用纯英文目录。

3.2 基础配置

工程创建后,软件自动进入 Pinout 视图。

时钟配置 :本工程系统时钟为 48 MHz (HSI ÷ 3),DAC 内核时钟为 144 MHz(PSIS 时钟),预分频系数为 1。

3.3 GPIO 配置(PA5 输出)

  1. 在 Pinout 视图中找到 PA5 引脚。
  2. 右键点击 PA5,选择 Assign signal → GPIO。
  3. 再次右键点击 PA5,选择 Configure GPIO,进入 GPIO 详细配置界面。
  4. 将 PA5 的 Mode 设置为 Output。
  5. 保持默认参数:Output level 为 Low,Output mode 为 Push Pull,Pull-up/Pull-down 为 No pull-up and no pull-down,Maximum output speed 为 Low。
  6. 在 User Label 输入框中填入 LD1。

设置别名后,CubeMX2 会自动生成宏定义 LD1_PORT 和 LD1_PIN。

3.4 DAC1 配置

(1)启用 DAC1

在左侧外设列表中找到 Analog → DAC1 ,点击展开。将 Channel 1 设置为 Connected to external pin only(仅连接到外部引脚)。

设置完成后,Pinout 视图中 PA4 自动分配为 DAC1_OUT1(模拟模式)。

(2)配置 DAC 参数

在 DAC1 的 Parameter Settings 中设置:

参数 值 说明
Output Buffer Enable 输出缓冲开启,带负载能力更强
Trigger None 无触发(软件触发)
Data Alignment 12 bits right 12 位右对齐
Output Connection External 输出连接到外部引脚
High Frequency Mode Auto 高频模式自动选择

(3)确认引脚配置

回到 Pinout 视图,PA4 应显示为 DAC1_OUT1(模拟模式)。

3.5 项目配置

  1. 点击 Project Settings,进入工程设置页面。
  2. 在 IDE Format 下拉选项中选择 CMake。
  3. 在 CMake Toolchain 下拉选项中选择 GCC。
  4. 确认配置无误后,点击 Generate Code。CubeMX2 会执行配置检查,如果没有错误,开始在指定路径下生成 CMake 工程文件。
  5. 生成完成后,项目路径下会出现标准 CMake 工程结构,包含 Core/、Drivers/、CMakeLists.txt 等。

4. 编程实现

4.1 实现思路

采用 "DAC 无触发启动 + 主循环更新转换值 + PA5 同步翻转" 的方案:

text 复制代码
mx_system_init() // CubeMX2 生成:时钟、GPIO(PA4/PA5)、DAC1 初始化
│
▼
mx_dac1_gethandle() // 获取 DAC1 句柄
│
▼
HAL_DAC_SetChannelData() // 先写数据到 DHR(无触发模式要求)
│
▼
HAL_DAC_StartChannel() // 再使能通道,开始转换
│
▼
主循环:周期性地写入递增的转换值,形成锯齿波
│
├─ dac_value += DAC_STEP_VALUE
│
└─ dac_value >= DAC_MAX_VALUE?
├─ 是 → 回绕到最小值,翻转 PA5
└─ 否 → 继续
│
▼
HAL_Delay(2) // 步进延时,决定锯齿波周期

无触发的启动时序 :HAL_DAC_TRIGGER_NONE 模式下,应先 HAL_DAC_SetChannelData() 写入初始值到 DHR,再 HAL_DAC_StartChannel() 使能通道。顺序不可颠倒。

写入立即生效 :无触发模式下,HAL_DAC_SetChannelData() 写入 DHR 后输出电压立即更新,无需等待任何触发事件。这正是能在主循环中"写一次、更新一次"生成锯齿波的原理。

各步骤使用的 HAL 函数:

步骤 HAL 函数 作用
获取 DAC1 句柄 mx_dac1_gethandle() 返回 CubeMX 生成的 DAC1 句柄
写入转换值 HAL_DAC_SetChannelData() 写入 DHR,无触发时立即生效
启动通道 HAL_DAC_StartChannel() 使能 DAC 通道 1
翻转 PA5 HAL_GPIO_TogglePin(LD1_PORT, LD1_PIN) 切换 PA5 输出电平

4.2 关键代码

在 VS Code 中打开生成的 CMake 工程,找到 Core/Src/main.c,添加以下代码。

(1)文件头部添加宏定义与变量

c 复制代码
/* Private define ------------------------------------------------------------*/
/* DAC1 channel 1 (12-bit, right-aligned) output value range */
#define DAC_MIN_VALUE        0U
#define DAC_MAX_VALUE        4095U
#define DAC_STEP_VALUE       128U   /* step per update -> sawtooth resolution  */

/* Private variables ---------------------------------------------------------*/
static hal_dac_handle_t *hDAC1_handle = NULL;

(2)主函数

c 复制代码
int main(void)
{
  if (mx_system_init() != SYSTEM_OK)
  {
    return (-1);
  }

  /* Get the DAC1 handle initialized by mx_dac1_init() */
  hDAC1_handle = mx_dac1_gethandle();
  if (hDAC1_handle == NULL)
  {
    return (-1);
  }

  /* Software (no hardware) trigger: set the initial value into DHR first,
     then enable the channel to start conversion. */
  if (HAL_DAC_SetChannelData(hDAC1_handle, HAL_DAC_CHANNEL_1, DAC_MIN_VALUE) != HAL_OK)
  {
    return (-1);
  }

  if (HAL_DAC_StartChannel(hDAC1_handle, HAL_DAC_CHANNEL_1) != HAL_OK)
  {
    return (-1);
  }

  /* Sawtooth generation: periodically update the DAC conversion value.
     PA5 (LD1) toggles at each period boundary to indicate the output period. */
  uint32_t dac_value = DAC_MIN_VALUE;

  while (1)
  {
    /* Update the DAC data holding register -> immediate output update */
    (void)HAL_DAC_SetChannelData(hDAC1_handle, HAL_DAC_CHANNEL_1, dac_value);

    /* Next step of the rising ramp */
    dac_value += DAC_STEP_VALUE;

    if (dac_value >= DAC_MAX_VALUE)
    {
      /* End of the sawtooth period: wrap to the minimum value */
      dac_value = DAC_MIN_VALUE;

      /* Toggle PA5 to mark one full output period */
      HAL_GPIO_TogglePin(LD1_PORT, LD1_PIN);
    }

    /* Delay between two updates defines the sawtooth step period */
    HAL_Delay(2U);
  }
}

代码说明:

  • mx_dac1_gethandle() 返回 CubeMX2 生成的 DAC1 句柄,返回 NULL 时需处理。
  • HAL_DAC_SetChannelData() 写入 DAC 数据保持寄存器(DHR),无触发模式下写入后立即生效。
  • HAL_DAC_StartChannel() 使能 DAC 通道 1,必须在 HAL_DAC_SetChannelData() 之后调用。
  • 主循环中写入 dac_value 后立即递增,形成锯齿波的上升沿。
  • 当 dac_value 超过 DAC_MAX_VALUE 时,回绕到 DAC_MIN_VALUE,形成锯齿波的回绕跳变。
  • 每次回绕时翻转 PA5(LD1),输出与锯齿波周期同步的方波。

5. 编译烧录与运行测试

5.1 编译与烧录

  1. 打开工程:用 VS Code 打开 CubeMX2 生成的 CMake 工程文件夹(如 DAC_Output_cmake)。
  2. 编译 :点击 VS Code 底部状态栏的 Build 按钮,或使用命令面板执行 CMake 构建。编译完成后,终端应输出 退出代码为 0,无报错提示。
  3. 连接开发板:用支持数据传输的 USB Type-C 线连接 NUCLEO-C542RC 的 ST-LINK USB 口(CN1)。
  4. 确认设备识别 :打开设备管理器,在"端口 (COM 和 LPT)"下应能看到 STLink COMx。
  5. 烧录:点击 VS Code 中的运行按钮,将固件下载到开发板。

5.2 运行与测试

烧录完成后,点击 VS Code 中的 Run 按钮,程序开始运行。使用双通道示波器观测 PA4 和 PA5 的波形。

测试方法:用示波器验证波形与同步关系

  1. 双通道示波器:CH1 接 PA4,CH2 接 PA5(共地,3.3 V 量程)。
  2. 观察 CH1:应观察到阶梯式上升后跳变回落的锯齿波。
  3. 观察 CH2:应观察到方波。
  4. 验证同步:以 PA5 的上升/下降沿为触发,观察 PA4 ------ 每次 PA5 翻转的时刻,恰好对应 PA4 锯齿波达到最大值后回落的时刻。

测试结果:

☑ 编译通过,无错误

☑ 烧录成功

☑ PA4 输出锯齿波

☑ PA5 输出方波,占空比 50%

☑ PA5 在 PA4 达到最大值时翻转,与锯齿波周期边界完全同步

功能正常。

6. 小结

本实验通过 DAC1 通道 1 经 PA4 输出模拟电压,实现了周期性更新转换值生成锯齿波,并通过 PA5 输出与锯齿波同步的方波,掌握了 STM32C5 系列 DAC 的配置与使用方法。

核心逻辑可以概括为:"DAC 无触发启动 → 主循环更新转换值 → 生成锯齿波 → PA5 同步翻转"。

版权声明:

欢迎关注 youcans@xidian【嵌入式软件AI编程】专栏

转发必须注明原文链接:

【STM32C5教程】(9)DAC 模拟量信号输出实验

Copyright by ai4mcu@qq.com 2026

Crated:2026-10

相关推荐
智购科技自动售货机工厂1 小时前
省电40%的底层逻辑:冷热双温售货机基于SaaS的智能温控算法~YH
单片机·嵌入式硬件·百度·架构·emacs
深圳市恒锐丰科技杨生1 小时前
SS6203D 200V 单路半桥栅极驱动芯片|LeadPower 率能半导体
嵌入式硬件·硬件工程
深圳老胡2 小时前
STM32C5 系列 MCU 的 FreeRTOS 软件架构搭建指南:外设配置与应用实践
笔记·stm32·单片机·代码规范
霖霖7142 小时前
【ESP32笔记】I2S的音频录制与播放
笔记·单片机·mcu·音视频
深圳市恒锐丰科技杨生2 小时前
SS6200 半桥栅极驱动芯片|LeadPower 率能半导体
嵌入式硬件·硬件工程
HQB20262 小时前
EG11732|屹晶微电子 30V 内置 80A 功率管大电流同步降压 DC‑DC
嵌入式硬件·硬件工程
LCG米2 小时前
STM32 HardFault故障定位实测:压栈帧寄存器解析、CFSR故障源判读与出错地址回溯
前端·javascript·stm32·单片机·嵌入式
yuehuaxin013 小时前
LP3717BSL 芯茂微|SOP8L 自供电 PSR,SEL 电阻调峰值电流,12W 充电器物料替代评估笔记
嵌入式硬件·适配器模式·智能硬件
G***技13 小时前
杰和科技亮相中国工博会:嵌入式边缘AI驱动自动化场景落地
嵌入式硬件·边缘ai·工博会