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]