1.10. MCPWM

mcpwm模块支持两路同时输出pwm,共6组,支持故障保护功能,支持复用。

1.10.1. mcpwm_init

mcpwm功能初始化。

原型:

int mcpwm_init(struct mcpwm_config *mcpwm_cfg);

参数:

mcpwm_cfg

mcpwm配置

返回值

mcpwm配置句柄(id号)

1.10.2. mcpwm_deinit

mcpwm功能初始化取消。

原型:

void mcpwm_deinit(int mcpwm_cfg_id);

参数:

mcpwm_cfg_id

init时返回的句柄(id号)

返回值

1.10.3. mcpwm_start

mcpwm功能启动。

原型:

void mcpwm_start(int mcpwm_cfg_id);

参数:

mcpwm_cfg_id

init时返回的句柄(id号)

返回值

1.10.4. mcpwm_mux_start

mcpwm功能多路同时启动。

原型:

void mcpwm_mux_start(u8 mcpwm_cfg_id_mux);

参数:

1.10.5. mcpwm_pause

mcpwm功能暂停。

原型:

void mcpwm_pause(int mcpwm_cfg_id);

参数:

mcpwm_cfg_id

init时返回的句柄(id号)

返回值

1.10.6. mcpwm_resume

mcpwm功能恢复。

原型:

void mcpwm_resume(int mcpwm_cfg_id);

参数:

mcpwm_cfg_id

init时返回的句柄(id号)

返回值

1.10.7. mcpwm_set_frequencys

设置mcpwm输出频率,单位Hz。

原型:

void mcpwm_set_frequency(int mcpwm_cfg_id, mcpwm_aligned_mode_type align, u32 frequency);

参数:

mcpwm_cfg_id

init时返回的句柄(id号)

align

对齐方式:中心对齐、边沿对齐

frequency

频率,单位:Hz

返回值

1.10.8. mcpwm_set_duty

设置mcpwm输出占空比。

原型:

void mcpwm_set_duty(int mcpwm_cfg_id, u16 duty);
参数:

mcpwm_cfg_id

init时返回的句柄(id号)

duty

占空比,如:5123,51.23%

返回值

1.10.9. mcpwm_set_duty_by_cnt

设置mcpwm输出占空比(以cnt配置)。

原型:

void mcpwm_set_duty_by_cnt(int mcpwm_cfg_id, u16 duty);
参数:

mcpwm_cfg_id

init时返回的句柄(id号)

duty

占空比,cnt形式

返回值

1.10.10. mcpwm参考demo(见mcpwm_demo.c)

int usr_id0;
int usr_id1;
int usr_id2;

void usr_mcpwm_detect_callback(u32 ch)
{
    printf("usr detect ch %d\n", ch);
    mcpwm_fpnd_clr(ch); //检测到故障,手动清PND恢复
}

___interrupt
void mcpwm_timeout_callback(void)
{
    MCPWM_TIMERx_REG *timer_reg = NULL;
    timer_reg = (MCPWM_TIMERx_REG *)(MCPWM_TMR_BASE_ADDR);
    JL_PORTC->DIR &= ~BIT(7);
    if (timer_reg->tmr_con & BIT(MCPWM_TMR_OFPN)) {
        //溢出中断发生在H端低电平中点
        timer_reg->tmr_con |= BIT(MCPWM_TMR_OFCLR);
        JL_PORTC->OUT ^= BIT(7);
    }
    if (timer_reg->tmr_con & BIT(MCPWM_TMR_UFPND)) {
        //借位中断发生在H端高电平中点
        timer_reg->tmr_con |= BIT(MCPWM_TMR_UFCLR);
        JL_PORTC->OUT ^= BIT(7);
    }
}

void mcpwm_test_demo_start(void)
{
    struct mcpwm_config usr_mcpwm_cfg0 = {
        .ch = MCPWM_CH0,                        // 通道号
        .aligned_mode = MCPWM_CENTER_ALIGNED,   // 中心对齐
        .frequency = 1000,                      // 1KHz
        .duty = 5000,                           // 占空比50%
        .h_pin = IO_PORTC_00,                   // 任意引脚
        .l_pin = IO_PORTC_01,                   // 任意引脚,不需要就填0xff
        .complementary_en = 1,                  // 0: 同步, 1: 互补
        .detect_port = MCPWM_FPIN_IO_PORTC_11,  // 故障保护检测IO
        .edge = MCPWM_EDGE_FAILL,                           // 下降沿
        .irq_cb = usr_mcpwm_detect_callback,        // 故障保护回调
        .irq_priority = 1,                          // 优先级默认为1
        .dten = 1,                                                          // 死区使能
        .dtpr = 0,                                                          // 死区时间=Tsys/(2^dtckps)*(dtpr+1)
        .dtckps = 4,                                                        // 时钟分频
        .ofie = 1,                                                          // 溢出中断
        .ufie = 1,                                                          // 借位中断
    };

    struct mcpwm_config usr_mcpwm_cfg1 = {
        .ch = MCPWM_CH1,                        // 通道号
        .aligned_mode = MCPWM_EDGE_ALIGNED,     // 边沿对齐
        .frequency = 1000,                      // 1KHz
        .duty = 5000,                           // 占空比50%
        .h_pin = IO_PORTC_02,                   // 任意引脚
        .l_pin = IO_PORTC_03,                   // 任意引脚,不需要就填0xff
        .complementary_en = 0,                  // 0: 同步, 1: 互补
        .detect_port = MCPWM_FPIN_IO_PORTC_11,  // 故障保护检测IO
        .edge = MCPWM_EDGE_FAILL,                           // 下降沿
        .irq_cb = usr_mcpwm_detect_callback,        // 故障保护回调
        .irq_priority = 1,                          // 优先级默认为1
        .dten = 1,                                                          // 死区使能
        .dtpr = 0,                                                          // 死区时间=Tsys/(2^dtckps)*(dtpr+1)
        .dtckps = 4,                                                        // 时钟分频
        .ofie = 0,                                                          // 溢出中断
        .ufie = 0,                                                          // 借位中断
    };

    struct mcpwm_config usr_mcpwm_cfg2 = {
        .ch = MCPWM_CH2,                        // 通道号
        .aligned_mode = MCPWM_EDGE_ALIGNED,     // 边沿对齐
        .frequency = 1000,                      // 1KHz
        .duty = 5000,                           // 占空比50%
        .h_pin = IO_PORTC_04,                   // 任意引脚
        .l_pin = IO_PORTC_05,                   // 任意引脚,不需要就填0xff
        .complementary_en = 0,                  // 0: 同步, 1: 互补
        .detect_port = MCPWM_FPIN_IO_PORTC_11,  // 故障保护检测IO
        .edge = MCPWM_EDGE_FAILL,                           // 下降沿
        .irq_cb = usr_mcpwm_detect_callback,        // 故障保护回调
        .irq_priority = 1,                          // 优先级默认为1
        .dten = 1,                                                          // 死区使能
        .dtpr = 0,                                                          // 死区时间=Tsys/(2^dtckps)*(dtpr+1)
        .dtckps = 4,                                                        // 时钟分频
        .ofie = 0,                                                          // 溢出中断
        .ufie = 0,                                                          // 借位中断
    };

    // 初始化分配id
    usr_id0 = mcpwm_init(&usr_mcpwm_cfg0);
    usr_id1 = mcpwm_init(&usr_mcpwm_cfg1);
    usr_id2 = mcpwm_init(&usr_mcpwm_cfg2);

#if 0
    // 顺序启动 三通道有相位差
    mcpwm_start(usr_id0);
    mcpwm_start(usr_id1);
    mcpwm_start(usr_id2);
#else
    // 同时启动 三通道无相位差
    mcpwm_mux_start(BIT(usr_id0) | BIT(usr_id1) | BIT(usr_id2));
#endif

    // 频率配置接口测试
    mcpwm_set_frequency(usr_id0, MCPWM_EDGE_ALIGNED, 2000); // 2K
    mcpwm_set_frequency(usr_id1, MCPWM_EDGE_ALIGNED, 4000); // 4K
    mcpwm_set_frequency(usr_id2, MCPWM_EDGE_ALIGNED, 8000); // 8K

#if 0
    // 百分比配置占空比
    mcpwm_set_duty(usr_id0, 2000); // 20%
    mcpwm_set_duty(usr_id1, 4000); // 40%
    mcpwm_set_duty(usr_id2, 8000); // 80%
#else
    // pwm cnt计数配置占空比
    u32 id0_frequency = 2000; // 2K
    u32 id1_frequency = 4000; // 4K
    u32 id2_frequency = 8000; // 8K
    u32 id0_loop_cntmax = clk_get("mcpwm") / id0_frequency;
    u32 id1_loop_cntmax = clk_get("mcpwm") / id1_frequency;
    u32 id2_loop_cntmax = clk_get("mcpwm") / id2_frequency;
    mcpwm_set_duty_by_cnt(usr_id0, id0_loop_cntmax / 10 * 2); // 20%
    mcpwm_set_duty_by_cnt(usr_id1, id1_loop_cntmax / 10 * 4); // 40%
    mcpwm_set_duty_by_cnt(usr_id2, id2_loop_cntmax / 10 * 8); // 80%
#endif

    // 溢出/借位中断测试
    request_irq(IRQ_MCPWM_TMR_IDX, IRQ_MCPWM_TMR_PRIORITY, mcpwm_timeout_callback, 0);
}

void mcpwm_test_demo_stop(void)
{
    mcpwm_deinit(usr_id0);
    mcpwm_deinit(usr_id1);
    mcpwm_deinit(usr_id2);

    unrequest_irq(IRQ_MCPWM_TMR_IDX);
}