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

使用nRF52系列PWM驱动实现6秒周期正弦PWM波的问题

nRF52生成6秒周期正弦PWM波的周期不符问题解决

问题核心

基于nRF52系列MCU,使用SDK v15.3.0配置250kHz PWM基础时钟、TOP值4167,用360个数据点存储正弦占空比,理论周期应为(4167/250000)*360≈6秒,但实际检测仅约1.2秒。

错误原因分析

  • 序列类型与加载模式不匹配:
    配置的load_mode = NRF_PWM_LOAD_INDIVIDUAL(单通道独立加载模式),但序列却错误使用了p_wave_form指针(对应NRF_PWM_LOAD_COMMON模式的波形结构体数组),而非p_individual指针(对应INDIVIDUAL模式的单通道占空比数组)。这种类型不匹配导致PWM模块错误解析内存数据,有效序列长度远小于预期的360个。
  • 无效TOP值覆盖:
    代码中定义的seq_values_wave_form结构体未被使用,但错误赋值后,PWM会读取到其中的counter_top=4095,覆盖了你配置的top_value=4167,单个PWM周期变为4095/250000≈0.01638秒。再加上类型不匹配导致有效数据点仅72个(360/5),总周期就变成了72*0.01638≈1.18秒,与实测结果吻合。

修正方案

1. 匹配序列类型与加载模式

将序列的values指针改为p_individual,对应INDIVIDUAL加载模式:

// 原错误代码
// seq_wave_form.values.p_wave_form = data;
// 改为
seq_wave_form.values.p_individual = data;

2. 删除无用代码

移除未使用的波形结构体定义,避免混淆:

// 删除该行
// nrf_pwm_values_wave_form_t seq_values_wave_form = {.channel_0 = 0, .counter_top = 4095};

3. 修正占空比缩放逻辑(可选)

原代码中data数组最大值为16368,远大于TOP值4167,会导致正弦波顶部被削平。调整缩放逻辑匹配TOP值:

// 原缩放代码
// uint16_t scaled_value = (uint16_t)((sin_value + 1) * 0x03FF);
// data[i] = scaled_value << 4;
// 改为
uint16_t scaled_value = (uint16_t)((sin_value + 1) * (4167 / 2.0)); // 归一化到0~4167范围
data[i] = scaled_value;

修正后的关键代码片段

uint16_t data[360];
uint16_t duty_cycle;

nrf_pwm_clk_t base_clock;

const nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);

// 移除无用的波形结构体定义
nrf_pwm_values_t seq_pwm_values;
nrf_pwm_sequence_t seq_wave_form;

void pwm_init_config()
{
    uint8_t prescaler_setting = 0;

    switch (prescaler_setting)
    {
    case 0:
        base_clock = NRF_PWM_CLK_250kHz;
        break; // 32MHz / 128
    }

    nrf_drv_pwm_config_t const config0 =
        {
            .output_pins =
                {
                    LED_1,
                    NRF_DRV_PWM_PIN_NOT_USED,
                    NRF_DRV_PWM_PIN_NOT_USED,
                    NRF_DRV_PWM_PIN_NOT_USED,
                },
            .irq_priority = APP_IRQ_PRIORITY_LOWEST,
            .base_clock = base_clock,
            .count_mode = NRF_PWM_MODE_UP,
            .top_value = 4167,
            .load_mode = NRF_PWM_LOAD_INDIVIDUAL,
            .step_mode = NRF_PWM_STEP_AUTO};
    APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL));
}

void initialize_basic_data()
{
    int size = sizeof(data) / sizeof(data[0]);

    for (int i = 0; i < size; i++)
    {
        double radian = i * (M_PI / 180);
        double sin_value = sin(radian);
        // 修正缩放逻辑匹配TOP值
        uint16_t scaled_value = (uint16_t)((sin_value + 1) * (4167 / 2.0));
        data[i] = scaled_value;
    }

    // 使用p_individual指针匹配加载模式
    seq_wave_form.values.p_individual = data;
    seq_wave_form.length = NRF_PWM_VALUES_LENGTH(data);
    seq_wave_form.repeats = 0;
    seq_wave_form.end_delay = 0;
}

void wave_effect()
{
    initialize_basic_data();
    nrf_drv_pwm_simple_playback(&m_pwm0, &seq_wave_form, 1, NRF_DRV_PWM_FLAG_LOOP);
}

验证逻辑

修正后,每个数据点对应一个PWM周期,总周期为360*(4167/250000)=360*0.016668≈6秒,与理论值一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 15:58:10