欢迎关注 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 为起点,而非开发板方式。
进入 MCU 选择界面
启动 STM32CubeMX2,在首页点击 MCU,进入芯片型号选择列表。搜索并选中芯片
在 MCU name 输入框中输入 STM32C542RC(或完整型号 STM32C542RCT6),从筛选出的列表中选择对应型号。
- 填写项目信息
输入项目名称 DAC_Output 和项目保存路径。项目名称避免使用特殊字符,路径建议使用纯英文目录。
3.2 基础配置
工程创建后,软件自动进入 Pinout 视图。
时钟配置:本工程系统时钟为48 MHz(HSI ÷ 3),DAC 内核时钟为144 MHz(PSIS 时钟),预分频系数为 1。
3.3 GPIO 配置(PA5 输出)
- 在 Pinout 视图中找到PA5引脚。
- 右键点击 PA5,选择Assign signal→GPIO。
- 再次右键点击 PA5,选择Configure GPIO,进入 GPIO 详细配置界面。
- 将 PA5 的Mode设置为Output。
- 保持默认参数:Output level 为 Low,Output mode 为 Push Pull,Pull-up/Pull-down 为 No pull-up and no pull-down,Maximum output speed 为 Low。
- 在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 项目配置
- 点击Project Settings,进入工程设置页面。
- 在IDE Format下拉选项中选择CMake。
- 在CMake Toolchain下拉选项中选择GCC。
- 确认配置无误后,点击Generate Code。CubeMX2 会执行配置检查,如果没有错误,开始在指定路径下生成 CMake 工程文件。
- 生成完成后,项目路径下会出现标准 CMake 工程结构,包含
Core/、Drivers/、CMakeLists.txt等。
4. 编程实现
4.1 实现思路
采用“DAC 无触发启动 + 主循环更新转换值 + PA5 同步翻转”的方案:
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)文件头部添加宏定义与变量
/* Private define ------------------------------------------------------------*//* DAC1 channel 1 (12-bit, right-aligned) output value range */#defineDAC_MIN_VALUE0U#defineDAC_MAX_VALUE4095U#defineDAC_STEP_VALUE128U/* step per update -> sawtooth resolution *//* Private variables ---------------------------------------------------------*/statichal_dac_handle_t*hDAC1_handle=NULL;(2)主函数
intmain(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_tdac_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 编译与烧录
- 打开工程:用 VS Code 打开 CubeMX2 生成的 CMake 工程文件夹(如 DAC_Output_cmake)。
- 编译:点击 VS Code 底部状态栏的Build按钮,或使用命令面板执行 CMake 构建。编译完成后,终端应输出
退出代码为 0,无报错提示。 - 连接开发板:用支持数据传输的 USB Type-C 线连接 NUCLEO-C542RC 的 ST-LINK USB 口(CN1)。
- 确认设备识别:打开设备管理器,在“端口 (COM 和 LPT)”下应能看到STLink COMx。
- 烧录:点击 VS Code 中的运行按钮,将固件下载到开发板。
5.2 运行与测试
烧录完成后,点击 VS Code 中的 Run 按钮,程序开始运行。使用双通道示波器观测 PA4 和 PA5 的波形。
测试方法:用示波器验证波形与同步关系
- 双通道示波器:CH1 接 PA4,CH2 接 PA5(共地,3.3 V 量程)。
- 观察 CH1:应观察到阶梯式上升后跳变回落的锯齿波。
- 观察 CH2:应观察到方波。
- 验证同步:以 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