weilan 发表于 2024-6-8 02:05:36

STC8H1K17T PLL + PWM问题

      最近用STC8H1K17T做了一无刷电调。需要用到PLL + PWM来实现高频率、高于10位分辨率的互补PWM波。接通电机后,发现电机转动过程中随机出现“抖动”。用示波器抓波形,发现如下现象:








如图所示,黄线为相电压,绿线为进入换相中断时的IO输出。由图可知,大部分的波形都是正常的梯形。但是偶尔会出现图2中的异常波形。从波形分析,看似是某次换相以后,上管的PWM输出突然停在高电平不动,导致上管常通。随着桥驱的自举电容电压下降,上管逐渐关闭而导致电压衰减。其它硬件问题已经被排除。因为当不使用PLL备频,只单独使用PWM时,电机完全可以正常平稳运转,未曾发现上述波形。以下是PWM和PLL相关的配置代码,请各路大神不吝赐教!

1. PLL的配置
void sys_clock_init()
{
    // FOSC = 32 MHz
    CLKSEL   = 0xC0;   // CKMS = 1b 使能PLL输出12倍频FPLL = 10.667 * 12 = 128 MHz, HSIOSK = 1b, 使能PWM时钟为PLL输出时钟
    HSCLKDIV = 0x00; // 分频系数为1
    PLLCR    = 0xC0;   // PCKI = 10 输入频率为FOSC / 3 = 10.667 MHz, ENCKM = 1b, 使能PLL倍频
}
2. 高速PWM的配置
void pwm_init()
{
    u8 i = 0;
      PWM1   = 0;
      PWM1_L = 0;
      PWM2   = 0;
      PWM2_L = 0;
      PWM3   = 0;
      PWM3_L = 0;
   
    // pwm输出口配置为推挽输出
    // 当使用PWMA_ENO禁止某相pwm输出时,io状态由GPIO寄存器控制
    P1M0 |=0xF3;
    P1M1 &= ~0xF3;
    PWMA_PS = 0x00; // C1PS, C3PS, C4PS = 00b,PWMA1输出端口为P1.0 P1.1 P1.4 P1.5 P1.6 P1.7
   
    PWMA_PSCRH = 0x00;
    PWMA_PSCRL = 0x00; // 中央对齐模式时使用
    //PWMA_DTR= 48; // PWM频率为32MHz / 512 / 2 = 31.25kHz
    //PWMA_ARRH = (512 - 1) >> 8;
    //PWMA_ARRL = (512 - 1);
    PWMA_DTR = 32; // PWM频率为 32MHz / 333 / 2 = 48.048kHz
    PWMA_ARRH = (333 - 1) >> 8;
    PWMA_ARRL = (333 - 1);
   
    PWMA_CCER1 = 0x00;
    PWMA_CCER2 = 0x00;
    PWMA_SR1   = 0x00;
    PWMA_SR2   = 0x00;
    PWMA_ENO   = 0x00;
    PWMA_IER   = 0x00;
      
    PWMA_CCMR1 = 0x78;// 输出模式,PWM模式2,使能PWMA_CCR预装载
    PWMA_CCR1H = 0x00;
    PWMA_CCR1L = 0x00;
    SET_BIT(PWMA_CCER1, 0); // 使能PWM1P比较输出,高电平有效
    SET_BIT(PWMA_CCER1, 2); // 使能PWM1N比较输出,高电平有效
   
    PWMA_CCMR3 = 0x78;// 输出模式,PWM模式2,使能PWMA_CCR预装载
    PWMA_CCR3H = 0x00;
    PWMA_CCR3L = 0x00;
    SET_BIT(PWMA_CCER2, 0);
    SET_BIT(PWMA_CCER2, 2);
   
    PWMA_CCMR4 = 0x68;// 输出模式,PWM模式1,使能PWMA_CCR预装载
    PWMA_CCR4H = 0x00;
    PWMA_CCR4L = 0x00;
    SET_BIT(PWMA_CCER2, 4);
    SET_BIT(PWMA_CCER2, 6);   
   
    PWMA_CR1 = 0x00;
    PWMA_BKR = 0x80; // MOEA = 1b, 使能主输出
    PWMA_CR1 = 0xA1; // ARPEA = 1b,使能PWMA_ARR自动重装,CMSA = 01b,中央对齐模式1,CENA = 1b, 开启定时器
    SET_BIT(PWMA_EGR, 0); // 产生更新事件,清零计数器
}

// 异步写入高速PWM寄存器
void pwm_init_hs()
{
    pwm_init();
    PWMA_DTR   =128; // 对应死区时间为 128 / (128MHz) = 1us,PWMA时钟为128MHz
    PWMA_ARRH= (1250 - 1) >> 8; // 对应 128MHz / 1250 / 2 = 51.2 kHz 的PWM波
    PWMA_ARRL= (1250 - 1);

    HSPWMA_CFG = 0x02; // 使能异步控制模式
}

void pwm_hs_write_sfr(u8 addr, u8 val)
{
    while( HSPWMA_ADR & 0x80 );
    HSPWMA_DAT = val;
    HSPWMA_ADR = (addr & 0x7F);
}
3. 电机换相函数
void motor_commute_hspwm()
{
    switch( motor_phase )
    {
      default:
      {
            break;
      }
      case 0: // AB
      {
            //pwm_hs_write_sfr( (u8)&PWMA_ENO, 0x00 );
            //while( HSPWMA_ADR & 0x80 );
            PWM1_L = 0;
            PWM2_L = 0;
            PWM3_L = 0;
            //delay_500ns();
            pwm_hs_write_sfr( (u8)&PWMA_ENO, 0x03 );
            while( HSPWMA_ADR & 0x80 );
            PWM2_L = 1;
            CMP_SET_PHC();
            CMPCR1 = 0x80 + 0x10;
            
            break;
      }
      case 1: // AC
      {
            pwm_hs_write_sfr( (u8)&PWMA_ENO, 0x03 );
            while( HSPWMA_ADR & 0x80 );
            PWM1_L = 0;
            PWM2_L = 0;
            PWM3_L = 0;
            //delay_500ns();
            PWM3_L = 1;
            CMP_SET_PHB();
            CMPCR1 = 0x80 + 0x20;
         
            break;
      }
      case 2: // BC
      {
            //pwm_hs_write_sfr( (u8)&PWMA_ENO, 0x00 );
            //while( HSPWMA_ADR & 0x80 );
            PWM1_L = 0;
            PWM2_L = 0;
            PWM3_L = 0;
            //delay_500ns();
            pwm_hs_write_sfr( (u8)&PWMA_ENO, 0xC0 );
            while( HSPWMA_ADR & 0x80 );
            PWM3_L = 1;
            CMP_SET_PHA();
            CMPCR1 = 0x80 + 0x10;
            
            break;
      }
      case 3: // BA
      {   
            pwm_hs_write_sfr( (u8)&PWMA_ENO, 0xC0 );
            while( HSPWMA_ADR & 0x80 );
            PWM1_L = 0;
            PWM2_L = 0;
            PWM3_L = 0;
            //delay_500ns();
            PWM1_L = 1;
            CMP_SET_PHC();
            CMPCR1 = 0x80 + 0x20;
            
            break;
      }
      case 4: // CA
      {
            //pwm_hs_write_sfr( (u8)&PWMA_ENO, 0x00 );
            //while( HSPWMA_ADR & 0x80 );
            PWM1_L = 0;
            PWM2_L = 0;
            PWM3_L = 0;
            //delay_500ns();
            pwm_hs_write_sfr( (u8)&PWMA_ENO, 0x30 );
            while( HSPWMA_ADR & 0x80 );
            PWM1_L = 1;
            CMP_SET_PHB();
            CMPCR1 = 0x80 + 0x10;
            
            break;
      }
      case 5: // CB
      {
            pwm_hs_write_sfr( (u8)&PWMA_ENO, 0x30 );
            while( HSPWMA_ADR & 0x80 );
            PWM1_L = 0;
            PWM2_L = 0;
            PWM3_L = 0;
            //delay_500ns();
            PWM2_L = 1;
            CMP_SET_PHA();
            CMPCR1 = 0x80 + 0x20;
            
            break;
      }
    }
    if( bmotor_start ) CMPCR1 = 0x80;   
}
我个人的初步判断是,这个高速PWM的异步写入方式可能存在BUG,可能会出现某次调用后,PWM不工作的情况。这导致PWM在某次调用后常开。具体问题请各路大神帮忙分析。

页: [1]
查看完整版本: STC8H1K17T PLL + PWM问题