电机启动完成停在BC相序就转不动了,P1.3的电压和P5.4的电压基本相同,无法进入比较器中断。下面是程序代码和原理图。
#define MAIN_Fosc 24000000L //定义主时钟
#include "STC15Fxxxx.H"
//CMPCR1
#define CMPEN 0x80 //1: 允许比较器, 0: 禁止,关闭比较器
电源
#define CMPIF 0x40 //比较器中断标志, 包括上升沿或下降沿中断, 软件清0
#define PIE 0x20 //1: 比较结果由0变1, 产生上升沿中断
#define NIE 0x10 //1: 比较结果由1变0, 产生下降沿中断
#define PIS 0x08 //输入正极性选择, 0: 选择外部P5.5做正输入, 1: 由ADCIS[2:0]所选择的ADC输入端做正输入.
#define NIS 0x04 //输入负极性选择, 0: 选择内部BandGap电压BGv做负输入, 1: 选择外部P5.4做输入.
#define CMPOE 0x02 //1: 允许比较结果输出到P1.2, 0: 禁止.
#define CMPRES 0x01 //比较结果, 1: CMP+电平高于CMP-, 0: CMP+电平低于CMP-, 只读
//CMPCR2
#define INVCMPO 0x80 //1: 比较器输出取反, 0: 不取反
#define DISFLT 0x40 //1: 关闭0.1uF滤波, 0: 允许
#define LCDTY 0x3F //, 比较结果变化延时周期数
sbit PWM2_L = P5^5;
sbit PWM1_L = P3^6;
sbit PWM0_L = P3^3;
u8 Step; //相数
u8 PWM_Value; // 决定PWM占空比的值
bit B_RUN; //电机运行标志位
u8 PWW_Set; //给定占空比
u8 cnt10ms; //10ms时隙
u8
timeOut; //堵转超时
u8 FLAG,FLAG2;
unsigned char buffer[3];
unsigned char rec_flag=0; //等于0等待接受 等于1正在接受 extern uchar pwm1;
/*************************/
void Delay_n_ms(u8 dly)
{
u16 j;
do
{
j = MAIN_Fosc / 13000; //延时1ms, 主程序在此节拍下运行
while(--j) ;
}while(--dly);
}
void Delay50us() //@24.000MHz
{
unsigned char i, j;
i = 2;
j = 39;
do
{
while (--j);
} while (--i);
}
void StepXL(void) // 换相序列函数
{
switch(Step) //连接12V位高端,连接地为低端
{
//CCAP0H表示A相高端
//CCAP1H表示C相高端
//CCAP2H表示B相高端
//PWM1_L-P3.6表示B相低端
//PWM0_L-P3.3表示A相低端
//PWM2_L-P5.5表示C相低端
case 0: // AB
CCAP0H = PWM_Value; PWM0_L = 1; // 打开A相的高端
CCAP1H = 0; PWM2_L = 0; // 关闭C相
CCAP2H = 0xff; PWM1_L = 0; // 打开B相的低端
ADC_CONTR = 0XED; // 选择P1.5作为ADC输入 即c相电压
CMPCR1 = 0x9C; //下降沿中断
break;
case 1: // AC
CCAP0H = PWM_Value; PWM0_L = 1; // 打开A相的高端
CCAP1H = 0xff; PWM2_L = 0; // 打开C相的低端
CCAP2H = 0; PWM1_L = 0; // 关闭B相
ADC_CONTR = 0XEC; // 选择P1.4作为ADC输入 即B相电压
CMPCR1 = 0xAC; //上升沿中断
break;
case 2: // BC
CCAP0H = 0; PWM0_L = 0; // 关闭A相
CCAP1H = 0xff; PWM2_L = 0; // 打开C相的低端
CCAP2H = PWM_Value; PWM1_L = 1; // 打开B相的高端
ADC_CONTR = 0XEB; // 选择P1.3作为ADC输入 即a相电压
CMPCR1 = 0x9C; //下降沿中断
break;
case 3: // BA
CCAP0H = 0xff; PWM0_L = 0; // 打开A相的低端
CCAP1H = 0; PWM2_L = 0; // 关闭C相
CCAP2H = PWM_Value; PWM1_L = 1; // 打开B相的高端
ADC_CONTR = 0XED; // 选择P1.5作为ADC输入 即c相电压
CMPCR1 = 0xAC; //上升沿中断
break;
case 4: // CA
CCAP0H = 0xff; PWM0_L = 0; // 打开A相的低端
CCAP1H = PWM_Value; PWM2_L = 1; // 打开C相的高端
CCAP2H = 0; PWM1_L = 0; // 关闭B相
ADC_CONTR = 0XEC; // 选择P1.4作为ADC输入 即B相电压
CMPCR1 = 0x9C; //下降沿中断
break;
case 5: // CB
CCAP0H = 0; PWM0_L = 0; // 关闭A相
CCAP1H = PWM_Value; PWM2_L = 1; // 打开C相的高端
CCAP2H = 0xff; PWM1_L = 0; // 打开B相的低端
ADC_CONTR = 0XEB; // 选择P1.3作为ADC输入 即a相电压
CMPCR1 = 0xAC; //上升沿中断
break;
default:
break;
}
}
void PWM_Init(void)
{
PWM0_L = 0;
PWM1_L = 0;
PWM2_L = 0;
P3n_push_pull(0x80);
P1n_push_pull(0x03);
CMOD = 5 << 1; //选择系统时钟/4为时钟源,即PWM频率=24M/4/256=23.4K
CL=0; // PCA计数器清零
CH=0;
PCA_PWM0 = 0X00;
CCAP0H=0; // 初始化占空比为0% H的值装载到L中
CCAP0L=0;
CCAPM0=0x42; // 设置为PWM模式
PCA_PWM1 = 0X00;
CCAP1H=0; // 初始化占空比为0%
CCAP1L=0;
CCAPM1=0x42; // 设置为PWM模式
PCA_PWM2 = 0X00;
CCAP2H=0; // 初始化占空比为0%
CCAP2L=0;
CCAPM2=0x42; // 设置为PWM模式
CR = 1;
}
void ADC_Init(void)
{
P1M1 |= 0x38; P1M0 &= 0xC7; //仅输入
P1ASF = 0X38; // 开通P1.3 P1.4 P1.5的AD输入口
}
u8 StartMotor(void)
{
u16 timer,i;
CMPCR1&=~CMPEN; //禁用比较器`
PWM_Value = 30; // 初始占空比=30/256=11.7%
Step = 0;
StepXL(); // 初始位置
Delay_n_ms(5); //delay_ms(5);
timer = 300;
while(1) //
{
for(i=0; i<timer; i++) Delay50us(); // 9.6S --换相时间越来越短,加速过程
timer -= timer /15 + 1; //
if(timer < 25) {FLAG=1;return(1);}
if( Step < 5) Step++;
else Step = 0;
StepXL();
}
}
void UART_init(void) //9600bps@24MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x04; //定时器2时钟为Fosc,即1T
T2L = 0x8F; //设定定时初值
T2H = 0xFD; //设定定时初值
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x10; //启动定时器2
ES = 1; //允许串口中断
EA = 1; //开总中断
}
void UART_send_byte(unsigned int bytea)
{
ES = 0; //关串口中断
TI = 0; //清零串口发送完成中断请求标志
SBUF = bytea;
while(TI ==0); //等待发送完成
TI = 1; //清零串口发送完成中断请求标志
ES = 1; //允许串口中断
}
void Communication_Decode(void)
{
if((buffer[0]==0xaa)&&(buffer[2]==0xbb))
{
PWW_Set=buffer[1];
}
UART_send_byte(PWW_Set);
UART_send_byte(Step);
UART_send_byte(FLAG);
UART_send_byte(FLAG2);
}
void UART_Interrupt_Receive(void) interrupt 4
{
static u8 i;
if(RI)
{
RI = 0;
if(rec_flag==0) { if(SBUF==0xff){ rec_flag=1; i=0; } }
else
{
if(SBUF==0xff) { rec_flag=0; if(i==3){ Communication_Decode();} i=0;}
else { buffer[i]=SBUF; i++; }
}
}
else
{}
}
void CMP_INT(void) interrupt 21 //比较器中断
{
CMPCR1 &= ~CMPIF; // 需软件清除中断标志位 CMPCR1&= 0xbf
if(Step<5) Step++;
else Step = 0;
StepXL();
TimeOut = 10; //10ms超时
FLAG2 = 1;
}
void CMP_Init(void)
{
CMPCR1 = 0;
CMPCR2 = 0;
// CMPCR1&=~PIS; //选择外部管脚P5.5(CMP+)为比较器的正极输入源
CMPCR1|=PIS; //选择ADCIS[2:0]所选的ADCIN为比较器的正端输入源
// CMPCR1&=~NIS; //选择内部BandGap电压BGV为比较器的负极输入源
CMPCR1|=NIS; //选择外部引脚P5.4(CMP-)为比较器的负极输入源
CMPCR1&=~CMPOE; //禁用比较器的比较结果输出
// CMPCR1|=CMPOE; //使能比较器的比较结果输出到P1.2
CMPCR2&=~INVCMPO; //比较器结果正常输出到P1.2
// CMPCR2|=INVCMPO; //比较器结果取反输出到P1.2
CMPCR2&=~DISFLT; //使能比较器输出端的0.1us滤波
电路
// CMPCR2|=DISFLT; //禁用比较器输出端的0.1us滤波电路
// CMPCR2&=~LCDTY; //比较器结果不去抖动,直接输出
CMPCR2|=(DISFLT&0x3C); //比较器经过60个时钟后再输出
CMPCR1|=PIE; //上升沿中断
// CMPCR1|=NIE; //下降沿中断
// CMPCR1|=CMPEN; //使能比较器
CMPCR1&=~CMPEN; //禁用比较器
EA=1;
}
/**********************************************/
void main(void)
{
FLAG = 0;
FLAG2= 0;
PWM_Init();
ADC_Init();
CMP_Init();
UART_init();
PWW_Set = 0; //占空比预设值为0
cnt10ms = 0; //
TimeOut = 0; //清除time溢出标志
EA = 1; // 打开总中断
while (1)
{
Delay_n_ms(1); //延时1ms, 主程序在此节拍下运行
if(TimeOut > 0) ///溢出
{
if(--TimeOut == 0) //堵转超时
{
CCAP0H=0; CCAP1H=0; CCAP2H=0; // 占空比为0
PWM0_L=0; PWM1_L=0; PWM2_L=0;
CMPCR1&=~CMPEN; //禁用比较器
Delay_n_ms(250); //堵转时,延时1秒再启动
Delay_n_ms(250);
Delay_n_ms(250);
Delay_n_ms(250);
PWW_Set = 0;
PWM_Value = 0;
B_RUN = 0;
TimeOut = 0;
}
} //此时TimeOut为0
if(!B_RUN && (PWW_Set >= 30)) // PWM_Set >= 30, 并且马达未运行, 则启动马达
{
StartMotor(); // 启动马达
CMPCR1 &= ~0X40; // 需软件清除中断标志位
CMPCR1|=CMPEN; //使能比较器
B_RUN = 1;
TimeOut = 0;
}
if(++cnt10ms >= 10) // 10ms时隙
{
cnt10ms = 0;
if(B_RUN)
{
if(PWM_Value < PWW_Set) PWM_Value++;
if(PWM_Value > PWW_Set) PWM_Value--;
if(PWM_Value < 20) // 停转
{
PWM_Value = 0;
B_RUN = 0;
CCAP0H=0; CCAP1H=0; CCAP2H=0; // 占空比为0
PWM0_L=0; PWM1_L=0; PWM2_L=0;
CMPCR1&=~CMPEN; //禁用比较器
}
}
}
}
}
-
根据你的程序猜测你用的是航模电机,初始速度偏高,这样就使励磁电流要大,也就是pwm开通大,如果跟不上,就会导致失步,甚至只是转子振动,仔细调整定位pwm,初始速度,加速曲线这几个参数,还有,没看到你开环启动后进入闭环的代码,也没打开BEMF中断检测
有感电机不存在启动抖动问题,抖动是无感特有,在进入闭环之前转子位置估计不准确导致的抖动
一周热门 更多>