完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电机启动完成停在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 //, 比较结果变化延时周期数 ***it PWM2_L = P5^5; ***it PWM1_L = P3^6; ***it 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 -= 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; //禁用比较器 } } } } }
|
|
相关推荐
2 条评论
5个回答
|
|
你提供的信息太少了,很难精确判断,如什么电机?极对数?是否带载?BEMF是否正常?启动失败时转子运转正常? 根据你的程序猜测你用的是航模电机,初始速度偏高,这样就使励磁电流要大,也就是pwm开通大,如果跟不上,就会导致失步,甚至只是转子振动,仔细调整定位pwm,初始速度,加速曲线这几个参数,还有,没看到你开环启动后进入闭环的代码,也没打开BEMF中断检测 |
|
|
|
WAITXHURT 发表于 2016-3-2 12:52 请问无刷直流电机(有霍尔)启动会有抖动可能是什么愿意呢? |
|
|
|
你应该把你的问题与现象发出来 供大家给你解决
|
|
|
|
有感电机不存在启动抖动问题,抖动是无感特有,在进入闭环之前转子位置估计不准确导致的抖动 |
|
|
|
{:1:}{:1:}{:1:}{:1:}{:1:}{:1:}
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-LCD显示图片编程示例之介绍mmap
238 浏览 0 评论
《DNESP32S3使用指南-IDF版_V1.6》第二章 常用的C语言知识点
629 浏览 0 评论
【RA-Eco-RA2E1-48PIN-V1.0开发板试用】(第三篇)ADC采集+PWM输出
552 浏览 0 评论
《DNK210使用指南 -CanMV版 V1.0》第四十五章 人脸识别实验
552 浏览 0 评论
1074 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
11765 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-23 13:34 , Processed in 0.725965 second(s), Total 87, Slave 68 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号