This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
工具/软件:Code Composer Studio
您好!
我们正在使用 MSP430FR2355开发 BLDC 电机控制逻辑。 我们遇到了几个 PWM 模块问题。
相同的图像如下所示。 我们所需的系统是在20kHz 开关频率下工作、两个 ADC 通道用于电池监控和速度控制。
BLDC 的逻辑是在两个脉冲模式下运行开关、而高侧开关以 PWM 方式工作。
下图显示的 PWM 具有很少的其他频率、我将占空比保持在50%、但该占空比也不可见
//头文件//
#include "msp430fr2355.h"
#include "stdint.h"
#define CALTDH0CTL1_256 *((unsigned int *) 0x1A36)
/********* InstaSPIN 代码 /
#define PWM_PERIOD 600 // PWM 频率(Hz)= 25MHz/((2 * PWM_PERIOD)-1)
#define MAX_DUTYCYCLE 600 //相对于 PWM_PERIOD
#define MIN_DUTYCYCLE 5 //相对于 PWM_PERIOD
#define ACCEL_RATE 100 //斜升至满量程占空比的时间=(满量程占空比)* ACCEL_RATE * PWM_PERIOD/PWM_Frequency
#define DEAD_TIME_MCU 1 // MSP430的死区时间= DEAD_TIME* 0.0625us (对于16MHz 时钟)
#define Block_Rotor_Duration 800 // blocked_but 关闭时间(s)= Block_Rotor_Duration * 30000/计时器时钟频率
INT LPM3_ON = 0;
/********* 程序变量******** /
unsigned int DC_BUS_CURRENT = 0;
unsigned int DC_BUS_Voltage = 0;
unsigned int speed_REF = 0;
unsigned int Temperature_feedback = 0;
unsigned int start_count = 0;
unsigned int HALL_State = 0;
unsigned int softstart_counter = 0;
unsigned int CurrentDutyCycle = 100;
unsigned int direction = 0;
unsigned int FirstADC_flag = 1;
unsigned int adc_selection_FLAG = 1;
unsigned int adc_selection_FLAG_1 = 1;
unsigned int Block_Rotor_Counter = 0;
unsigned int Block_Rotor_Counter_1 =0;
unsigned int ADC_Result = 0;
unsigned int 换向_time = 0;
unsigned int 换向_time_counter = 0;
unsigned int Adv_angle_time_counter = 0;
unsigned int Adv_angle_time = 0;
unsigned int sorting_done = 0;
unsigned int previous_State = 0;
unsigned int prese_State = 0;
unsigned int PWM_Duty = PWM_PERIOD;
unsigned int adc_counter_FLAG = 0;
无符号 int BATT_V = 0;
unsigned int i = 0;
unsigned int j = 0;
void Init_clocks (void);
void init_io (void);
void init_wdt (void);
void init_adc (void);
void init_TimerB (void);
void Hall_State_Change_Forward (void);
void Hall_State_Change_Reverse (void);
void a_PWM (void);
void B_PWM (void);
void C_PWM (void);
void a_low (void);
void B_low (void);
void C_low (void);
void a_Z (void);
void B_Z (void);
void C_Z (void);
void a_high (void);
void B_high (void);
void C_high (void);
void main (void)
{
WDTCTL = WDTPW + WDTHOLD;//停止 WDT
_delay_cycles (1000000);
init_clocks ();//初始化25MHz 的时钟
init_adc ();
init_TimerB ();
//init_WDT ();
init_io ();
A_Z();
B_Z();
C_Z();
_delay_cycles (1000000);
/********* 启用 DRV8323 /
P4OUT &=~BIT1;
_delay_cycles (2500);//100us 延迟
//P4OUT |= BIT1;
_delay_cycles (250);//10us 延迟
//方向=(P5IN & BIT4);
方向= 0;
HALL_STATE =((P3IN & BIT0)+(P3IN & BIT1)+(P3IN & BIT2));
ADC_COUNTER_FLAG = 0;
while (1)
{
I = 0;
if (softstart_counter >= ACCEL_RATE)
{
softstart_counter = 0;
IF (CurrentDutyCycle < SPED_REF)
{
CurrentDutyCycle ++;
}
否则、如果(CurrentDutyCycle > SPED_REF)
{
电流占空比--;
}
IF (CurrentDutyCycle >= MAX_DUTYCYCLE)
{
CurrentDutyCycle = MAX_DUTYCYCLE;
}
否则、如果(CurrentDutyCycle <= MIN_DUTYCYCLE)
{
CurrentDutyCycle = MIN_DUTYCYCLE;
}
}
if (DIRECTION ==0)
{
HALL_State_Change_Forward ();
}
其他
{
HALL_State_Change_Reverse ();
}
}
//结束 main
}
//WDT 以重新启动 ADC
void init_WDT (void)
{
WDTCTL = WDT_MDLY_32;//从1MHz 到 SMCLK 的 WDT 32ms 间隔定时器
//SFRIE1 |= WDTIE;//启用 WDT 中断
}
空 init_TimerB (空)
{
TB3CTL = TBSSEL_SMCLK | MC_3 | TBCLR;// SMCLK、UP_DOWN 模式、清除 TBR
TB3CCR0 = PWM_PERIOD;// PWM 周期
TB3CCR1 = PWM_PERIOD;// CCR1 PWM 占空比
TB3CCR2 = PWM_PERIOD;// CCR2 PWM 占空比
TB3CCR3 = PWM_PERIOD;// CCR3 PWM 占空比
TB3CCR4 = PWM_PERIOD;// CCR4 PWM 占空比
TB3CCR5 = PWM_PERIOD;// CCR3 PWM 占空比
TB3CCR6 = PWM_PERIOD;// CCR4 PWM 占空比
TB3CCTL1 = OUTMOD_6;// CCR1复位/置位
TB3CCTL2 = OUTMOD_2;// CCR2复位/置位
TB3CCTL3 = OUTMOD_6;// CCR3复位/置位
TB3CCTL4 = OUTMOD_2;// CCR4复位/置位
TB3CCTL5 = OUTMOD_6;// CCR4复位/置位
TB3CCTL6 = OUTMOD_2;// CCR4复位/置位
TB3CCTL0 |= CCIE;
_bis_SR_register (GIE);//启用中断
__no_operation();//用于调试器
_EINT();//启用中断
}
//时钟和 Vcore
void Init_clocks (void)
{
FRCTL0 = FRCTLPW | NWAITS_2;
_bis_SR_register (SCG0);//禁用 FLL
CSCTL3 |= SELREF_REFOCLK;//将 REFO 设置为 FLL 基准源
CSCTL0 = 0;//清除 DCO 和 MOD 寄存器
CSCTL1 |= DCORSEL_7;//设置 DCO = 24MHz
CSCTL2 = FLLD_0 + 731;// DCOCLKDIV = 24MHz
_DELAY_CYCLES (3);
_BIC_SR_register (SCG0);//启用 FLL
while (CSCTL7 &(FLLUNLOCK0 | FLLUNLOCK1));// FLL 锁定
CSCTL4 = SELMS_DCOCLKDIV | SELA_REFOCLK;//将默认 REFO (~32768Hz)设置为 ACLK 源、ACLK = 32768Hz
//默认 DCOCLKDIV 为 MCLK 和 SMCLK 源
}
//IO 初始化//
void init_io (void)
{
PM5CTL0 &=~LOCKLPM5;
P2SEL0 &=~(BIT6);//GPIO-LED3
P2SEL1 &=~(BIT6);
P2DIR |=(BIT6);//输出 LED3
P1SEL0 |= BIT1;//A0引脚
P1SEL1 |= BIT1;
P1SEL0 |= BIT7;//A0引脚
P1SEL1 |= BIT7;
///PWM 输出
//GPIO-PWM
P6DIR |=(BIT0+BIT1 +BIT2 + BIT3 + BIT4 + BIT4);//OutputPWM
//方向控制
P5SEL0 &=~(BIT4);//GPIO - DIR
P5SEL1 &=~(BIT4);//GPIO - DIR
P5DIR |=(BIT4);//输入- DIR
//启用栅极驱动器
P4SEL0 &=~(BIT1);//GPIO - DIR
P4SEL1 &=~(BIT1);//GPIO - DIR
P4DIR |=(BIT1);//输出- DIR
//故障输入
P4SEL0 &=~(BIT0);//GPIO - DIR
P4DIR &=~(BIT0);//输入- DIR
//霍尔传感器输入
P3SEL0 &=~(BIT0+BIT1 + BIT2);//GPIO -霍尔传感器
P3DIR &=~(BIT0+BIT1 + BIT2);//输入-霍尔传感器
P3IES |=((BIT0)+(BIT1)+(BIT2));//将霍尔中断更改为下降边沿以检测两个边沿
P3IE |=(BIT0 | BIT1 | BIT2);
P3IFG &=~(BIT0| BIT1 | BIT2);
_bis_SR_register (GIE);
}
void init_adc (void)
{
//配置 ADC12
ADCCTL0 |= ADCSHT_2 | ADCON;// ADCON、S&H=16 ADC CLKS
ADCCTL1 |= ADCSHP;// ADCCLK = MODOSC;采样计时器
ADCCTL2 &=~ADCRES;//清除 ADCCTL 中的 ADCRES
ADCCTL2 |= ADCRES_2;// 12位转换结果
ADCMCTL0 |= ADCINCH_0;// A1 ADC 输入选择;Vref=AVCC
ADCIE |= ADCIE0;//启用 ADC 转换完成中断
ADCCTL0 |= ADCENC | ADCSC;
}
/******** ADC 中断********* /
// ADC 中断服务例程
#if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
#pragma vector=ADC_vector
_interrupt void ADC_ISR (void)
#Elif defined (_GNU_)
void __attribute__((interrupt (ADC_vector))) ADC_ISR (void)
其他
错误编译器不受支持!
#endif
{
switch (__evo_in_range (ADCIV、ADCIV_ADCIFG))
{
案例 ADCIV_NONE:
中断;
ADCIV_ADCOVIFG 案例:
中断;
案例 ADCIV_ADCTOVIFG:
中断;
ADCIV_ADCHIIFG 案例:
中断;
ADCIV_ADCLOIFG 案例:
中断;
ADCIV_ADCINIFG 案例:
中断;
ADCIV_ADCIFG 案例:
ADC_RESULT = ADCMEM0;
ADC_COUNTER_FLAG++;
中断;
默认值:
中断;
}
}
/******** TIMERD0.1中断************* /
//计时器 B1中断服务例程
#if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
#pragma vector = TIMER3_B0_vector
_interrupt void Timer3_B0_ISR (void)
#Elif defined (_GNU_)
void __attribute__((中断(TIMER3_B0_vector)) Timer3_B0_ISR (void)
其他
错误编译器不受支持!
#endif
{
///PWM_Duty =(PWM_Period - CurrentDutyCycle);
PWM_Duty = 300;
P5OUT ^= BIT4;
TB3CCR1 = PWM_Duty;// CCR1 PWM 占空比
TB3CCR2 = PWM_DUTY;
TB3CCR3 = PWM_DUTY;// CCR1 PWM 占空比
TB3CCR4 = PWM_DUTY;
TB3CCR5 = PWM_Duty;// CCR1 PWM 占空比
TB3CCR6 = PWM_DUTY;
如果(ADC_COUNTER_FLAG = 1)
{
SPED_REF = ADC_RESULT;
SPED_REF =(SPED_REF >>2);
ADCCTL0 &=~ADCENC;//禁用
ADCMCTL0 =(ADCMCTL0 &~ADCINCH)| 7;
ADCCTL0 |= ADCENC | ADCSC;
}
如果(ADC_COUNTER_FLAG = 2)则为其他值
{
BATT_V = ADC_Result;
ADCCTL0 &=~ADCENC;//禁用
ADCMCTL0 =(ADCMCTL0 &~ADCINCH)| 0;
ADCCTL0 |= ADCENC | ADCSC;
ADC_COUNTER_FLAG = 0;
}
softstart_counter ++;
Block_Rotor_Counter_1_+;
IF (Block_Rotter_Counter_1_=30000)
{
Block_Rotor_Counter++;
}
IF (Block_Rotor_Counter > Block_Rotor_Duration)
{
A_Z();
B_Z();
C_Z();
disable_interrupt ();
//while (1);
}
TB3CCTL0 &=~CCIFG;
}
/******** 端口1中断服务例程********* /
#if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
#pragma vector=PORT3_vector
_interrupt void Port_3 (void)
#Elif defined (_GNU_)
void __attribute__((interrupt (PORT3_vector))) Port_3 (void)
其他
错误编译器不受支持!
#endif
{
HALL_STATE =((P3IN & BIT0)+(P3IN & BIT1)+(P3IN & BIT2));
if (DIRECTION ==0)
{
HALL_State_Change_Forward ();
}
其他
{
HALL_State_Change_Reverse ();
}
Block_Rotor_Counter = 0;
Block_Rotor_Counter_1 = 0;
P3IES ^=(BIT0)+(BIT1)+(BIT2);
P3IFG &=~(BIT0| BIT1 | BIT2);
}
/******** ADC 中断结束********* /
//看门狗定时器中断服务例程
#pragma vector=WDT_Vector
_interrupt void WDT_ISR (void)
{
}
/********* 换向序列前进 /
void Hall_State_Change_Forward (void)
{
开关(HALL_State)
{
案例2:
C_Z();
a_pwm ();
b_low ();
中断;
案例6:
B_Z();
a_pwm ();
c_low();
中断;
案例3:
A_Z();
c_PWM ();
b_low ();
中断;
案例1:
B_Z();
c_PWM ();
a_low ();
中断;
案例4:
A_Z();
b_pwm ();
c_low();
中断;
情况5:
C_Z();
b_pwm ();
a_low ();
中断;
默认值:
A_Z();
B_Z();
C_Z();
中断;
}
}
/********* 换向序列反向 /
void Hall_State_Change_Reverse (void)
{
开关(HALL_State)
{
案例2:
C_Z();
b_pwm ();
a_low ();
中断;
案例6:
B_Z();
c_PWM ();
a_low ();
中断;
案例3:
A_Z();
b_pwm ();
c_low();
中断;
案例1:
B_Z();
a_pwm ();
c_low();
中断;
案例4:
A_Z();
c_PWM ();
b_low ();
中断;
情况5:
C_Z();
a_pwm ();
b_low ();
中断;
默认值:
A_Z();
B_Z();
C_Z();
中断;
}
}
/********* PWM GPIO 的定义 /
void A_PWM (void)
{
P6SEL0 |= BIT0;
P6SEL0 |= BIT1;
}
void B_PWM (void)
{
P6SEL0 |= BIT2;
P6SEL0 |= BIT3;
}
void C_PWM (void)
{
P6SEL0 |= BIT4;
P6SEL0 |= BIT5;
}
void a_low (void)
{
P6SEL0 &=~BIT0;
P6SEL1 &=~BIT0;
P6OUT &=~BIT0;
P6SEL0 &=~BIT1;
P6SEL1 &=~BIT1;
P6OUT |= BIT1;
}
void B_low (void)(空)
{
P6SEL0 &=~BIT2;
P6OUT &=~BIT2;
P6SEL0 &=~BIT3;
P6OUT |= BIT3;
}
void C_low (void)
{
P6SEL0 &=~BIT4;
P6OUT &=~BIT4;
P6SEL0 &=~BIT4;
P6OUT |= BIT5;
}
void A_Z (void)
{
P6SEL0 &=~BIT0;
P6OUT &=~BIT0;
P6SEL0 &=~BIT1;
P6OUT &=~BIT1;
}
空 B_Z (空)
{
P6SEL0 &=~BIT2;
P6OUT &=~BIT2;
P6SEL0 &=~BIT3;
P6OUT &=~BIT3;
}
空 C_Z (空)
{
P6SEL0 &=~BIT4;
P6OUT &=~BIT4;
P6SEL0 &=~BIT4;
P6OUT &=~BIT4;
}
void a_high (void)(空)
{
P6SEL0 &=~BIT0;
P6OUT |= BIT0;
P6SEL0 &=~BIT1;
P6OUT &=~BIT1;
}
空 B_HIGH (空)
{
P6SEL0 &=~BIT2;
P6OUT |= BIT2;
P6SEL0 &=~BIT3;
P6OUT &=~BIT3;
}
void C_high (void)(空)
{
P6SEL0 &=~BIT4;
P6OUT |= BIT4;
P6SEL0 &=~BIT4;
P6OUT &=~BIT4;
}
当我在 Launchpad 上运行该代码并在某个偶然点暂停、然后明确地将 P6SEL0=0x3F 置位、我在50%的占空比下获得一个完美的20kHz 方波(如预期的那样)。
我观察到、状态机经常启用/禁用 PWM (P6SEL0处)。 我怀疑这些交互会使您的占空比消失、而不必遵循您的逻辑。
您好、Jeet、
我正在深入了解我在 BOOSTXL-DRV8320RS 的软件文件中找到的一些示例代码。 该代码最初用于 MSP430F5529 Launchpad。
它会针对每个状态执行以下操作:
-仅为低电平阶段(代码的 x_low)重置 LS,然后选择 I/O
-重置 Hi-Z 阶段的 HS 和 LS (代码的 x_Z),然后选择 I/O
-选择 PWM 阶段的 PWM (代码的 x_PWM)、然后将低电平阶段设置为低电平
我复制了示例代码的 U->V 示例以与案例5 (A_PWM、B_LOW、C_Z)进行比较。 请尝试修改您的函数、使其与上面列出的步骤的顺序相匹配、并显示在下面的代码中:
案例2: /* U-V * /* V 相(低-高)的复位开关*/ P1OUT &=~(BIT4); /*重置位 P1.4、P1.5 */ P1SEL &=~(BIT5); /*选择 P1.4、P1.5作为 V*/相的 I/O 功能 /* W 相(低-高)的复位开关*/ P1OUT &=~(BIT2 | BIT3); /*重置位 P1.2、P1.3 */ P1SEL &=~(BIT2 | BIT3); /*选择 P1.2、P1.3作为相位 W*/的 I/O 功能 P2SEL |= BIT4 | BIT5; /*为 U 相选择同步 PWM */ P1OUT |= BIT4; /*设置 V 相的低侧*/ 中断;
您好、
感谢您的回复。
代码的问题是:
1、代码卡在块转子条件下、因此 PWM 进入代码中指定的高阻抗模式。 所有中断都按照 "IF "循环中的指定被禁用。
我的问题是关于高阻抗状态、为什么在高阻抗状态下 PWM 会以上述图像方式出现。
>void B_Z (void) {
>P6SEL0 &=~BIT2;
>P6OUT &=~BIT2;
>P6SEL0 &=~BIT3;
>P6OUT &=~BIT3;
在这里、我要提到的是、这不会将引脚置于高阻态、而是输出低电平。 您需要添加以下内容:
>P6DIR &=~(BIT2|BIT3);