You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何利用STM32G4的DAC与DMA生成三角波叠加正弦波

问题描述

我拥有一块STM32G4 nucleo开发板,希望利用STM32G4的DAC和DMA生成由~1Hz三角波与500Hz正弦波叠加而成的波形。请问能否从单个DAC通道输出该叠加波形?我已计算出正弦波单周期查找表,并将其叠加到斜线上,但发现仅能生成上升沿和下降沿各带一个正弦周期的三角波。相关代码如下:

#define dac_buf_len 200
HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_2, (uint32_t *) dac, dac_buf_len,DAC_ALIGN_12B_R);

//generate sine wave
for (uint32_t i=0; i < dac_buf_len; i++)
{
    float s = (float) i/(float)(dac_buf_len-1);
    dac_sin[i] = sine_amplitude * sin(2*M_PI*s);    //one cycle of sine wave
}

//generate triangular wave (ramp up)
for (uint32_t i=0; i<dac_buf_len/2; i++)
{
    dac_triangular[i] = 0.006*i - 0.5;
}

//generate triangular wave (ramp down)
for (uint32_t i=0; i<dac_buf_len/2; i++)
{
    dac_triangular[100+i] = -0.006*i + 0.1;
}

//sum two waves together
for (uint32_t i=0; i< dac_buf_len; i++)
{
    dac[i] = dac_sin[i] + dac_triangular[i];
}

解决方案

完全可以从单个DAC通道输出这两种波形的叠加,问题出在当前的波形生成逻辑没有匹配两个信号的频率关系:

1Hz三角波的周期是1秒,500Hz正弦波的周期是2ms,意味着在三角波的1秒周期内,需要包含500个正弦波周期。而你的代码中,仅在200点的buffer里生成了1个正弦周期,导致三角波半周期(0.5秒)内只有1个正弦周期,这就是你看到的现象。

修正步骤

1. 确定DAC输出速率

通过定时器触发DAC的DMA请求,设定触发频率(即每个DAC采样点的输出速率)。例如,设置触发频率为100kHz,每个点的输出时间是10μs,1秒需要100000个采样点,刚好匹配1Hz三角波的周期。

2. 匹配波形的采样点数量

  • 三角波:1秒周期,分成上升沿(0.5秒)和下降沿(0.5秒),各需要50000个点
  • 正弦波:500Hz,每个周期需要200个点(100kHz / 200 = 500Hz),1秒内刚好是500个周期(500×200=100000点)

3. 修正代码逻辑

以下是调整后的代码示例(假设12位DAC输出范围为0~4095,可根据实际幅度需求调整):

// 总采样点:100kHz触发下,1秒输出完,对应1Hz三角波
#define DAC_BUF_LEN 100000
// 正弦波每个周期的采样点:100kHz/200=500Hz
#define SINE_CYCLE_POINTS 200

// 定义buffer(建议用全局变量,避免栈溢出)
float dac_sin[DAC_BUF_LEN];
float dac_triangular[DAC_BUF_LEN];
uint32_t dac[DAC_BUF_LEN];

// 生成正弦波:1秒内500个周期
for (uint32_t i = 0; i < DAC_BUF_LEN; i++)
{
    // 计算当前点在正弦周期内的相位
    float phase = (2 * M_PI * (i % SINE_CYCLE_POINTS)) / SINE_CYCLE_POINTS;
    // 正弦幅度设为DAC量程的1/4(可调整)
    dac_sin[i] = (4095.0 / 4) * sin(phase);
}

// 生成三角波:上升沿(0~4095,0.5秒)
for (uint32_t i = 0; i < DAC_BUF_LEN / 2; i++)
{
    // 线性从0上升到4095
    dac_triangular[i] = (4095.0 / (DAC_BUF_LEN / 2 - 1)) * i;
}

// 生成三角波:下降沿(4095~0,0.5秒)
for (uint32_t i = 0; i < DAC_BUF_LEN / 2; i++)
{
    uint32_t idx = DAC_BUF_LEN / 2 + i;
    // 线性从4095下降到0
    dac_triangular[idx] = 4095.0 - (4095.0 / (DAC_BUF_LEN / 2 - 1)) * i;
}

// 叠加波形并转换为12位DAC格式(确保值在0~4095范围内,避免削波)
for (uint32_t i = 0; i < DAC_BUF_LEN; i++)
{
    float sum = dac_sin[i] + dac_triangular[i];
    // 限制范围,防止超出DAC输出能力
    sum = (sum < 0) ? 0 : sum;
    sum = (sum > 4095) ? 4095 : sum;
    // 转换为12位右对齐格式
    dac[i] = (uint32_t)sum;
}

// 启动DAC DMA循环输出(需确保DMA设置为循环模式)
HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_2, dac, DAC_BUF_LEN, DAC_ALIGN_12B_R);

额外注意事项

  • DMA循环模式:需在CubeMX中设置DAC的DMA为循环模式,确保buffer重复输出,得到连续波形。
  • 定时器配置:配置定时器触发DAC的频率为100kHz(可根据实际需求调整,只要满足三角波周期1秒、正弦波500Hz的比例即可)。
  • 幅度调整:根据实际需求修改正弦波和三角波的幅度,叠加后不要超出DAC的输出范围(0~4095),否则会出现削波失真。

内容的提问来源于stack exchange,提问作者jlim14

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 13:50:18