-
ATIM :CH1、CH2、CH3 三个通道比较产生 PWM 波用于驱动电机,CH4为芯片内部通道,无外部引脚,只有一路比较捕获寄存器 (ATIM_CH4CCR),且只能用于比较,不能用来捕获。我们使用 CH4 的比较功能触发 DMA 传输。
-
DMA :使用4路 DMA 通道:CH1、CH2、CH3、 CH4:
-
CH1 将 ADC 单次单通道的采样结果传入 RAM
-
CH2 将 ADC 的 CR1 寄存器的配置值从 RAM 传入寄存器
-
CH3 将 ADC 的 START 寄存器的配置值从 RAM 传入寄存器
-
CH1、CH2、CH3由 ADC 硬件触发,CH4 由 ATIM 硬件触发,启动 ADC
-
ADC :ADC 采样的时钟设置需要与 PWM 载波频率结合,计算采样时间;采用单通道单次采样,首次采样由 ATIM 硬件触发,ADC 转换完毕后触发 DMA 传输,通过 DMA 传输自动改变采样通道。这样设置可以实现 ATIM 触发一次就采样五个数据(U、V、W 相电压、母线电压、外部电位器调速电压)
-
BTIM1 :BTIM1 设置 1ms 进入一次中断,在中断里改变标志位实现主程序的控制
-
BTIM2 :BTIM2 作为换相时间间隔的记录定时器,决定延迟多长时间后换相
-
BTIM3 :BTIM3 设置中断,在中断里完成退磁和换相
操作 ATIM CH4 的 CCR 寄存器,可以选择 ADC 在一个 PWM 周期内不同位置的采样:
void Commutation(uint32_t step,uint32_t PWM_ON_flag)
{
if(PWM_ON_flag==0)
{
CW_ATIM->CH1CCRA=0;CW_ATIM->CH2CCRA=0;CW_ATIM->CH3CCRA=0;
PWM_AL_OFF; PWM_BL_OFF;PWM_CL_OFF;
CW_ATIM->CH4CCR=PWM_TS-800;
return;
}
if(step==0||step==5){PWM_AL_OFF;PWM_CL_OFF;}
else if(step==1||step==2){PWM_AL_OFF;PWM_BL_OFF;}
else if(step==3||step==4){PWM_BL_OFF;PWM_CL_OFF;}
if(step==0||step==1){CW_ATIM->CH2CCRA=0;CW_ATIM->CH3CCRA=0;CW_ATIM->CH1CCRA=OutPwm;}
if(step==2||step==3){CW_ATIM->CH1CCRA=0;CW_ATIM->CH3CCRA=0;CW_ATIM->CH2CCRA=OutPwm;}
if(step==4||step==5){CW_ATIM->CH1CCRA=0;CW_ATIM->CH2CCRA=0;CW_ATIM->CH3CCRA=OutPwm;}
if(step==0||step==5){PWM_BL_ON;}
else if(step==1||step==2){PWM_CL_ON;}
else if(step==3||step==4){PWM_AL_ON;}
Step_Last=step;
if(OutPwm>=1200&&Flag_ON_or_OFF==0){Flag_ON_or_OFF=1;CW_ATIM->CH4CCR=300;}
else if(OutPwm<1200&&Flag_ON_or_OFF==1){Flag_ON_or_OFF=0;CW_ATIM->CH4CCR=PWM_TS-600; }
Step_Time=BTIM_GetCounter(CW_BTIM2);
BTIM_SetCounter(CW_BTIM2,0);
if(Flag_Start_OK==0)
BTIM_SetAutoreload(CW_BTIM3,Step_Time/8);
else
BTIM_SetAutoreload(CW_BTIM3,Step_Time/6);
BTIM_SetCounter(CW_BTIM3,0);
BTIM_Cmd(CW_BTIM3, ENABLE);
Flag_Demagnetize_State=1;
HALLcount++;
}
void BTIM3_IRQHandler(void)
{
if(BTIM_GetITStatus(CW_BTIM3, BTIM_IT_OV))
{
BTIM_ClearITPendingBit(CW_BTIM3, BTIM_IT_OV);
if(Flag_Demagnetize_State == 1)
{
Flag_Demagnetize_State = 2;
BTIM_Cmd(CW_BTIM3, DISABLE);
}
else if(Flag_Demagnetize_State == 3 && Flag_Start_OK == 1)
{
BTIM_Cmd(CW_BTIM3, DISABLE);
if(Direction == 0)
{
Cur_Step++;
if(Cur_Step == 6)Cur_Step = 0;
}
else
{
if(Cur_Step == 0)Cur_Step = 5
;
else Cur_Step--;
}
Commutation(Cur_Step,Motor_Start_F);
}
}
}
过零点比较函数
如下,此函数在 ADC 完成五次采样后调用。
void ADC_Process(void)
{
static uint8_t count = 0;
uint32_t Voltage_Bus = 0;
uint8_t Flag_0V = 0;
if(Flag_Demagnetize_State != 2)return;
BEMFConvertedValue =SampleData[TAB_BEMFChannel[Cur_Step]];
RisingFalling=TAB_RisingFalling[Direction][Cur_Step];
if(Flag_ON_or_OFF == 0)Voltage_Bus = 50;
else Voltage_Bus = SampleData[2];
if(RisingFalling == FALLING)
{
if(BEMFConvertedValue < Voltage_Bus)
{
count++;
if(count >= 2)
{
count = 0;
Flag_Demagnetize_State = 3;
Count_0V++;
Flag_Confirm = 1;
Flag_0V = 1;
}
}
else count = 0;
}
else if(RisingFalling == RISING)
{
if(BEMFConvertedValue > Voltage_Bus)
{
count++;
if(count >= 2)
{
count = 0;
Flag_Demagnetize_State = 3;
Count_0V++;
Flag_Confirm = 1;
Flag_0V = 1;
}
}
else count = 0;
}
if(Count_0V >= STCount && Flag_Start_OK == 0)
{
Flag_Start_OK = 1;
}
if(Flag_Start_OK == 1 && Flag_0V == 1)
{
Flag_0V = 0;
BTIM_SetAutoreload(CW_BTIM3,Step_Time/8);
BTIM_SetCounter(CW_BTIM3,0);
BTIM_Cmd(CW_BTIM3, ENABLE);
}
}
do
{
if(Direction == 0)
{
Cur_Step++;
if(Cur_Step >= 6)Cur_Step = 0;
}
else
{
if(Cur_Step == 0)Cur_Step = 5;
else Cur_Step--;
}
Flag_Confirm = 0;
if(Flag_Start_OK == 0)
{
Commutation(Cur_Step,Motor_Start_F);
}
TimeCountTemp = 0;
while(TimeCountTemp < RAMP_TABLE[Com_time])
{
if(Flag_Confirm == 1 || Flag_Start_OK == 1)break;
}
Com_time++;
OutPwm+=10;
}while(Flag_Start_OK==0 && Com_time<60
&& ErrorCode==0);