找回密码
 立即注册
查看: 511|回复: 0

STC8H1K17T PLL + PWM问题

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2024-06-21 21:05:12

2

主题

2

回帖

40

积分

新手上路

积分
40
发表于 2024-6-8 02:05:36 | 显示全部楼层 |阅读模式
        最近用STC8H1K17T做了一无刷电调。需要用到PLL + PWM来实现高频率、高于10位分辨率的互补PWM波。接通电机后,发现电机转动过程中随机出现“抖动”。用示波器抓波形,发现如下现象:


示波器.jpg


示波器2.jpg


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


1. PLL的配置

  1. void sys_clock_init()
  2. {
  3.     // FOSC = 32 MHz
  4.     CLKSEL   = 0xC0;   // CKMS = 1b 使能PLL输出12倍频FPLL = 10.667 * 12 = 128 MHz, HSIOSK = 1b, 使能PWM时钟为PLL输出时钟
  5.     HSCLKDIV = 0x00; // 分频系数为1
  6.     PLLCR    = 0xC0;   // PCKI = 10 输入频率为FOSC / 3 = 10.667 MHz, ENCKM = 1b, 使能PLL倍频
  7. }
复制代码

2. 高速PWM的配置

  1. void pwm_init()
  2. {
  3.     u8 i = 0;
  4.         PWM1   = 0;
  5.         PWM1_L = 0;
  6.         PWM2   = 0;
  7.         PWM2_L = 0;
  8.         PWM3   = 0;
  9.         PWM3_L = 0;
  10.    
  11.     // pwm输出口配置为推挽输出
  12.     // 当使用PWMA_ENO禁止某相pwm输出时,io状态由GPIO寄存器控制
  13.     P1M0 |=  0xF3;
  14.     P1M1 &= ~0xF3;
  15.     PWMA_PS = 0x00; // C1PS, C3PS, C4PS = 00b,PWMA1输出端口为P1.0 P1.1 P1.4 P1.5 P1.6 P1.7
  16.    
  17.     PWMA_PSCRH = 0x00;
  18.     PWMA_PSCRL = 0x00; // 中央对齐模式时使用
  19.     //PWMA_DTR  = 48; // PWM频率为32MHz / 512 / 2 = 31.25kHz
  20.     //PWMA_ARRH = (512 - 1) >> 8;
  21.     //PWMA_ARRL = (512 - 1);
  22.     PWMA_DTR = 32; // PWM频率为 32MHz / 333 / 2 = 48.048kHz
  23.     PWMA_ARRH = (333 - 1) >> 8;
  24.     PWMA_ARRL = (333 - 1);
  25.    
  26.     PWMA_CCER1 = 0x00;
  27.     PWMA_CCER2 = 0x00;
  28.     PWMA_SR1   = 0x00;
  29.     PWMA_SR2   = 0x00;
  30.     PWMA_ENO   = 0x00;
  31.     PWMA_IER   = 0x00;
  32.         
  33.     PWMA_CCMR1 = 0x78;// 输出模式,PWM模式2,使能PWMA_CCR预装载
  34.     PWMA_CCR1H = 0x00;
  35.     PWMA_CCR1L = 0x00;
  36.     SET_BIT(PWMA_CCER1, 0); // 使能PWM1P比较输出,高电平有效
  37.     SET_BIT(PWMA_CCER1, 2); // 使能PWM1N比较输出,高电平有效
  38.    
  39.     PWMA_CCMR3 = 0x78;// 输出模式,PWM模式2,使能PWMA_CCR预装载
  40.     PWMA_CCR3H = 0x00;
  41.     PWMA_CCR3L = 0x00;
  42.     SET_BIT(PWMA_CCER2, 0);
  43.     SET_BIT(PWMA_CCER2, 2);
  44.    
  45.     PWMA_CCMR4 = 0x68;// 输出模式,PWM模式1,使能PWMA_CCR预装载
  46.     PWMA_CCR4H = 0x00;
  47.     PWMA_CCR4L = 0x00;
  48.     SET_BIT(PWMA_CCER2, 4);
  49.     SET_BIT(PWMA_CCER2, 6);   
  50.    
  51.     PWMA_CR1 = 0x00;
  52.     PWMA_BKR = 0x80; // MOEA = 1b, 使能主输出
  53.     PWMA_CR1 = 0xA1; // ARPEA = 1b,使能PWMA_ARR自动重装,CMSA = 01b,中央对齐模式1,CENA = 1b, 开启定时器
  54.     SET_BIT(PWMA_EGR, 0); // 产生更新事件,清零计数器
  55. }
  56. // 异步写入高速PWM寄存器
  57. void pwm_init_hs()
  58. {
  59.     pwm_init();
  60.     PWMA_DTR   =  128; // 对应死区时间为 128 / (128MHz) = 1us,PWMA时钟为128MHz
  61.     PWMA_ARRH  = (1250 - 1) >> 8; // 对应 128MHz / 1250 / 2 = 51.2 kHz 的PWM波
  62.     PWMA_ARRL  = (1250 - 1);
  63.     HSPWMA_CFG = 0x02; // 使能异步控制模式
  64. }
  65. void pwm_hs_write_sfr(u8 addr, u8 val)
  66. {
  67.     while( HSPWMA_ADR & 0x80 );
  68.     HSPWMA_DAT = val;
  69.     HSPWMA_ADR = (addr & 0x7F);
  70. }
复制代码

3. 电机换相函数

  1. void motor_commute_hspwm()
  2. {
  3.     switch( motor_phase )
  4.     {
  5.         default:
  6.         {
  7.             break;
  8.         }
  9.         case 0: // AB
  10.         {
  11.             //pwm_hs_write_sfr( (u8)&PWMA_ENO, 0x00 );
  12.             //while( HSPWMA_ADR & 0x80 );
  13.             PWM1_L = 0;
  14.             PWM2_L = 0;
  15.             PWM3_L = 0;
  16.             //delay_500ns();
  17.             pwm_hs_write_sfr( (u8)&PWMA_ENO, 0x03 );
  18.             while( HSPWMA_ADR & 0x80 );
  19.             PWM2_L = 1;
  20.             CMP_SET_PHC();
  21.             CMPCR1 = 0x80 + 0x10;
  22.             
  23.             break;
  24.         }
  25.         case 1: // AC
  26.         {
  27.             pwm_hs_write_sfr( (u8)&PWMA_ENO, 0x03 );
  28.             while( HSPWMA_ADR & 0x80 );
  29.             PWM1_L = 0;
  30.             PWM2_L = 0;
  31.             PWM3_L = 0;
  32.             //delay_500ns();
  33.             PWM3_L = 1;
  34.             CMP_SET_PHB();
  35.             CMPCR1 = 0x80 + 0x20;
  36.            
  37.             break;
  38.         }
  39.         case 2: // BC
  40.         {
  41.             //pwm_hs_write_sfr( (u8)&PWMA_ENO, 0x00 );
  42.             //while( HSPWMA_ADR & 0x80 );
  43.             PWM1_L = 0;
  44.             PWM2_L = 0;
  45.             PWM3_L = 0;
  46.             //delay_500ns();
  47.             pwm_hs_write_sfr( (u8)&PWMA_ENO, 0xC0 );
  48.             while( HSPWMA_ADR & 0x80 );
  49.             PWM3_L = 1;
  50.             CMP_SET_PHA();
  51.             CMPCR1 = 0x80 + 0x10;
  52.             
  53.             break;
  54.         }
  55.         case 3: // BA
  56.         {   
  57.             pwm_hs_write_sfr( (u8)&PWMA_ENO, 0xC0 );
  58.             while( HSPWMA_ADR & 0x80 );
  59.             PWM1_L = 0;
  60.             PWM2_L = 0;
  61.             PWM3_L = 0;
  62.             //delay_500ns();
  63.             PWM1_L = 1;
  64.             CMP_SET_PHC();
  65.             CMPCR1 = 0x80 + 0x20;
  66.             
  67.             break;
  68.         }
  69.         case 4: // CA
  70.         {
  71.             //pwm_hs_write_sfr( (u8)&PWMA_ENO, 0x00 );
  72.             //while( HSPWMA_ADR & 0x80 );
  73.             PWM1_L = 0;
  74.             PWM2_L = 0;
  75.             PWM3_L = 0;
  76.             //delay_500ns();
  77.             pwm_hs_write_sfr( (u8)&PWMA_ENO, 0x30 );
  78.             while( HSPWMA_ADR & 0x80 );
  79.             PWM1_L = 1;
  80.             CMP_SET_PHB();
  81.             CMPCR1 = 0x80 + 0x10;
  82.             
  83.             break;
  84.         }
  85.         case 5: // CB
  86.         {
  87.             pwm_hs_write_sfr( (u8)&PWMA_ENO, 0x30 );
  88.             while( HSPWMA_ADR & 0x80 );
  89.             PWM1_L = 0;
  90.             PWM2_L = 0;
  91.             PWM3_L = 0;
  92.             //delay_500ns();
  93.             PWM2_L = 1;
  94.             CMP_SET_PHA();
  95.             CMPCR1 = 0x80 + 0x20;
  96.             
  97.             break;
  98.         }
  99.     }
  100.     if( bmotor_start ) CMPCR1 = 0x80;   
  101. }
复制代码

我个人的初步判断是,这个高速PWM的异步写入方式可能存在BUG,可能会出现某次调用后,PWM不工作的情况。这导致PWM在某次调用后常开。具体问题请各路大神帮忙分析。


回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-3 05:28 , Processed in 0.157640 second(s), 49 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表