RISVC_SPWM使用参考


REVISION HISTORY

Revision No.
Description
Date
1.0
  • Initial release
  • 09/06/2024
    1.1
  • 调整目录层级和完善FAQ描述
  • 04/14/2025

    1. 概述

    SPWM(Sinusoidal Pulse Width Modulation)是一种脉宽调制技术,常用于交流电机驱动和逆变器控制中。它通过将直流电压转换为接近正弦波形的交流电压,实现对交流电机速度和功率的精确控制。

    SPWM技术基于PWM(Pulse Width Modulation,脉宽调制)原理,但不同于传统的方波PWM,它使用一系列的窄脉冲来模拟正弦波形。这些窄脉冲的脉宽和频率可以通过合理的调节来产生接近正弦波的输出。

    1.1. 调制过程

    以载波频率为正弦波频率的8倍(即调制指数=8)为例,调制过程可以解释如下:

    将正弦波分成八个相等的段,并用数字<1>至<8>标记每个段;

    根据自动控制中面积相等的原理,调整方波(红色突出部分)的占空比,使其面积与每个区间内正弦波(蓝色突出部分)下方的面积相匹配。 例如图中区间<1>所示,对电机的控制效果是等价的。 通过这种方法,我们可以通过使用一系列方波来达到与正弦波相同的控制效果。

    1.2. 电机控制

    以两相四线电机为例,有四个端子:A- A+ B- B+。 A-和A+结合形成A相正弦波,而B-和B+结合形成B相正弦波。 A相和B相之间的相位差为90°。 正弦波的频率越高,电机速度越快。

    三相电机与两相电机类似,主要区别在于三相电机具有三相,且相邻相之间的相位差为60°。

    2. 功能描述

    • 支持SPWM的channel数量为18个,其中channel 0~17需要加入各自的Group,详见Group与channel对应关系,正常情况使用时需要将4个channel或者6个channel均加入group,以电机控制的角度来看,最大支持3个两相四线电机和1个三相六线电机(如果使用4个两相四线电机,那么剩余的两个channel可以当作PWM使用)

    • SPWM载波频率为50Hz~50KHz,支持的OSCCLK(Hz)为:86M、24M、12M、6M、3M、1.5M、750K

    • 正弦波不能失真,即当前正弦波周期结束后周期及占空比等新配置才会生效

    • SPWM支持的调制模式为Full-wave modeHalf-wave modeSymmetric half-wave mode,对应的最大调制指数为64、128、256

    • 同组SPWM共用一份duty table,最大支持16bit * 64个duty的配置,即一个调制周期最大支持64个不同的占空比设定

    • 支持相位调整,即可以选择duty table中的任意一个duty作为起始点开始输出SPWM

    • 支持scale功能,即可以对duty table内的所有duty配置缩放比例,可用于调整调制波的幅度

    • 支持clamp功能,即可以对占空比设置钳位,当duty<=下限时占空比为0,当duty>=上限时占空比为100%,可用于死区保护

    • 支持round功能,即同Group内的SPWM会在产生特定数量的脉冲后停止

    • 支持stop功能,即同Group内的SPWM会紧急停止

    3. 相关概念说明

    3.1. 调制模式和调制指数

    • Full-wave mode,全波模式

      一个正弦周期的最大值为64个载波周期(调制指数最大可设置为64),每个载波周期都生效duty,按照duty table的设定顺序输出占空比

    • Half-wave mode,半波模式

      一个正弦周期的最大值为128个载波周期(调制指数最大可设置为128),前64个载波周期均生效duty,按照duty table的设定顺序输出占空比,后64个载波周期的duty为0

    • Symmetric half-wave mode,对称半波模式

      一个正弦周期的最大值为256个载波周期(调制指数最大可设置为256),第1~64个载波周期均生效duty,按照duty table的设定顺序输出占空比,第65~128个载波周期均生效duty,按照duty table设定的相反顺序输出占空比,与前64个载波周期形成对称,第128~256个载波周期的duty为0

    • Duty Table

      每组spwm共用一份duty table,可以抽象理解为一个数组,最大可以存储64个duty值,spwm启动时会按照duty table的顺序依次在每个载波周期输出对应的duty;

      Full-wave mode举例,调制指数设定为10,初始相位为0,那么spwm就会按照duty table的duty0~duty9输出波形;调制指数设定为64,那么spwm就会按照duty table的duty0~duty63输出波形;Full-wave mode的调制指数不支持设定值大于64;

      Half-wave mode举例,调制指数设定为10,初始相位为0,那么spwm第1~10个载波周期就会按照duty table的duty0duty9输出波形,第1120个载波周期的duty为0;调制指数设定为128,那么spwm第1~64个载波周期就会按照duty table的duty0duty63输出波形,第65128个载波周期的duty为0;Half-wave mode的调制指数不支持设定值大于128;

    3.2. scale功能

    占空比缩放功能,可以快速调整调制波的幅度

    以OSCCLK为12MHz,载波周期为50KHz,scale设定的缩放比例为原先的50%,duty的变化情况如下:

    duty index 原始占空比 缩小50%的占空比
    0 250 ns 83 ns
    1 500 ns 250 ns
    2 750 ns 335 ns
    3 1000 ns 500 ns
    4 1250 ns 585 ns
    5 1500 ns 750 ns
    6 1750 ns 835 ns
    7 2000 ns 1000 ns
    8 2250 ns 1085 ns
    9 2500 ns 1250 ns

    请注意占空比是12MHz的整数倍,因此scale转换后,不是整数倍的占空比会被向下取整

    3.3. clamp功能

    占空比钳位模式,当duty<=下限时占空比为0,当duty>=上限时占空比为100%

    以OSCCLK为12MHz,载波周期为50KHz,duty table设定的占空比范围250ns16000ns,占空比钳位上下限设定为1000012000ns,输出的波形如下:

    3.4. GROUP相关概念

    3.4.1. Sync mode

    sync mode可以将每个spwm channel加入到各自的group群组中,完成同时对多个spwm进行控制的目的,一个group有4个或6个spwm channel,且group与channel对应关系如下:

    Group Group Member
    Group0 SPWM0、SPWM1、SPWM2、SPWM3
    Group1 SPWM4、SPWM5、SPWM6、SPWM7
    Group2 SPWM8、SPWM9、SPWM10、SPWM11
    Group3 SPWM12、SPWM13、SPWM14、SPWM15、SPWM16、SPWM17

    可通过SYSDESC配置选择是否将spwm加入到Group中:

    <pwm0>
        [reg_u32_u16] 0x2203200 0x40;
        ......
        [group_u32] 0xFFFF;
        [spwm_group_u32] 0;
        ......
    
    <pwm1>
        [reg_u32_u16] 0x2203240 0x40;
        ......
        [group_u32] 0xFFFF;
        [spwm_group_u32] 0;
        ......
    
    <pwm2>
        [reg_u32_u16] 0x2203280 0x40;
        ......
        [group_u32] 0xFFFF;
        [spwm_group_u32] 0;
        ......
    
    <pwm3>
        [reg_u32_u16] 0x22032C0 0x40;
        ......
        [group_u32] 0xFFFF;
        [spwm_group_u32] 0;
        ......
    
    <pwm4>
        [reg_u32_u16] 0x2203400 0x40;
        ......
        [group_u32] 1;
        [spwm_group_u32] 0xFFFF;
        ......
    
    <pwm5>
        [reg_u32_u16] 0x2203440 0x40;
        ......
        [group_u32] 1;
        [spwm_group_u32] 0xFFFF;
        ......
    
    <pwm6>
        [reg_u32_u16] 0x2203480 0x40;
        ......
        [group_u32] 1;
        [spwm_group_u32] 0xFFFF;
        ......
    
    <pwm7>
        [reg_u32_u16] 0x22034C0 0x40;
        ......
        [group_u32] 1;
        [spwm_group_u32] 0xFFFF;
        ......
    
    <pwm8>
        [reg_u32_u16] 0x2203800 0x40;
        ......
        [group_u32] 0xFFFF;
        [spwm_group_u32] 0xFFFF;
        ......
    
    <pwm9>
        [reg_u32_u16] 0x2203840 0x40;
        ......
        [group_u32] 0xFFFF;
        [spwm_group_u32] 0xFFFF;
        ......
    

    SYSDESC PWM节点配置spwm_group_u32则使能spwm功能并加入spwm group,比如pwm0pwm3都配置了[spwm_group_u32] 0并且[group_u32] 0xFFFF,那么pwm0pwm3都将赋予spwm功能并加入spwm group0,需要遵循spwm的特性与设定,因此可将spwm_group_u32理解为spwm的功能开关;

    SYSDESC PWM节点配置group_u32则使能pwm功能并加入pwm group,比如pwm4pwm7都配置了[group_u32] 1并且[spwm_group_u32] 0xFFFF,那么pwm4pwm7都将赋予pwm功能并加入pwm group1,此时无法使用spwm的功能;

    SYSDESC PWM节点配置[group_u32] 0xFFFF[spwm_group_u32] 0xFFFF,比如pwm8和pwm9,那么pwm8和pwm9只能当作普通的pwm使用;

    3.4.2. Round mode

    round功能会在同spwm group内的所有spwm channel完成一定数量的脉冲后停止,每组spwm group都有自己独立的round功能,如下图,spwm group0使用full wave mode,round设定为64,因此实际输出64个脉冲后波形停止

    3.4.3. Stop mode

    stop功能可以让当前spwm group中的所有spwm channel立即停止(不会等当前周期完成)并维持结束时的电平,每组spwm group都有自己独立的stop功能。

    注意:stop 时间不建议太长,尤其是停止后维持的电平为高电平时


    4. 硬件连接说明

    PIN脚复用为PWM MODE后,已经处于output状态,为了保护电路,请不要外灌电压;同时硬件会根据寄存器设定输出PWM波形或者SPWM波形,可根据需要接入负载

    5. RISCV用法介绍

    5.1 DRIVER PATH

    sc/driver/sysdriver/pwm/drv/pub/drv_pwm.h
    sc/driver/sysdriver/pwm/drv/src/drv_pwm.c
    sc/driver/sysdriver/pwm/drv/src/drv_spwm_test.c
    sc/driver/sysdriver/pwm/hal/chipname/src/hal_pwm.c
    sc/driver/sysdriver/pwm/hal/chipname/inc/hal_pwm.h
    sc/driver/sysdriver/pwm/hal/chipname/inc/hal_pwm_cfg.h
    

    5.2. CONFIG配置

    config文件位于mak/options_chipname_riscv_isw.mak,使能CONFIG_PWM_SUPPORTCONFIG_SSTAR_SPWMCONFIG_SSTAR_PWM_EXTEND

    # Feature_Name = [DRV] PWM driver support
    # Description = PWM driver support
    # Option_Selection = TRUE, FALSE
    CONFIG_PWM_SUPPORT = TRUE       //使能PWM驱动
    CONFIG_SSTAR_SPWM  = TRUE       //使能SPWM功能
    CONFIG_SSTAR_PWM_EXTEND = TRUE  //SPWM仅支持高精度模式
    

    5.3 SYSDESC配置

    chipname_xxx.sys文件是用于描述外设硬件属性的文件,外设节点中包含的属性值可用于外设的配置,类似Linux的设备树,该文件位于sc/driver/sysdriver/sysdesc/hal/chipname/pub, 下文以pwm0举例:

    <pwm0>
        [reg_u32_u16] 0x2203200 0x40;
        [interrupts_u32] INT_IRQ_PWM_GROUP0;
        [camclk_u16] CAMCLK_pwm;
        [group_u32] 0xFFFF;
        [spwm_group_u32] 0;
        [clk_level_u8] 0;
        [status_u8] 0;
    

    pwm驱动中支持配置的属性如下表:

    属性 描述 设定值 备注
    reg_u32_u16 指定bank地址 0x2203200 禁止修改
    interrupts_u32 指定硬件中断号 INT_IRQ_PWM_GROUP0 禁止修改
    camclk_u16 指定时钟源 CAMCLK_pwm 禁止修改
    group_u32 选择是否加入pwm group 使能spwm必须将此属性设为0xFFFF 加入group或加入spwm group只能二选一
    spwm_group_u32 选择是否加入spwm group 按照Group与channel对应关系赋值相应的group index,0xFFFF表示不加入 加入group或加入spwm group只能二选一
    clk_level_u8 选择时钟源 pwm017可选06分别对应12M/6M/3M/1.5M/750K/86M/ 24M pwm0~17选择必须一致
    status_u8 选择是否使能驱动 1:enable;0:disable 可根据需要修改

    5.4 PADMUX配置

    CONFIG配置:CONFIG_PADMUX_SUPPORT=TRUE

    如果chipname_xxx.sys文件配置了属性<padmux>,那么PADMUX的设定直接在此配置:

    <padmux>
        [schematic_u32_u32_u32]
                  PAD_GPIOC_00   PINMUX_FOR_PWM0_MODE_1    MDRV_PUSE_PWM0,
                  PAD_GPIOC_01   PINMUX_FOR_PWM1_MODE_1    MDRV_PUSE_PWM1,
                  PAD_GPIOC_02   PINMUX_FOR_PWM2_MODE_1    MDRV_PUSE_PWM2,
                  PAD_GPIOC_03   PINMUX_FOR_PWM3_MODE_1    MDRV_PUSE_PWM3,
                  PAD_GPIOC_04   PINMUX_FOR_PWM4_MODE_1    MDRV_PUSE_PWM4,
                  PAD_GPIOC_05   PINMUX_FOR_PWM5_MODE_1    MDRV_PUSE_PWM5,
                  PAD_GPIOC_06   PINMUX_FOR_PWM6_MODE_1    MDRV_PUSE_PWM6,
                  PAD_GPIOC_07   PINMUX_FOR_PWM7_MODE_1    MDRV_PUSE_PWM7,
                  PAD_GPIOC_08   PINMUX_FOR_PWM8_MODE_1    MDRV_PUSE_PWM8,
                  PAD_OUTP_CH0   PINMUX_FOR_PWM9_MODE_1    MDRV_PUSE_PWM9,
                  PAD_GPIOA_00   PINMUX_FOR_PWM10_MODE_2   MDRV_PUSE_PWM10,
                  PAD_GPIOA_01   PINMUX_FOR_PWM11_MODE_2   MDRV_PUSE_PWM11,
                  PAD_GPIOA_02   PINMUX_FOR_PWM12_MODE_2   MDRV_PUSE_PWM12,
                  PAD_GPIOA_03   PINMUX_FOR_PWM13_MODE_2   MDRV_PUSE_PWM13,
                  PAD_GPIOA_04   PINMUX_FOR_PWM14_MODE_2   MDRV_PUSE_PWM14,
                  PAD_GPIOA_05   PINMUX_FOR_PWM15_MODE_2   MDRV_PUSE_PWM15,
                  PAD_GPIOA_06   PINMUX_FOR_PWM16_MODE_2   MDRV_PUSE_PWM16,
                  PAD_GPIOA_07   PINMUX_FOR_PWM17_MODE_2   MDRV_PUSE_PWM17,
                  ......
        [status_u8] 1;
    

    否则通过使能PADMUX驱动,在chipname-xxx-padmux.c文件配置引脚复用功能,该文件位于sc/driver/sysdriver/padmux/hal/chipname/src,只需要在对应的schematic属性添加如下内容中设定:

    pad_info_t schematic[] =
    {
          {PAD_GPIOC_00   PINMUX_FOR_PWM0_MODE_1    MDRV_PUSE_PWM0},
          {PAD_GPIOC_01   PINMUX_FOR_PWM1_MODE_1    MDRV_PUSE_PWM1},
          {PAD_GPIOC_02   PINMUX_FOR_PWM2_MODE_1    MDRV_PUSE_PWM2},
          {PAD_GPIOC_03   PINMUX_FOR_PWM3_MODE_1    MDRV_PUSE_PWM3},
          {PAD_GPIOC_04   PINMUX_FOR_PWM4_MODE_1    MDRV_PUSE_PWM4},
          {PAD_GPIOC_05   PINMUX_FOR_PWM5_MODE_1    MDRV_PUSE_PWM5},
          {PAD_GPIOC_06   PINMUX_FOR_PWM6_MODE_1    MDRV_PUSE_PWM6},
          {PAD_GPIOC_07   PINMUX_FOR_PWM7_MODE_1    MDRV_PUSE_PWM7},
          {PAD_GPIOC_08   PINMUX_FOR_PWM8_MODE_1    MDRV_PUSE_PWM8},
          {PAD_OUTP_CH0   PINMUX_FOR_PWM9_MODE_1    MDRV_PUSE_PWM9},
          {PAD_GPIOA_00   PINMUX_FOR_PWM10_MODE_2   MDRV_PUSE_PWM10},
          {PAD_GPIOA_01   PINMUX_FOR_PWM11_MODE_2   MDRV_PUSE_PWM11},
          {PAD_GPIOA_02   PINMUX_FOR_PWM12_MODE_2   MDRV_PUSE_PWM12},
          {PAD_GPIOA_03   PINMUX_FOR_PWM13_MODE_2   MDRV_PUSE_PWM13},
          {PAD_GPIOA_04   PINMUX_FOR_PWM14_MODE_2   MDRV_PUSE_PWM14},
          {PAD_GPIOA_05   PINMUX_FOR_PWM15_MODE_2   MDRV_PUSE_PWM15},
          {PAD_GPIOA_06   PINMUX_FOR_PWM16_MODE_2   MDRV_PUSE_PWM16},
          {PAD_GPIOA_07   PINMUX_FOR_PWM17_MODE_2   MDRV_PUSE_PWM17},
          ......
    };
    

    第一列为引脚索引号,可以在sc/drivers/sysdriver/gpio/hal/chipname/pub/gpio.h中查询;

    第二列为模式定义,可以在sc/drivers/sysdriver/gpio/hal/chipname/pub/padmux.h中查询;

    第三列为引脚及搭配模式的索引名称,可以在sc/drivers/sysdriver/padmux/drv/pub/drv_puse.h中查询;

    5.5. Sample Code

    demo源码位于sc/driver/sysdriver/pwm/drv/src/drv_spwm_test.c

    6. API参考

    头文件位于sc/driver/sysdriver/pwm/drv/pub/drv_pwm.h

    struct spwm_gp_cfg
    {
        u8  mode;       //调制模式
        u8  step;       //初始相位
        u8  scale;      //duty缩放比例n,按n/8计算
        u32 group;      //spwm group id
        u8  enable;     //1:enable
        u64 period;     //spwm载波周期,以ns为单位
        u8  clamp_en;   //使能duty钳位功能
        u8  duty_len;   //duty table使用的length
        u64 duty[64];   //duty table的设定,最大64个
        u32 round_num;  //设置round的脉冲数量
        u64 clamp_max;  //钳位上限
        u64 clamp_min;  //钳位下限
    };
    
    extern int drv_spwm_update_period(u32 group, u64 period);
    extern int drv_spwm_set_sram_duty(u32 group, u8 index, u64 duty_ns);
    extern int drv_spwm_update_duty(u32 group, u8 index, u8 len, u64 *duty_ns);
    extern int drv_spwm_set_group_config(struct spwm_gp_cfg *gp_cfg);
    extern int drv_spwm_get_group_config(struct spwm_gp_cfg *gp_cfg);
    extern int drv_spwm_stop_enable(u32 group, u8 stop_en);
    extern int drv_spwm_round_enable(u32 group, u32 round_num);
    

    6.1. drv_spwm_set_group_config

    • 目的

      配置spwm group属性

    • 语法

      int drv_spwm_set_group_config(struct spwm_gp_cfg *gp_cfg)
      
    • 参数

      参数名称 描述
      gp_cfg 用于配置spwm group的调制模式,初始相位,duty table,载波周期等属性
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    6.2. drv_spwm_get_group_config

    • 目的

      获取当前spwm group的属性配置

    • 语法

      int drv_spwm_get_group_config(struct spwm_gp_cfg *gp_cfg)
      
    • 参数

      参数名称 描述
      gp_cfg 用于获取spwm group的调制模式,初始相位,duty table,载波周期等属性
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    6.3. drv_spwm_update_period

    • 目的

      更新spwm group的载波周期

    • 语法

      int drv_spwm_update_period(u32 group, u64 period)
      
    • 参数

      参数名称 描述
      group 选择要使能spwm波形的group
      period 载波周期,以ns为单位
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    6.4. drv_spwm_set_sram_duty

    • 目的

      更新spwm duty table指定下标的单个duty值

    • 语法

      int drv_spwm_set_sram_duty(u32 group, u8 index, u64 duty_ns)
      
    • 参数

      参数名称 描述
      group 选择要使能spwm波形的group
      index 选择duty table的下标
      duty_ns 设定占空比,以ns为单位
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    6.5. drv_spwm_update_duty

    • 目的

      更新spwm duty table指定下标的length个duty值

    • 语法

      int drv_spwm_update_duty(u32 group, u8 index, u8 len, u64 *duty_ns);
      
    • 参数

      参数名称 描述
      group 选择要使能spwm波形的group
      index 选择duty table的下标,作为起始更新点
      len 设定此次更新的duty个数
      duty_ns 占空比数组的地址
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    6.6. drv_spwm_stop_enable

    • 目的

      使能stop功能

    • 语法

      int drv_spwm_stop_enable(u32 group, u8 stop_en)
      
    • 参数

      参数名称 描述
      group 选择要使能停止功能的group
      stop_en 1:enable,波形停止;0:disable,波形恢复
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    6.7. drv_spwm_round_enable

    • 目的

      设置round mode运行的pwm周期数

    • 语法

      int drv_spwm_round_enable(u32 group, u32 round_num)
      
    • 参数

      参数名称 描述
      group 选择使能round mode的group
      round_num 指定pwm周期数
    • 返回值

      结果 描述
      成功 返回0
      失败 返回负数

    7. FAQ

    Q1:SPWM Device不存在

    1. 检查SYSDESC PWM节点的status是否为1

    2. 检查SYSDESC PWM节点spwm-group属性,应配置为0/½/3

    3. 检查SYSDESC PWM节点group属性,应配置为0xFFFF

    4. 检查config是否配置,详见[5.2. CONFIG配置]

    Q2:配置后SPWM无波形产生

    1. 首先确认测量的引脚是否正确:打开对应的原理图确认

    2. 确认对应的PWM mode是否生效,引脚复用失败主要有两个原因:

      原因一:该引脚没有设置为PWM mode,设置方法详见[PADMUX配置]

      原因二:有优先级比PWM mode更高级别的padmux mode被开启

    3. 检查相关参数是否设置成功

      可调用drv_spwm_get_group_config获取当前的配置是否正确