最近用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. 电机换相函数
我个人的初步判断是,这个高速PWM的异步写入方式可能存在BUG,可能会出现某次调用后,PWM不工作的情况。这导致PWM在某次调用后常开。具体问题请各路大神帮忙分析。
|