【STM32 CubeMX】DAC 输出正弦波

本篇实现效果, 预览:

目录

一、前言

二、正弦波频率公式

[三、CubeMX 配置](#三、CubeMX 配置)

[1、DAC 基础 配置](#1、DAC 基础 配置)

[2、DMA 传输 配置](#2、DMA 传输 配置)

[3、TIM 定时器 配置](#3、TIM 定时器 配置)

[四、代码实现 --- 正弦表数组法输出信号](#四、代码实现 --- 正弦表数组法输出信号)

1、波形样本数组

2、启动定时器、DAC的DMA传输

3、运行效果

五、进阶---频率调整实战

[1、 编写可调式波形函数](#1、 编写可调式波形函数)

2、实例一:输出100kHz正弦波(高频挑战)

3、实例二:输出500Hz正弦波(低频实现)


一、前言

使用 数模转换器 (DAC) 生成高精度模拟波形 是一项常见需求。

本文将示范一种高效、可靠的正弦波生成方案:

利用定时器 (TIM) 自动触发 DAC 转换,并由 DMA 直接搬运波形数据

该方案能最大限度地解放CPU资源,确保输出连续、精准的正弦波信号。

为帮助读者循序渐进地掌握,教程将分为两个核心部分:

  1. 基础实践:通过STM32CubeMX的图形化配置,快速实现一个预设频率(10kHz)正弦波的输出,了解完整操作流程。
  2. 进阶应用:深入讲解波形数据表的动态生成方法与频率计算公式,实现目标频率的正弦波输出。

本文所有示例及方法均提供开源程序以供验证与参考,如有疑问或建议,欢迎交流指正。

开源程序: 【STM32 CubeMX】 DAC 输出正弦波 (已设置0积分。如发现下载需要积分,请通知修改)

实验器材:

实验器材 备注说明 链接
STM32F407VE 开发板 F4系列DAC共两个通道(PA4, PA5) 【链接】
示波器 带宽50MHz、采样率1Gsa/s 【链接】
探头 使用1X档位 机配

二、正弦波频率公式

在开始操作之前,先看看正弦波频率的计算公式:

  • 正弦波频率 = TIM时钟频率 ÷ PSC ÷ ARR ÷ 波点数

|-------------|--------------------------|
| 正弦波频率 | 希望输出的正弦波频率(单位:Hz) |
| TIM时钟频率 | 触发DAC的定时器的时钟频率(单位:Hz) |
| PSC | 定时器时钟的预分频器值 |
| ARR | 定时器的自动重载值。多少个定时器脉冲触发一次事件 |
| 波点数 | 一个正弦波周期的采样点数(波形数据表的长度) |

实例计算:输出10kHz正弦波

为了让大家更直观地理解,以STM32F407为例,规划一组参数来实现 10kHz 的正弦波。

  • 正弦波频率: 10,000 Hz

  • **TIM 时钟频率:**本篇使用 TIM6 。通常,F103的TIM6是72MHz, F407的TIM6是84MHz。

  • **PSC 预分频器:**通常设置为1,即不分频,以方便计算,并获得最高的触发频率。

  • **ARR 周期值:**分频后的TIM时钟,产生N个脉冲数后,触发一次DAC转换。

  • 波点数:这里用128,即一个正弦波由128个样本点组成 。样本点数越多,波形越细腻。

现在,公式中的5个成员,仅剩 ARR 为未知数。

我们将数值代入公式进行计算 (正弦波频率 = TIM时钟频率 ÷ PSC ÷ ARR ÷ 波点数):

10000 = 84000000 ÷ 1 ÷ ARR ÷ 128

计算过程:ARR = 84000000 ÷ 1 ÷ 128 ÷ 10000 = 65.625

寄存器值必须是整数 ,取整 ARR = 66

因此,实际的波形频率将是:正弦波频率 = 84000000 ÷ 1 ÷ 66 ÷ 128 = 9943Hz

这与我们的目标10kHz存在微小误差,这是由于ARR必须为整数所致。

解释、提示

设计目标是输出 10,000 Hz 的正弦波,但根据最终参数计算出的实际频率约为 9,943 Hz

这不是错误,而是一个刻意展示的关键现象。

寄存器值必须是整数。当ARR的计算不能整除,取整后,将无法实现精准波形频率的输出!

不必担心,这种微小的误差(约0.57%)在绝大多数应用中是完全可以接受的。

下文也将详细示范如何通过联动调整样本点数(波点数)与 ARR,来寻找最优解,从而实现对特定目标频率的精准输出。


三、CubeMX 配置

本节基于一个已建立的CubeMX工程进行讲解。若需了解新建工程的基础操作,可参考:

以下将在现有工程基础上,添加正弦波生成所需的DAC、DMA 和 TIM 配置。

1、DAC 基础 配置

实现步骤:

  • 使能:打勾通道
  • Output Buffer:Disable 禁用
  • Trigger:Timmer 6 Trigger Out event

解释、 提示

1、输出通道 OUT1、OUT2

STM32系列的大部分型号,DAC通常包含两个独立通道:

  • OUT1 对应引脚 PA4
  • OUT2 对应引脚 PA5

勾选需要的通道后,CubeMX 会自动配置对应引脚的工作模式,无需手动设置

为演示方便,本示例同时启用了两个通道。

2、Output Buffer (输出缓冲器):Disable。

这个功能很有意思 。好些网上教程对此项的描述过于偏理论了。稍作解释。

把这个"输出缓冲器"理解为:在DAC核心与输出引脚之间,有一个片内集成运算放大器。

输出的信号是否启用 (经过) 这个 输出缓冲放大器,是影响输出性能的关键选择。

使能--输出缓冲 Enabled

  • 优势:提供更大的驱动电流,可直接驱动如耳机、小功率扬声器等负载;
  • 缺点:略有噪声、输出电压范围受限(约0.2V~3.1V)
  • 适用场景:长电缆驱动、耳机、功率器件等对驱动能力要求高而对精度要求不严的场合

禁用--输出缓冲 Disabled

  • 优势:噪声更低、线性度更好、输出电压范围更宽(接近0V~VDDA)
  • 缺点:驱动负载时需外接运放电路
  • 适用场景:高精度测量、传感器校准、示波器等需要满幅输出的应用

本篇是把信号直接输出至示波器探头,因此禁用输出缓冲器: Disabled。

3、Trigger (触发源): Timer 6 Trigger Out event。

为使DAC能自动、周期性地进行转换,需要为其配置一个硬件触发源。

此处选择 Timer 6 Trigger Out event。

触发源在项目中用得比较少,这里也稍作解释。

每当Timer的计数器达到设定值,产生"更新事件"(Update Event)时,通过内部的TRGO线路向外发送一个脉冲信号。DAC被连接至此脉冲信号后,每个脉冲都会自动启动一次DAC转换。

结合下面的DMA功能,CPU只需启动传输,即可由定时器"指挥"DMA将波形数据数组自动、同步地搬运给DAC,从而高效、精准地输出连续波形,无需CPU持续干预

2、DMA 传输 配置

实现步骤:

  • 点击Add: 添加DAC1、DAC2
  • Mode: Circular
  • Memory: 打勾
  • 数据宽度: HalfWord

注意!别漏了添加DAC2,不然PA5会没信号输出。

解释、 提示

1、Mode 传输模式

  • Circular 循环传输 --- 输出连续波形必需
  • 每当 DMA 传输完指定数量的数据后,会重新、从头开始传输。这是输出连续、周期性波形 (如正弦波)的必需设置

2、Increment Address 地址增量控制

  • Peripheral 外设地址:不勾选。DAC数据寄存器是硬件,地址是固定的。
  • Memory 内存地址:勾选 。波形数组地址自动递增。

3、Data Width 数据宽度

  • Half Word :**半字, 16位。**DAC 的数据寄存器是 12 位,用16 位即可对齐访问。
  • 程序中的波形样本数组,应定义为uint16_t类型,与此处设置保持一致

3、TIM 定时器 配置

实现步骤:

  • 使能 TIM6:勾选 Activated
  • PSC (预分频器值): 1-1 (TIM的分频从0起,0即1分频,即不分频)
  • ARR (周期脉冲数):66-1 (TIM计数从0起; 即66个脉冲为一周期)
  • Trigger Event Selection (触发事件):Update Event (更新事件)

解释、 提示

TIM的配置,目的是将定时器配置为一个精准的"节拍器",每个"节拍"(更新事件), 触发DAC进行一次转换。

1、为什么上图里用 n-1 的写法? 而不直接写 0、65?

因为定时器硬件的计数机制是从0开始的。

寄存器值 = 期望值 - 1 。

权威解释请参阅《STM32参考手册》中关于TIM寄存器 TIMx_PSCTIMx_ARR 的详细描述。

2、TIM 的使能方式

在CubeMX中,使能定时器的方式因TIM而异,常见有三种:

  • Activated 复选框:勾选即可使能(TIM6、TIM7等基础定时器)
  • Internal Clock 复选框:勾选即可使能内部时钟(部分通用定时器)
  • Clock Source 多选框:选择"Internal Clock"选项(多数高级定时器)

对于本篇使用的TIM6 ,只需勾选Activated复选框即可完成使能。

3、预分频器 ( Prescaler, PSC )

作用:对输入时钟进行分频,得到供给计数器CNT的计数时钟。

每接收 PSC (Prescaler+1)个时钟脉冲,才产生1个计数脉冲。

在使用 TIM 触发 DAC 转换的应用中,通常将 Prescaler设置为 0(PSC=0+1,1分频即不分频)

不分频的好处是简化计算,并允许定时器以最高频率运行。

4、自动重载值 (Period, ARR )

设定定时器的计数周期,是决定触发频率的关键参数。

工作原理

  1. 计数器CNT从0开始,每个脉冲加1
  2. 当CNT值达到ARR设定值时,定时器发生溢出
  3. CNT自动清零,并产生一个更新事件 (Update Event)
  4. 此过程周而复始,形成稳定周期。

数值关系:

  • CubeMX界面或代码里的Period项填写值:66-1
  • 实际寄存器值:65(第66个脉冲溢出触发更新事件)

5、 触发事件选择 ( Trigger Event Selection )

选择:Update Event 更新事件

解释:此配置将定时器内部的更新事件映射到其TRGO(Trigger Output) 引脚上。每次定时器溢出产生更新事件时,都会通过TRGO线路发送一个精准的脉冲信号,用于触发DAC进行数据转换。这些操作将由硬件自动完成。

信号路径

定时器计数溢出 → 产生更新事件 → TRGO输出脉冲 → 触发DAC转换

这种硬件级触发方式确保了转换时序的精确性和稳定性,无需CPU干预。

配置阶段已完成。

点击 "**GENERATE CODE"**按钮,令CubeMX 把 DAC、DMA 、TIM6 的初始化代码生成到工程中。

接下来,我们将进入 代码实现 部分。


四、代码实现 --- 正弦表数组法输出信号

在使用CubeMX完成DAC、DMA和TIM的配置后,用户需要编写的代码量极少。主要步骤为:

  1. 准备正弦波数据表(数组)
  2. 启动定时器(TIM)
  3. 启动DAC的DMA传输

1、波形样本数组

实现步骤:

  • /* USER CODE BEGIN PV *//* USER CODE END PV */之间,添加正弦波数据数组。
cpp 复制代码
#define WAVE_POINTS    128         // 正弦波一个周期的采样点数

/* 1、正弦波数据表 (12位DAC,数值范围0~4095)
 * 使用数组法的优点:减少每次启动时的计算时间,保证波形精度
 * 注意事项:若将数组定义在函数内部,建议使用static修饰,避免栈溢出
 */
static const uint16_t sineData[WAVE_POINTS] =     
{
    /* 0°~90° 上升段 (n=0~31) */
    2048, 2148, 2248, 2348, 2447, 2545, 2642, 2737,
    2831, 2923, 3013, 3100, 3185, 3267, 3346, 3423,
    3495, 3565, 3630, 3692, 3750, 3804, 3853, 3898,
    3939, 3975, 4007, 4034, 4056, 4073, 4085, 4093,

    /* 90°~180° 下降段 (n=32~63) */
    4095, 4093, 4085, 4073, 4056, 4034, 4007, 3975,
    3939, 3898, 3853, 3804, 3750, 3692, 3630, 3565,
    3495, 3423, 3346, 3267, 3185, 3100, 3013, 2923,
    2831, 2737, 2642, 2545, 2447, 2348, 2248, 2148,

    /* 180°~270° 下降段 (n=64~95) */
    2048, 1947, 1847, 1747, 1648, 1550, 1453, 1358,
    1264, 1172, 1082,  995,  910,  828,  749,  672,
     600,  530,  465,  403,  345,  291,  242,  197,
     156,  120,   88,   61,   39,   22,   10,    2,

    /* 270°~360° 上升段 (n=96~127) */
       0,    2,   10,   22,   39,   61,   88,  120,
     156,  197,  242,  291,  345,  403,  465,  530,
     600,  672,  749,  828,  910,  995, 1082, 1172,
    1264, 1358, 1453, 1550, 1648, 1747, 1847, 1947
};

复制添加后,位置如下图:

解释、提示

  • 数组sineData存储了一个完整正弦周期的128个采样点,对应12位DAC的数值范围(0~4095)。
  • 若将数组定义在函数内部,尽量使用static,否则数组会在栈上分配,当样本数组过大时可能导致栈溢出,并且每次函数调用都会重新初始化。
  • 如果想修改波点数,不能直接修改这里的宏定义,还需要波点数重新计算每一个样本值。下文中提供了计算函数。

2、启动定时器、DAC的DMA传输

实现步骤:

  • main函数的/* USER CODE BEGIN 2 *//* USER CODE END 2 */之间(即在while(1)循环之前),添加以下代码:
cpp 复制代码
/* 2、启动定时器 TIM6 */
HAL_TIM_Base_Start(&htim6);                                                                    // 启动TIM。每个更新事件(计数达到一周期),由硬件发出脉冲信号触发DAC转换一次

/* 3、启动DAC的DMA传输 */
HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t *)sine12bit, WAVE_POINTS, DAC_ALIGN_12B_R);  // 启动DAC通道1(对应PA4)的DMA传输
HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_2, (uint32_t *)sine12bit, WAVE_POINTS, DAC_ALIGN_12B_R);  // 启动DAC通道2(对应PA5)的DMA传输

编写后,位置如下图:

解释、提示

1、HAL_TIM_Base_Start(&htim6):启动定时器TIM6

定时器开始从0计数,当计数值达到ARR(即66)时产生更新事件 。

2、HAL_DAC_Start_DMA ( ):启动DAC的DMA传输。

参数依次为:

  • &hdac:DAC句柄
  • DAC_CHANNNEL_1:DAC通道1(对应PA4)
  • (uint32_t*)sineData:波形数据数组的首地址(需转换为uint32_t指针)
  • WAVE_POINTS:传输数据个数(即数组长度)
  • DAC_ALIGN_12B_R:数据右对齐,12位有效位(因为DAC数据寄存器是12位的)

注意:如果只使用一个通道(例如只使用PA4),则只需调用一次HAL_DAC_Start_DMA,并选择对应的通道。

3、运行效果

编译、烧录到STM32F407开发板,

使用示波器采集 PA5 引脚 (或PA4),即可观察到输出的10kHz正弦波。

效果如下:

解释、提示

真实频率应该是9.943KHz,不是10KHz。

上面截图显示10KHz,是因为示波器 Freq 值在小幅跳动,拍照时刚好卡点10K而已。

为什么真实频率是9.943,在上文中已有说明:

因为寄存器必须用整数,而计算结果 ARR=65.6,ARR取值66,因此无法达成10KHz。

可参考下文,通过联动调整样本点数(波点数)与 ARR,寻找最优解,实现精准输出。


五、进阶---频率调整实战

想输出其他频率,只需在核心公式中调整参数即可:

回顾公式:

  • 正弦波频率 = TIM时钟频率 ÷ PSC ÷ ARR ÷ 波点数

当使用相同TIM时钟且PSC=1时,调整原则如下:

  • 提高频率:减小ARR值,或 减小波点数
  • 降低频率:增大ARR值,或 增加波点数

下面通过 100kHz 和 500Hz 两个实例,演示具体操作及常见误区。

1、 编写可调式波形函数

为便于调试,我们将波形生成过程封装为函数,

并把启动TIM启动DAC的DMA传输这两条执行语句,也封装进去,以简化调试过程。

实现步骤:

  • 在 main.c 的 /* USER CODE BEGIN 0 */ 与 /* USER CODE END 0 */ 之间添加函数
cpp 复制代码
/******************************************************************************
 * 函数名 : DAC_SineStart
 * 功  能 : 启动DAC正弦波输出 (动态计算波形表) 
 * 备  注 : 1. 波点数可通过宏定义WAVE_POINTS灵活调整; 
 *          2. 波点数的取值,建议根据 TIM时钟频率即值,如84MHz时钟下,取值21、42、84、168等,能令公式整除,以达到精准的波形频率
 *          2. 输出幅值:[MIN_VALUE, MAX_VALUE](默认 0-4095)
 *          3. 直流偏置:OFFSET(默认 0)
 *          4. TIM6 更新事件触发,DMA 循环模式
 *          5. 上电重新计算表,调试方便;若需提速,可在调试成型后改用 const 静态表
 * 参  数 : 无 (由函数内宏定义控制)
 * 返回值 : 无
 ******************************************************************************/
#include "math.h"

void DAC_SineStart(void)
{
    /* 1、定义参数 */
    #define WAVE_POINTS     128                      // 正弦数据点数; 取值建议根据 TIM时钟频率即值,如84MHz时钟下,取值21、42、84、168等,能令公式整除,以达到精准的波形频率
    #define MIN_VALUE         0                      // 正弦数据最小值; 即,波底的DAC值; 取值范围:0~4095 (对应0V~3.3V); 用于适配不同设备的工作安全范围,减少硬件电路的设计修改;
    #define MAX_VALUE      4095                      // 正弦数据最大值; 即,波顶的DAC值; 取值范围:0~4095 (对应0V~3.3V); 用于适配不同设备的工作安全范围,减少硬件电路的设计修改;
    #define OFFSET            0                      // 偏移量; 控制波形的直流偏置 (垂直位置)
    #define SCALE ((MAX_VALUE - MIN_VALUE) / 2.0)    // 缩放系数; 控制波形的幅度 (振幅大小)
    
    /* 2、开辟缓存 */
    static uint16_t sineData[WAVE_POINTS] = { 0 };   // 存储正弦波点值

    /* 3、生成无缝正弦表
          计算法:上电实时算表
          优点:调试阶段可随时改 WAVE_POINTS / MIN / MAX,方便灵活调试出需要的波形、振幅
          缺点:每次上电运行都得跑一遍 sin(),启动时间随点数线性增加; 调试定型后建议改用 const 静态表,上电即用,零计算延时  
    */
    for (uint16_t i = 0; i < WAVE_POINTS; i++)
    {
        double x = (double)i * (2.0 * 3.14159265 / WAVE_POINTS);              // 周期内均匀采样; 将索引转换为0到2π之间的值
        double sinValue = sin(x);                                             // 计算正弦值
        sineData[i] = (uint16_t)(lround((sinValue + 1.0) * SCALE + OFFSET));  // 缩放和平移正弦值        
        
    }
 
    /* 4、启动 TIM */
    HAL_TIM_Base_Start(&htim6);                                               // 启动TIM。每个更新事件(计数达到一周期),由硬件发出脉冲信号触发DAC转换一次

    /* 5、启动DAC的DMA传输 */
    HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t *)sineData, WAVE_POINTS, DAC_ALIGN_12B_R);    // 启动DAC通道1的DMA传输,数据输出至PA4引脚
    HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_2, (uint32_t *)sineData, WAVE_POINTS, DAC_ALIGN_12B_R);    // 启动DAC通道2的DMA传输,数据输出至PA5引脚
}

解释、提示

  1. sin() 和 lround() 需要添加文件引用: #include "math.h"
  2. 波点样本数,为了示范,也用 128 个波点数。
  3. 其余几个参数用于限制振幅,以适用于不同的方案场景,本篇不述。
  4. 使用这种实时计算波点样本,可便于调试。定型后改为静态const数组能提升性能。

编写后,位置如下图:

实现步骤:

  • 在main函数的初始化后、while之前, 调用刚才编写的函数
cpp 复制代码
 DAC_SineStart();                 // 启动波形输出

编写完成后,位置如下:

2、实例一:输出100kHz正弦波(高频挑战)

初次尝试。

使用100KHz、128个样本点。

参数计算: (TIM6时钟=84MHz、PSC=1、波点数=128、波形频率=100000)

得到 ARR = 84000000 ÷ 1 ÷ 128 ÷ 100000 = 6.56

寄存器必须是整数,取整后 ARR = 7。

如何修改ARR的值呢?两种操作方法:

  • CubeMX修改:打开工程文件夹的ioc文件进入CubeMX,修改TIM的period值为 7-1,生成。
  • 代码修改:在keil里双击打开 tim.c 文件,找到MX_TIM6_Init()函数,修改 Period = 7-1

建议使用修改代码的方法,更省工夫。

操作步骤:

  • 打开tim.c文件,找到TIM的初始化函数:MX_TIM6_Init( )
  • 修改 TIM 初始化中的 htim6.Init.Period = 7-1

修改完成 。

编译、烧录,运行效果如下图:

示波器实测,只有46.7KHz, 远远达不到100Khz!

问题根源DAC转换时间不足!

在调试摸索中总结:F407 的 DAC 的转换时间需90ns

而当前的触发周期:7 ÷ 84MHz ≈ 83ns < 90ns

触发过快 导致了转换错误!

疑惑

这个转换时间的测试数据,与芯片手册中的理论转换时间,差距甚大。

若有朋友知道其中原因,望分享。

正确方案:减少采样点数、加大ARR值

将采样点由128减至42。

参数计算: (TIM6时钟=84MHz、PSC=1、波点数=42、波形频率=100000)

ARR = 84000000 ÷ 1 ÷ 42 ÷ 100000 = 20

操作步骤:

  • 修改 WAVE_POINTS 宏值 为 42
  • 修改 TIM 初始化中的 htim6.Init.Period = 20-1

编写完成后,如下图:

编译、烧录,实现效果如下图:

解释、提示

1、关于波点数、ARR的取值技巧

为了能精准地实现波形频率,关键在于公式中的 ARR 能被整除。

举例,如F4的TIM6,时钟频率是84MHz,波点数取 21、42、84、168等, ARR容易被整除。

2、关于波形频率的上限

细心的朋友应该发现,上图中,波顶和波底,没有达到满幅的3.3V、0V。

这是因为波点数太少了。增大波点数,如168,可令信号无限接近满幅。

但是,这又回到头痛的问题,增大波点数,需要减小ARR值。而当F407的168MHz时钟下,务必注意 ARR >= 8,即 触发时间 > 90ns,否则转换出错。

补充:有些朋友咨询,如何实现1M、4M的波形。不能!!上面100K已经不能满幅了!!

3、实例二:输出500Hz正弦波(低频实现)

高频应用关注转换速度极限,而低频实现则更侧重于波形精度与平滑度

下面以输出500Hz正弦波为例,展示不同采样点数对波形质量的影响及参数调整方法。

参数计算 :(TIM6时钟=84MHz、PSC=1、波点数=42个、波形频率=500Hz)

ARR = 84000000 ÷ 1 ÷ 42 ÷ 500 = 4000

实现步骤:

  • 修改 WAVE_POINTS 宏值为 42
  • 修改 TIM 初始化中的 htim6.Init.Period = 4000-1

编译、烧录运行后,波形效果如下图:

可生成500Hz正弦波,但波形呈明显阶梯状平滑度差

这是因为每个周期仅用42个点来描绘,样本点数过低,导致波形失真严重,无法满足大多数对质量有要求的应用。

改进:增加点数至168点的平滑实现

为提高波形质量,将采样点数增加至168点。

参数计算(TIM6时钟84MHz、PSC=1、波点数168个、波形频率500Hz):

得到 ARR = 84000000 ÷ 168 ÷ 500 = 1000

实现步骤:

  • 修改 WAVE_POINTS 宏值为 168
  • 修改 TIM 初始化中的 htim6.Init.Period = 1000-1

输出效果,如下图:

增加点数后重新运行,波形平滑度得到显著改善。虽然会略微增加内存占用,但对于低频应用,这是提升输出信号质量的必要代价。


至此,我们已完整演示了从固定数组动态计算 、从10kHz100kHz 高频挑战及500Hz 低频实现的全过程。通过调整采样点数(N)定时器周期(ARR) 的配比,即可灵活生成不同频率与精度的正弦波。

教程中的方法、公式及代码均通过实际硬件验证。如有任何疑问或发现错漏,欢迎指正与交流。

相关推荐
十月的皮皮10 小时前
stm20260720-从新手 C 到量产 STM32 工程:程序设计推导指南
c语言·开发语言·stm32·stm32cubemx·hal库
开发笔记-阿牛10 小时前
解析一款有意思的产品||CK6159A语音芯片设计的儿童专注力训练机-舒尔特玩具
stm32·单片机·嵌入式硬件·音频
搞全栈小苏12 小时前
SIMetrix_simplis8.4安装教程——附安装包
stm32·单片机·嵌入式硬件·电力电子
qq_5739678213 小时前
STM32控制器
stm32·单片机·嵌入式硬件
某林21214 小时前
履带小车底盘stm32F103RCT6开发
人工智能·stm32·单片机·嵌入式硬件·架构·人机交互·ros2
做萤石二次开发的哈哈16 小时前
萤石 ERTC Windows SDK 包含哪些类型定义?
stm32·单片机·嵌入式硬件
亿道电子Emdoor16 小时前
【Aitium】PCB导出DXF文件出现eDuplicateRecordName报错
stm32·单片机·嵌入式硬件·altium
巴巴媛6661 天前
STM32学习笔记【38.DHT11实验】
笔记·stm32·学习
深圳市泰凌微电子1 天前
HK航顺 HK32F407RGT7替STM32F405RGT6 微控制器32位MCU
stm32·单片机·嵌入式硬件
小心亦新2 天前
STM32学习16--定时器输出比较2直流电机
stm32·嵌入式硬件·学习