直流无刷电机控制PIC程序(全部整合)
- 格式:doc
- 大小:72.50 KB
- 文档页数:9
#include <pic168xa.h> //2008.4.24--14点00分#include <math.h>#include <stdlib.h>int charge_delay,jm,lkk,trial,run_num,protect_num;char m,n,k,s,L,tri;char hall_num; //循环次数char hall_number; //1+3+2+10+8+9=33(一个循环和),hallless_protect()int pwm_hi; // pwm占空比上限int pwm_cycle; // pwm周期int pwm_lo; // pwm占空比下限,由A/D结果确定int pwm_real; // pwm占空比实际int ad_result; // A/D转换结果bit ghy,run_flag; //运行标志---0,未运行,停止bit flag_autohand; //开始为-----自动void delay(delay_num)int delay_num;{int j;for (j=delay_num;j>1;j--){asm("nop");}}union adres{int y1;unsigned char adre[2];}adresult;void para_chushihua(){protect_num=0;trial=0b10110000;tri=0x00;lkk=10;hall_num=0x00;hall_number=0x00;run_flag=0; //运行标志---0,未运行,停止flag_autohand=1; //开始为-----自动pwm_cycle= 240; // pwm周期// pwm_hi=pwm_cycle-5; // pwm占空比上限pwm_hi=pwm_cycle-1; // pwm占空比上限pwm_real=pwm_cycle; // 实际pwm占空比为pwm周期上限pwm_lo=0x0A; //设定下限+++++++++++++++++++++++++++++++++++++++++++++++}void nointerupt_chushihua(){INTCON=0X00; //禁止中断}void Io_chushihua(){// ADCON1=0x8e; //RA0/AN0--VOLTAGE 电压采样,右对齐1 ADCON1=0x86; //设定RA0--RA6设定为I/O口;TRISA =0x09; //RA0---PROTECT保护(电流保护和过温保护)--输出,0--不保护,1--保护;//RA1----PSW1,继电器,输出,0,电源接通//RA2----指示灯,输出0--->>//RA3----按键,加,输入 1//RA4----指示灯,输出0--->>//RA5----RSW1,继电器,输出0,软启充电PORTA=PORTA&0x09; //RA1=0,----输出低电平,PSW1,继电器断//RA2=0,----输出低电平,指示灯灭//RA4=0,----输出低电平,指示灯灭//RA5=0,----输出低电平,RSW1,继电器断RBPU=0; //RB端口内部弱上拉电路禁止TRISB =0xfe; //RB7=1, 空----输入//RB6=1----HA,输入//RB5=1----HB,输入//RB4=1----HC,输入//RB3=1----停,输入,按钮//RB2=1----启,输入,按钮//RB1=1----自/手选择,输入,开关//RB0=0----ST/STOP,输出,控制GAL PORTB=PORTB&0xfe; //RB0=0,----输出低电平,禁止GAL输出TRISC =0x02; //RC7---A1+,PWMA1+,输出0//RC6---A1, 输出0//RC5---B1+,输出0//RC4---B1,输出0//RC3---C1+,输出0//RC2---CCP1(PWM),输出,死区0//RC1----减,输入,按钮 1//RC0---C1,输出0 PORTC=0x06;}void protect(){ //过流和过温保护GIE=0; //关全局中断pwm_real=pwm_hi; //PWM_real----PWM实时值CCPR1L=pwm_real; //设置PWM输出为最大CCPR1H=0x00; //CCP1CON=0x0c; //CCP1选择为PWM工作方式PR2=pwm_cycle; //设置PWM的周期TRISC=TRISC&0xfb; //设置RC2---PWM输出T2CON=0x00; //分频系数=0x00TMR2ON=1; //启用TMR2PORTC=0x00; //PORTB=PORTB&0xfe; //RB0=0,----输出低电平,禁止GAL输出while(1){PORTA^=0b00010100;delay(15000); //延时}}void protect_run(){ //过流和过温保护GIE=0; //关全局中断pwm_real=pwm_hi; //PWM_real----PWM实时值CCPR1L=pwm_real; //设置PWM输出为最大CCPR1H=0x00; //CCP1CON=0x0c; //CCP1选择为PWM工作方式PR2=pwm_cycle; //设置PWM的周期TRISC=TRISC&0xfb; //设置RC2---PWM输出T2CON=0x00; //分频系数=0x00TMR2ON=1; //启用TMR2PORTC=0x00; //PORTB=PORTB&0xfe; //RB0=0,----输出低电平,禁止GAL输出while(1){// PORTA^=0b00010000; //RA4闪动PORTA^=0b00000100; //RA2闪动delay(15000); //延时}}void PWM_chushihua(){// CCPR1L=0xa0;// CCPR1H=0x00;run_num=0;pwm_real=pwm_hi; //PWM_real----PWM实时值CCPR1L=pwm_real; //设置PWM输出为最大CCPR1H=0x00; //CCP1CON=0x0c; //CCP1选择为PWM工作方式PR2=pwm_cycle; //设置PWM的周期TRISC=TRISC&0xfb; //设置RC2---PWM输出T2CON=0x00; //分频系数=0x00TMR2ON=1; //启用TMR2}void open_loopf() //开环运行50次,启动{k=0b00011000; //5 //HA,HB,HC,s=PORTC&0b00000110; //1 0 1, B-C+PORTC=k|s; //delay(8000); //延时k=0b10010000; //4 //HA,HB,HC,s=PORTC&0b00000110; //1 0 0, A+B-PORTC=k|s; //delay(8000); //延时k=0b10000001; //6 //HA,HB,HC,s=PORTC&0b00000110; //1 1 0, C-A+PORTC=k|s; //delay(8000); //延时k=0b00100001; //2 //HA,HB,HC,s=PORTC&0b00000110; //0 1 0, B+C-PORTC=k|s; //delay(8000); //延时k=0b01100000; //3 //HA,HB,HC,s=PORTC&0b00000110; //0 1 1, A-B+PORTC=k|s; //delay(8000); //延时k=0b01001000; //1 //HA,HB,HC,s=PORTC&0b00000110; //0 0 1, C+A-PORTC=k|s; //delay(8000); //延时}void interrupt RB4_int(){char th;run_num++;if(run_num>10){run_num=10;}m=PORTB;//RB7-HA,RB5-HB,RB4-HCm&=0xB0; //1 0 1 1m^=0x90;//A=/A,B=B,C=/C //1 1n=m>>4; //switch(n){ //HA,HB,HC,// case 1: k=0b01001000;break; //0 0 1, C+A-// case 3: k=0b01100000;break; //0 1 1, A-B+// case 2: k=0b00100001;break; //0 1 0, B+C-// case 10:k=0b10000001;break; //1 1 0, C-A+// case 8: k=0b10010000;break; //1 0 0, A+B-// case 9: k=0b00011000;break; //1 0 1, B-C+// default:k=0b00000000; //其它(000,111),0x00,输出为无效case 1: k=0b00011000;break; //1 0 1, B-C+case 3: k=0b01001000;break; //0 0 1, C+A-case 2: k=0b01100000;break; //0 1 1, A-B+case 10:k=0b00100001;break; //0 1 0, B+C-case 8: k=0b10000001;break; //1 1 0, C-A+case 9: k=0b10010000;break; //1 0 0, A+B-default:k=0b00000000; //其它(000,111),0x00,输出为无s=PORTC&0b00000110; //取RC1,RC2状态PORTC=k|s; //输出PORTCif (RB7==0) {trial&=0b00110000;} //RB7=0if (RB5==0) {trial&=0b10010000;} //RB5=0if (RB4==0) {trial&=0b10100000;} //RB4=0if (lkk>1) {lkk--;} //每20次测试一次// tri=n;// if ((tri&=0b00001000)==0) {trial&=0b00110000;} //RB7=0// tri=n;// if ((tri&=0b00000010)==0) {trial&=0b10010000;} //RB5=0// tri=n;// if ((tri&=0b00000001)==0) {trial&=0b10100000;} //RB4=0// if (lkk>2) {lkk--;} //每20次测试一次else{while(trial!=0b00000000){GIE=0; //关全局中断pwm_real=pwm_hi; //PWM_real----PWM实时值CCPR1L=pwm_real; //设置PWM输出为最大CCPR1H=0x00; //CCP1CON=0x0c; //CCP1选择为PWM工作方式PR2=pwm_cycle; //设置PWM的周期TRISC=TRISC&0xfb; //设置RC2---PWM输出T2CON=0x00; //分频系数=0x00TMR2ON=1; //启用TMR2PORTC=0x00; //PORTB=PORTB&0xfe; //RB0=0,----输出低电平,禁止GAL输出while(1){PORTA^=0b00010000; //RA4闪动for (jm=15000;jm>1;jm--){asm("nop");}}}trial=0b10110000;lkk=10;}RBIF=0;}void max_min_compare(){if (pwm_real>pwm_hi) pwm_real=pwm_hi;if (pwm_real<pwm_lo) pwm_real=pwm_lo;}para_chushihua(); //参数初始化nointerupt_chushihua(); //禁止中断初始化Io_chushihua(); //I/O初始化PWM_chushihua(); //PWM初始化RA1=0; //RA1-PSW1发送低电平,接通电源RA5=0; //RA5-RSW1发送低电平,主电路充电延时RA2=0; //RA2,指示灯灭RA4=0; //RA4,指示灯灭delay(100); //主电路充电延时RB0=0; //ST/(-STOP)发送低电平,禁止GAL输出delay(100);RA1=1; //RA1-PSW1发送高电平,接通电源for(charge_delay=0;charge_delay<50;charge_delay++){delay(15000);}RA5=1; //RA5-RSW1发送高电平,主电路充电延时delay(100); //主电路充电延时PP: asm(" nop"); //RBIF=0; //禁止RB4-7中断,清RBIF 标志设定RBIE=0; //禁止RB4-7中断,RBIE设定GIE=0; //关全局中断RA2=0; //RA2,指示灯灭RA4=0; //RA4,指示灯灭run_flag=0; //运行标志---由RB2按钮设置while(run_flag==0) //----------主程序-------------//{ //RB2启动键,低电平有效if (RB2==0) run_flag=1; //运行标志---由RB2按钮设置delay(100); //延时} //while(run_flag==1) //运行,则执行......{int ope; //设定开环运行次数为12次int openloopn; //RB0=1; //ST/(-STOP)发送高电平,开放GAL输出delay(100); //延时RA4=1;// pwm_real=180;pwm_real=230;delay(500); //延时// ope=10; //设定开环运行次数为20次ope=3; //设定开环运行次数为20次for (openloopn=0;openloopn<=ope;openloopn++){ //00 0000000000000000CCPR1L=pwm_real; //设置开环下PWM输出值----130open_loopf(); //开环运行20次,启动} //----------------------- //000000000000000000delay(6000); //延时RBIF=0; //RB4-7中断,RBIF标志设定RBIE=1; //RB4-7中断,RBIE设定GIE=1; //开全局中断RA2=1; //-----------------------pwm_real=pwm_hi; //-----------------------ghl: asm(" nop"); //if ((pwm_real<110)&&(run_num<10)) //如果pwm_real<140,但是run_num<10,表明未动,则{ //protect_run();protect_run();}while(RA0==1) //RA0=1,过流和过温保护{ //delay(150); //调用延时程序protect_num++; //if (protect_num>30)//如果30次保护,则认为是真正保护(过温和过流保护软件滤波){protect();} //过流和过温保护} //protect_num=0; //if(RB1==1) flag_autohand=1; //自/手标志设定,标志设定else flag_autohand=0; //RB1=1---AUTO;自动//RB1=0---HAND;手动//----------------------- if (flag_autohand==1){ //111 11111111111111111if (pwm_real>pwm_lo) pwm_real-=1; //自动else pwm_real=pwm_lo;}//11111111111111111111else{if(RA3==0) //加(低有效), 则{if (pwm_real<pwm_hi) pwm_real+=1;else pwm_real=pwm_hi;}if(RC1==0) //减(低有效),则{if (pwm_real>pwm_lo) pwm_real-=1;else pwm_real=pwm_lo;}}max_min_compare();CCPR1L=pwm_real; //设置PWM输出delay(4500); //调用延时子程序while(RA0==1) //RA0------过流和过温保护输入,高电平保护{ //protect(); //过流和过温保护} //while(RB3==0){ //RB3停机键,低电平有效run_flag=0; //运行标志---由RB3按钮设置}if (run_flag==0) //停机,则跳转至......{for(;pwm_real<pwm_hi;pwm_real++){delay(2000); //至上限否?CCPR1L=pwm_real; //设置PWM输出为最大}RB0=0; //ST/(-STOP)发送低电平,禁止GAL输出para_chushihua(); //参数初始化nointerupt_chushihua(); //禁止中断初始化PWM_chushihua(); //PWM初始化run_num=0;goto PP;}else{// run_num=0;goto ghl;}}// goto PP;}。
实用标准文案目录1 总体设计框架 (3)2 硬件电路设计 (4)2.1 芯片介绍 (4)2.2 驱动电路 (9)2.3 按键控制电路 (10)3 程序编写 .................................................103.1 工作原理 (10)21程序书写过程3.2 ......................................................参考资料 (16)精彩文档.实用标准文案直流电机驱动Abstract 摘要:本文主要内容是利用PIC18F452单片机来控制直流电机,通过L293NE来驱动电机,通过按键来使其正转,反转。
Keywords 关键词:直流电机,PWM,L293NE精彩文档.实用标准文案总体设计框架1硬件电路利用驱动芯片L293D来驱动直流电机,按键则是单独引出。
如图1所示。
软件则是C语言编程。
PI驱C直动1流8电电F路机452图1硬件设计框精彩文档.实用标准文案2硬件电路设计2.1 芯片介绍首先,总体说明硬件电路设计,如图2 原理图,图3 PCB图以及图4板子的图所示。
三个输入信号,如图分别为RD4,RD5,RD6连上光耦的2脚,然后通过光耦的4脚引入L293D的使能引脚(12EN)以及输入引脚(1A,2A),然后L293D的输出引脚(1Y,2Y)通过H-桥型控制电路与直流电机连接。
图2 直流电机控制部分原理图精彩文档.实用标准文案PCB图图3直流电机控制部分成品板图4其中红线圈表示直流电机控制部分。
下面详细介绍各个芯片。
PIC18F452、1外部端口以及内部存储器是相同的。
上图的与PIC18F452PIC18F4580 。
U2精彩文档.实用标准文案2、光耦P521光耦主要的作用是保护单片机。
光耦的结构如图5所示。
图5 光耦P521结构在PCB中(如图6所示),即U7,U9,U10三个光耦,左下方方形孔为1引脚,按逆时针方向,依次为2,3,4引脚。
pic单片机直流无刷电机控制程序下载温馨提示:该文档是我店铺精心编制而成,希望大家下载以后,能够帮助大家解决实际的问题。
文档下载后可定制随意修改,请根据实际需要进行相应的调整和使用,谢谢!并且,本店铺为大家提供各种各样类型的实用资料,如教育随笔、日记赏析、句子摘抄、古诗大全、经典美文、话题作文、工作总结、词语解析、文案摘录、其他资料等等,如想了解不同资料格式和写法,敬请关注!Download tips: This document is carefully compiled by the editor. I hope that after you download them, they can help you solve practical problems. The document can be customized and modified after downloading, please adjust and use it according to actual needs, thank you!In addition, our shop provides you with various types of practical materials, such as educational essays, diary appreciation, sentence excerpts, ancient poems, classic articles, topic composition, work summary, word parsing, copy excerpts, other materials and so on, want to know different data formats and writing methods, please pay attention!Title: PIC单片机直流无刷电机控制程序Introduction在现代工业控制系统中,直流无刷电机的应用越来越广泛。
另一完整版#include "DSP281x_Device.h"#include "DSP281x_Examples.h"//#include "DSP281x_Globalprototypes.h"#include "DSP281x_Device.h"#include "DSP281x_Examples.h"void InitPieCtrl(void);void init_7219(void);void InitSysCtrl(void);void InitPieVectTable(void);void pdelay(void);void delay(void);interrupt void eva_capint1_isr(void);interrupt void eva_capint2_isr(void);interrupt void eva_timer1_isr(void);extern void DSP28x_usDelay(Uint32 Count);unsigned s=500;unsigned state;unsigned i,j;int32 x3=0,speed1,speed2=0;//数组供显示用unsigned K;unsigned y=0;int32 x1=0,x2=0;Uint16 counter=0;//===========PI参数===========float Kpspeed=10,Kispeed=0.01,Kcspeed=0.0046;int Nmin=0,Nmax=1500; //float RKspeed=0,Uspeed=0.0; //int Nref=300,N=0,Iref=0;int Espeed=0;//===============速度PID====================//void SPEED_PI(void) //{//Xispeed:速度调节器积分累积量Espeed=Nref-N;Uspeed=Kpspeed*Espeed+RKspeed;if(Uspeed<0){if((Nmin-Uspeed)>=0)Iref=Nmin;elseIref=(int)Uspeed;}else{if(Nmax-Uspeed<0)Iref=Nmax;elseIref=(int)Uspeed;}RKspeed=Kcspeed*(Iref-(int)Uspeed)+Espeed*Kispeed+RKspeed; Iref=1500-Iref;}//=============增调速=====================//void tiaosujian(void){if(Nref<=0){Nref=0;}else{Nref=Nref-1;}}//=============减调速=====================//void tiaosuzeng(void){if(Nref>=1500){Nref=1500;}else{Nref=Nref+1;}}//=============延时程序=====================//void pdelay(void){for(j=0;j<100;j++){ for (i = 0; i < 5; i++);}}//=============SPI初始化====================//void InitSpi(void){SpiaRegs.SPICCR.all=0x000F; //复位SPI模块,SPICLK 信号上升沿时,数据输出//单个移位序列周期移入,移出的位数为16SpiaRegs.SPICTL.all=0x000E; //SPICLK 信号延时半个周期,主模式,使能发送SpiaRegs.SPIBRR=120;SpiaRegs.SPICCR.bit.SPISWRESET=1; //SPI准备好发送或接收下一个字符//=============MAX7219 Init====================== GpioDataRegs.GPFCLEAR.bit.GPIOF3=1;SpiaRegs.SPIRXBUF=SpiaRegs.SPIRXBUF;SpiaRegs.SPITXBUF=0x09FF;while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG==1){};GpioDataRegs.GPFSET.bit.GPIOF3=1;GpioDataRegs.GPFCLEAR.bit.GPIOF3=1;SpiaRegs.SPIRXBUF=SpiaRegs.SPIRXBUF;SpiaRegs.SPITXBUF=0x0A0A;while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG==1){};GpioDataRegs.GPFSET.bit.GPIOF3=1;GpioDataRegs.GPFCLEAR.bit.GPIOF3=1;SpiaRegs.SPIRXBUF=SpiaRegs.SPIRXBUF;SpiaRegs.SPITXBUF=0x0B03;while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG==1){};GpioDataRegs.GPFSET.bit.GPIOF3=1;GpioDataRegs.GPFCLEAR.bit.GPIOF3=1;SpiaRegs.SPIRXBUF=SpiaRegs.SPIRXBUF;SpiaRegs.SPITXBUF=0x0C01;while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG==1){};GpioDataRegs.GPFSET.bit.GPIOF3=1;GpioDataRegs.GPFCLEAR.bit.GPIOF3=1;SpiaRegs.SPIRXBUF=SpiaRegs.SPIRXBUF;SpiaRegs.SPITXBUF=0x0F00;while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG==1){};GpioDataRegs.GPFSET.bit.GPIOF3=1;}//===========显示子程序=====================//void XianShi(long int m){Uint16 dizhi[4]={0x0100,0x0200,0x0300,0x0400};Uint16 shu[4];int i;for(i=3;i>=0;i--){shu[i]=m%10;m=m/10;GpioDataRegs.GPFCLEAR.bit.GPIOF3=1;SpiaRegs.SPIRXBUF=SpiaRegs.SPIRXBUF;SpiaRegs.SPITXBUF=dizhi[i]|shu[i];while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG==1){};GpioDataRegs.GPFSET.bit.GPIOF3=1;}}//==============EV A初始化子程序=============/void EV A_Timer1(){//EvaRegs.GPTCONA.all=0;EvaRegs.T1CNT=0x0000; //T1CNT(定时器1的计数寄存器)EvaRegs.T1PR=1500;EvaRegs.ACTRA.all = 0x0000; //比较方式寄存器,设置比较器输出引脚的方式EvaRegs.CMPR1 = 500; //全比较寄存器EvaRegs.CMPR2 = 500;EvaRegs.T2CNT=0x0000;EvaRegs.T2PR=0xFFFF;EvaRegs.T2CON.all=0x1740;EvaRegs.EV AIMRA.bit.T1UFINT=1; //EV AIMRA(EV A的中断屏蔽寄存器A).T1PINT(通用定时器1的周期中断使能)EvaRegs.EV AIFRA.bit.T1UFINT=1;//EV AIFRA(EV A的中断标志寄存器.T1PINT(通用定时器1的周期中断标志)//写1清除定时器1的周期中断标志CONA.all = 0x82FF; //比较器控制寄存器EvaRegs.T1CON.all=0x1002;//T1CON=000 10 000 0100 0000EvaRegs.T1CON.bit.TMODE=01;EvaRegs.T1CON.bit.TENABLE=1;EvaRegs.CAPCONA.all = 0;//EvaRegs.CAPCONA.all=0xA0F0;EvaRegs.CAPCONA.bit.CAP12EN = 1; //使能捕获单元1和2EvaRegs.CAPCONA.bit.CAP1EDGE = 3; //选用两边沿EvaRegs.CAPCONA.bit.CAP2EDGE = 3; //选用上两边沿EvaRegs.CAPCONA.bit.CAP12TSEL = 0; //选择定时器2*/EvaRegs.CAPFIFOA.bit.CAP1FIFO = 0; //状态寄存器清零EvaRegs.CAPFIFOA.bit.CAP2FIFO = 0; //状态寄存器清零EvaRegs.EV AIMRC.bit.CAP1INT = 1; //捕获1中断屏蔽位使能EvaRegs.EV AIFRC.bit.CAP1INT = 1; //复位标志位EvaRegs.EV AIMRC.bit.CAP2INT = 1; //捕获1中断屏蔽位使能EvaRegs.EV AIFRC.bit.CAP2INT = 1; //复位标志位}//===============主程序=====================//void main(void){Uint16 num=0;DINT; //关总中断IER=0x0000; //禁止使能IFR=0x0000;InitSysCtrl(); //系统初始化InitGpio();InitSpi();EALLOW;SysCtrlRegs.PLLCR.all=0x0002;SysCtrlRegs.HISPCP.all=0x0000; //HISPCP(高速外设时钟预定标寄存器)//bit0~2=011:高速时钟的频率=SYSCKLOUT/6//高速时钟的频率=25M EDIS;EALLOW; //关闭寄存器保护GpioMuxRegs.GPAMUX.all=0x030F;//将A0-A3设成pwm 口,将A8、A9设成CAP口,将A4、A5设成IO口,做测试用,A10为IO口按键做保护用GpioMuxRegs.GPADIR.bit.GPIOA4=1;GpioMuxRegs.GPADIR.bit.GPIOA5=1;GpioMuxRegs.GPADIR.bit.GPIOA10=0;GpioMuxRegs.GPBMUX.bit.PWM7_GPIOB0=0;GpioMuxRegs.GPBMUX.bit.PWM8_GPIOB1=0;GpioMuxRegs.GPBDIR.bit.GPIOB0=0;GpioMuxRegs.GPBDIR.bit.GPIOB1=0;GpioMuxRegs.GPFMUX.all=0x000f;GpioMuxRegs.GPFMUX.bit.SPICLKA_GPIOF2=1; //选择复用SPISIMO,SPISTE,SPICLKGpioMuxRegs.GPFMUX.bit.SPISIMOA_GPIOF0=1;// GpioMuxRegs.GPFMUX.bit.SPISTEA_GPIOF3=1;GpioMuxRegs.GPFMUX.bit.SPISTEA_GPIOF3=0;GpioMuxRegs.GPFDIR.bit.GPIOF3=1;EDIS;EV A_Timer1();InitPieCtrl(); //初始化PIE控制寄存器InitPieVectTable();//重新映射定时器1的比较中断入口EALLOW;PieVectTable.CAPINT1 = &eva_capint1_isr; //中断使能PieVectTable.CAPINT2 = &eva_capint2_isr; //中断使能PieVectTable.T1UFINT = &eva_timer1_isr; //定时器下溢中断使能EDIS;//使能T1下溢中断:PIE-组2,中断6,使能捕获中断PieCtrlRegs.PIEIER2.bit.INTx6 = 1;PieCtrlRegs.PIEIER3.bit.INTx5 = 1;PieCtrlRegs.PIEIER3.bit.INTx6 = 1;//使能CPU INT2,GP-Timer1的下溢中断连接到该中断,使能捕获中断IER = 0x0006;//全局中断使能,并使能具有更高优先级的实时调试方式EINT; //使能全局中断INTMERTM;//使能全局实时中断DBGMwhile(1){if(GpioDataRegs.GPBDAT.bit.GPIOB0==1){tiaosuzeng();}asm(" nop");asm(" nop");if(GpioDataRegs.GPBDAT.bit.GPIOB1==1){tiaosujian();}asm(" nop");asm(" nop");InitSpi();XianShi(N);num++;if(num==9999){num=0;}DELAY_US(80000L);InitSpi();}}//============捕获1 中断处理================// interrupt void eva_capint1_isr(void){// asm(" RPT #150 || NOP"); //空操作延时GpioMuxRegs.GPAMUX.all = 0x000F;GpioMuxRegs.GPADIR.bit.GPIOA8=0;GpioMuxRegs.GPADIR.bit.GPIOA9=0;if(GpioDataRegs.GPADAT.bit.GPIOA8==0&&GpioDataRegs.GPADAT.bit.GPIOA9==0){ state=0;}if(GpioDataRegs.GPADAT.bit.GPIOA8==1&&GpioDataRegs.GPADAT.bit.GPIOA9==1){state=3;}if(GpioDataRegs.GPADAT.bit.GPIOA8==1&&GpioDataRegs.GPADAT.bit.GPIOA9==0){state=2;}if(GpioDataRegs.GPADAT.bit.GPIOA8==0&&GpioDataRegs.GPADAT.bit.GPIOA9==1){state=1;}// x2=EvaRegs.T2CNT;x2=counter;x3=(long int)(x2-x1);if(x3<0){x3+=65536;}speed1=8330/x3;N=speed1*6;x1=x2;GpioMuxRegs.GPAMUX.all = 0x030F;EvaRegs.EV AIFRC.bit.CAP1INT = 1;PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; }//============捕获2中断处理================// interrupt void eva_capint2_isr(void){//asm(" nop");GpioMuxRegs.GPAMUX.all = 0x000F;GpioMuxRegs.GPADIR.bit.GPIOA8=0;GpioMuxRegs.GPADIR.bit.GPIOA9=0;if(GpioDataRegs.GPADAT.bit.GPIOA8==1&&GpioDataRegs.GPADAT.bit.GPIOA9==0){state=2;}if(GpioDataRegs.GPADAT.bit.GPIOA8==0&&GpioDataRegs.GPADAT.bit.GPIOA9==1){state=1;}if(GpioDataRegs.GPADAT.bit.GPIOA8==0&&GpioDataRegs.GPADAT.bit.GPIOA9==0){ state=0;}if(GpioDataRegs.GPADAT.bit.GPIOA8==1&&GpioDataRegs.GPADAT.bit.GPIOA9==1){state=3;}GpioMuxRegs.GPAMUX.all = 0x030F;EvaRegs.EV AIFRC.bit.CAP2INT = 1;PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;}//============T1下溢中断处理================//interrupt void eva_timer1_isr(void){counter++;SPEED_PI();EvaRegs.CMPR1 = Iref;EvaRegs.CMPR2 = Iref;if(GpioDataRegs.GPADAT.bit.GPIOA10==1){ if(state==0){EvaRegs.ACTRA.all = 0x000A;GpioDataRegs.GPADAT.bit.GPIOA4=1;GpioDataRegs.GPADAT.bit.GPIOA5=1;}if( state==3){EvaRegs.ACTRA.all = 0x00A0;GpioDataRegs.GPADAT.bit.GPIOA4 = 0;GpioDataRegs.GPADAT.bit.GPIOA5 = 0;}if( state==2){EvaRegs.ACTRA.all = 0x0082;GpioDataRegs.GPADAT.bit.GPIOA4=0;GpioDataRegs.GPADAT.bit.GPIOA5=1;}if( state==1){EvaRegs.ACTRA.all = 0x0028;GpioDataRegs.GPADAT.bit.GPIOA4=1;GpioDataRegs.GPADAT.bit.GPIOA5=0;}} //通过以上不同的组合,可以改变I/O口的状态,//GpioDataRegs.GPEDAT.all查看I/O口状态EvaRegs.EV AIFRA.bit.T1UFINT=1;PieCtrlRegs.PIEACK.all=PIEACK_GROUP2; //#define PIEACK_GROUP2 0x0002;}。
#include <pic168xa.h> //2008.4.24--14点00分#include <math.h>#include <stdlib.h>int charge_delay,jm,lkk,trial,run_num,protect_num;char m,n,k,s,L,tri;char hall_num; //循环次数char hall_number; //1+3+2+10+8+9=33(一个循环和),hallless_protect()int pwm_hi; // pwm占空比上限int pwm_cycle; // pwm周期int pwm_lo; // pwm占空比下限,由A/D结果确定int pwm_real; // pwm占空比实际int ad_result; // A/D转换结果bit ghy,run_flag; //运行标志---0,未运行,停止bit flag_autohand; //开始为-----自动void delay(delay_num)int delay_num;{int j;for (j=delay_num;j>1;j--){asm("nop");}}union adres{int y1;unsigned char adre[2];}adresult;void para_chushihua(){protect_num=0;trial=0b10110000;tri=0x00;lkk=10;hall_num=0x00;hall_number=0x00;run_flag=0; //运行标志---0,未运行,停止flag_autohand=1; //开始为-----自动pwm_cycle= 240; // pwm周期// pwm_hi=pwm_cycle-5; // pwm占空比上限pwm_hi=pwm_cycle-1; // pwm占空比上限pwm_real=pwm_cycle; // 实际pwm占空比为pwm周期上限pwm_lo=0x0A; //设定下限+++++++++++++++++++++++++++++++++++++++ ++++++++}void nointerupt_chushihua(){INTCON=0X00; //禁止中断}void Io_chushihua(){// ADCON1=0x8e; //RA0/AN0--VOLTAGE 电压采样,右对齐1ADCON1=0x86; //设定RA0--RA6设定为I/O口;TRISA =0x09; //RA0---PROTECT保护(电流保护和过温保护)--输出,0--不保护,1--保护;//RA1----PSW1,继电器,输出,0,电源接通//RA2----指示灯,输出0--->>//RA3----按键,加,输入 1//RA4----指示灯,输出0--->>//RA5----RSW1,继电器,输出0,软启充电PORTA=PORTA&0x09; //RA1=0,----输出低电平,PSW1,继电器断//RA2=0,----输出低电平,指示灯灭//RA4=0,----输出低电平,指示灯灭//RA5=0,----输出低电平,RSW1,继电器断RBPU=0; //RB端口内部弱上拉电路禁止TRISB =0xfe; //RB7=1, 空----输入//RB6=1----HA,输入//RB5=1----HB,输入//RB4=1----HC,输入//RB3=1----停,输入,按钮//RB2=1----启,输入,按钮//RB1=1----自/手选择,输入,开关//RB0=0----ST/STOP,输出,控制GAL PORTB=PORTB&0xfe; //RB0=0,----输出低电平,禁止GAL输出TRISC =0x02; //RC7---A1+,PWMA1+,输出0//RC6---A1, 输出0//RC5---B1+,输出0//RC4---B1,输出0//RC3---C1+,输出0//RC2---CCP1(PWM),输出,死区0//RC1----减,输入,按钮 1//RC0---C1,输出0 PORTC=0x06;}void protect(){ //过流和过温保护GIE=0; //关全局中断pwm_real=pwm_hi; //PWM_real----PWM实时值CCPR1L=pwm_real; //设置PWM输出为最大CCPR1H=0x00; //CCP1CON=0x0c; //CCP1选择为PWM工作方式PR2=pwm_cycle; //设置PWM的周期TRISC=TRISC&0xfb; //设置RC2---PWM输出T2CON=0x00; //分频系数=0x00TMR2ON=1; //启用TMR2PORTC=0x00; //PORTB=PORTB&0xfe; //RB0=0,----输出低电平,禁止GAL输出while(1){PORTA^=0b00010100;delay(15000); //延时}}void protect_run(){ //过流和过温保护GIE=0; //关全局中断pwm_real=pwm_hi; //PWM_real----PWM实时值CCPR1L=pwm_real; //设置PWM输出为最大CCPR1H=0x00; //CCP1CON=0x0c; //CCP1选择为PWM工作方式PR2=pwm_cycle; //设置PWM的周期TRISC=TRISC&0xfb; //设置RC2---PWM输出T2CON=0x00; //分频系数=0x00TMR2ON=1; //启用TMR2PORTC=0x00; //PORTB=PORTB&0xfe; //RB0=0,----输出低电平,禁止GAL输出while(1){// PORTA^=0b00010000; //RA4闪动PORTA^=0b00000100; //RA2闪动delay(15000); //延时}}void PWM_chushihua(){// CCPR1L=0xa0;// CCPR1H=0x00;run_num=0;pwm_real=pwm_hi; //PWM_real----PWM实时值CCPR1L=pwm_real; //设置PWM输出为最大CCPR1H=0x00; //CCP1CON=0x0c; //CCP1选择为PWM工作方式PR2=pwm_cycle; //设置PWM的周期TRISC=TRISC&0xfb; //设置RC2---PWM输出T2CON=0x00; //分频系数=0x00TMR2ON=1; //启用TMR2}void open_loopf() //开环运行50次,启动{k=0b00011000; //5 //HA,HB,HC,s=PORTC&0b00000110; //1 0 1, B-C+PORTC=k|s; //delay(8000); //延时k=0b10010000; //4 //HA,HB,HC,s=PORTC&0b00000110; //1 0 0, A+B-PORTC=k|s; //delay(8000); //延时k=0b10000001; //6 //HA,HB,HC,s=PORTC&0b00000110; //1 1 0, C-A+PORTC=k|s; //delay(8000); //延时k=0b00100001; //2 //HA,HB,HC,s=PORTC&0b00000110; //0 1 0, B+C-PORTC=k|s; //delay(8000); //延时k=0b01100000; //3 //HA,HB,HC,s=PORTC&0b00000110; //0 1 1, A-B+PORTC=k|s; //delay(8000); //延时k=0b01001000; //1 //HA,HB,HC,s=PORTC&0b00000110; //0 0 1, C+A-PORTC=k|s; //delay(8000); //延时}void interrupt RB4_int(){char th;run_num++;if(run_num>10){run_num=10;}m=PORTB;//RB7-HA,RB5-HB,RB4-HCm&=0xB0; //1 0 1 1 m^=0x90;//A=/A,B=B,C=/C //1 1 n=m>>4; //switch(n){ //HA,HB,HC,// case 1: k=0b01001000;break; //0 0 1, C+A-// case 3: k=0b01100000;break; //0 1 1, A-B+// case 2: k=0b00100001;break; //0 1 0, B+C-// case 10:k=0b10000001;break; //1 1 0, C-A+// case 8: k=0b10010000;break; //1 0 0, A+B-// case 9: k=0b00011000;break; //1 0 1, B-C+// default:k=0b00000000; //其它(000,111),0x00,输出为无效case 1: k=0b00011000;break; //1 0 1, B-C+case 3: k=0b01001000;break; //0 0 1, C+A-case 2: k=0b01100000;break; //0 1 1, A-B+case 10:k=0b00100001;break; //0 1 0, B+C-case 8: k=0b10000001;break; //1 1 0, C-A+case 9: k=0b10010000;break; //1 0 0, A+B-default:k=0b00000000; //其它(000,111),0x00,输出为无效}s=PORTC&0b00000110; //取RC1,RC2状态PORTC=k|s; //输出PORTCif (RB7==0) {trial&=0b00110000;} //RB7=0if (RB5==0) {trial&=0b10010000;} //RB5=0if (RB4==0) {trial&=0b10100000;} //RB4=0if (lkk>1) {lkk--;} //每20次测试一次// tri=n;// if ((tri&=0b00001000)==0) {trial&=0b00110000;} //RB7=0// tri=n;// if ((tri&=0b00000010)==0) {trial&=0b10010000;} //RB5=0// tri=n;// if ((tri&=0b00000001)==0) {trial&=0b10100000;} //RB4=0// if (lkk>2) {lkk--;} //每20次测试一次else{while(trial!=0b00000000){GIE=0; //关全局中断pwm_real=pwm_hi; //PWM_real----PWM 实时值CCPR1L=pwm_real; //设置PWM输出为最大CCPR1H=0x00; //CCP1CON=0x0c; //CCP1选择为PWM工作方式PR2=pwm_cycle; //设置PWM的周期TRISC=TRISC&0xfb; //设置RC2---PWM输出T2CON=0x00; //分频系数=0x00TMR2ON=1; //启用TMR2PORTC=0x00; //PORTB=PORTB&0xfe; //RB0=0,----输出低电平,禁止GAL输出while(1){PORTA^=0b00010000; //RA4闪动for (jm=15000;jm>1;jm--){asm("nop");}}}trial=0b10110000;lkk=10;}RBIF=0;}void max_min_compare(){if (pwm_real>pwm_hi) pwm_real=pwm_hi;if (pwm_real<pwm_lo) pwm_real=pwm_lo;}main(void){para_chushihua(); //参数初始化nointerupt_chushihua(); //禁止中断初始化Io_chushihua(); //I/O初始化PWM_chushihua(); //PWM初始化RA1=0; //RA1-PSW1发送低电平,接通电源RA5=0; //RA5-RSW1发送低电平,主电路充电延时RA2=0; //RA2,指示灯灭RA4=0; //RA4,指示灯灭delay(100); //主电路充电延时RB0=0; //ST/(-STOP)发送低电平,禁止GAL输出delay(100);RA1=1; //RA1-PSW1发送高电平,接通电源for(charge_delay=0;charge_delay<50;charge_delay++){delay(15000);}RA5=1; //RA5-RSW1发送高电平,主电路充电延时delay(100); //主电路充电延时PP: asm(" nop"); //RBIF=0; //禁止RB4-7中断,清RBIF 标志设定RBIE=0; //禁止RB4-7中断,RBIE设定GIE=0; //关全局中断RA2=0; //RA2,指示灯灭RA4=0; //RA4,指示灯灭run_flag=0; //运行标志---由RB2按钮设置while(run_flag==0) //----------主程序-------------//{ //RB2启动键,低电平有效if (RB2==0) run_flag=1; //运行标志---由RB2按钮设置delay(100); //延时} //while(run_flag==1) //运行,则执行......{int ope; //设定开环运行次数为12次int openloopn; //RB0=1; //ST/(-STOP)发送高电平,开放GAL输出delay(100); //延时RA4=1;// pwm_real=180;pwm_real=230;delay(500); //延时// ope=10; //设定开环运行次数为20次ope=3; //设定开环运行次数为20次for (openloopn=0;openloopn<=ope;openloopn++){ //0 00000000000000000CCPR1L=pwm_real; //设置开环下PWM输出值----130open_loopf(); //开环运行20次,启动} //----------------------- //000000000000000000delay(6000); //延时RBIF=0; //RB4-7中断,RBIF标志设定RBIE=1; //RB4-7中断,RBIE设定GIE=1; //开全局中断RA2=1; //----------------------- pwm_real=pwm_hi; //-----------------------ghl: asm(" nop"); //if ((pwm_real<110)&&(run_num<10)) //如果pwm_real<140,但是run_num<10,表明未动,则{ //protect_run();protect_run();}while(RA0==1) //RA0=1,过流和过温保护{ //delay(150); //调用延时程序protect_num++; //if (protect_num>30)//如果30次保护,则认为是真正保护(过温和过流保护软件滤波){protect();} //过流和过温保护} //protect_num=0; //if(RB1==1) flag_autohand=1; //自/手标志设定,标志设定else flag_autohand=0; //RB1=1---AUTO;自动//RB1=0---HAND;手动//----------------------- if (flag_autohand==1){ //11 111111111111111111if (pwm_real>pwm_lo) pwm_real-=1; //自动else pwm_real=pwm_lo;}//11111111111111111111else{if(RA3==0) //加(低有效), 则{if (pwm_real<pwm_hi) pwm_real+=1;else pwm_real=pwm_hi;}if(RC1==0) //减(低有效),则{if (pwm_real>pwm_lo) pwm_real-=1;else pwm_real=pwm_lo;}}max_min_compare();CCPR1L=pwm_real; //设置PWM输出delay(4500); //调用延时子程序while(RA0==1) //RA0------过流和过温保护输入,高电平保护{ //protect(); //过流和过温保护} //while(RB3==0){ //RB3停机键,低电平有效run_flag=0; //运行标志---由RB3按钮设置}if (run_flag==0) //停机,则跳转至......{for(;pwm_real<pwm_hi;pwm_real++){delay(2000); //至上限否?CCPR1L=pwm_real; //设置PWM输出为最大}RB0=0; //ST/(-STOP)发送低电平,禁止GAL输出para_chushihua(); //参数初始化nointerupt_chushihua(); //禁止中断初始化PWM_chushihua(); //PWM初始化run_num=0;goto PP;}else{// run_num=0;goto ghl;}}// goto PP;}。
目录1 总体设计框架 (3)2 硬件电路设计 (4)2.1 芯片介绍 (4)2.2 驱动电路 (9)2.3 按键控制电路 (10)3程序编写 (10)3.1 工作原理 (10)3.2 程序书写过程 (12)参考资料 (16)直流电机驱动Abstract 摘要:本文主要内容是利用PIC18F452单片机来控制直流电机,通过L293NE来驱动电机,通过按键来使其正转,反转。
Keywords 关键词:直流电机,PWM,L293NE1总体设计框架硬件电路利用驱动芯片L293D来驱动直流电机,按键则是单独引出。
如图1所示。
软件则是C语言编程。
图1硬件设计框2硬件电路设计2.1 芯片介绍首先,总体说明硬件电路设计,如图2 原理图,图3 PCB图以及图4板子的图所示。
三个输入信号,如图分别为RD4,RD5,RD6连上光耦的2脚,然后通过光耦的4脚引入L293D的使能引脚(12EN)以及输入引脚(1A,2A),然后L293D的输出引脚(1Y,2Y)通过H-桥型控制电路与直流电机连接。
图2 直流电机控制部分原理图图3直流电机控制部分PCB图图4 成品板其中红线圈表示直流电机控制部分。
下面详细介绍各个芯片。
1、PIC18F452PIC18F452与PIC18F4580外部端口以及内部存储器是相同的。
上图的U2。
2、光耦P521光耦主要的作用是保护单片机。
光耦的结构如图5所示。
图5 光耦P521结构在PCB中(如图6所示),即U7,U9,U10三个光耦,左下方方形孔为1引脚,按逆时针方向,依次为2,3,4引脚。
光耦的1脚通过电阻与电源连接,2脚为输入引脚,3脚与地相连,4脚为输出引脚。
经试验测得,则当1脚输入高电平时,4脚也输出高电平。
则当1脚输入低电平时,4脚输出低电平。
图6 光耦外形图3、电阻一共用到7个大小为470Ω的电阻(分别为R16,R17,R18,R19,R20,R21,R22)和3个大小为1kΩ(分别为R23,R24,R25)。
题目基于PIC18F458的直流电动机PWM调速控制系统设计指导教师张钟铋学生姓名刘志宇专业电气自动化班级2012级电子系日期2013年6月摘要:本文是一套基于PIC单片机的直流电机控制器,作为其配套的试验装置。
根据系统的要求完成了整体方案设计和系统选型,针对所的控制方案对控制系统的软、硬件设计作了详细论述。
硬件部分先作了整体设计,然后介绍了以PIC16F458单片机为核心的硬件构成,对键盘电路、测量电路、显示电路等作了详细阐述;软件部分采用模块化设计思想,编制了各个模块的流程图。
论述了软件的设计思想和方法;实现了对直流电动机转动参数的设置、启动、停止、加速、减速和显示等功能。
利用PIC系列芯片进行低成本直流电动机控制系统的设计,能够简化系统构成、降低系统成本、增强系统性能、满足更多应用场合的需要。
针对直流电机运行环境恶劣、干扰严重的特点,从系统的硬件设计、软件设计等多方面进行抗干扰的综合考虑,并利用多种软件和硬件技术来提高和改善系统的抗干扰能力,有效地提高了系统的可靠性和实用性。
1 绪论1.1 引言当今,自动化控制系统已经在各行各业得到了广泛的应用和发展,而直流调速控制作为电气传动的主流在现代化生产中起着主要作用。
为了满足运行、生产、工艺的要求往往需要对另一类设备如风机、水泵等进行控制:为了减少运行损耗,节约电能也需要对电机进行调速。
电机调速系统由控制部分、功率部分和电动机三大要素组成一个有机整体。
各部分之间的不同组合,可构成多种多样的电机调速系统。
三十多年来,首先实现了整流器的更新换代,以晶闸管整流装置取代了习用已久的直流发电机电动机组及水银整流装置使直流电气传动完成了一次大的跃进。
同时,控制电路已经实现高集成化、小型化、高可靠性及低成本。
以上技术的应用,使直流调速系统的性能指标大幅提高,应用范围不断扩大。
直流调速技术不断发展,走向成熟化、完善化、系列化、标准化,在可逆脉宽调速、高精度的电气传动领域中仍然难以替代1.2 直流电机基本调速方法直流电动机分为有换向器和无换向器两大类。
;*************************************************;MCS51单片机控制直流无刷电机程序;*************************************************org 00hajmp startorg 30h;**********检测键盘状态的程序****************START:mov p0,#0ffh ;置p0为输入口,将P0口置为1,用于检查按键是否按下jnb p0.0,QIDONG ;按键S2按下,p0.0为0,进入启动(正转)程序jnb p0.1,FANZHUAN ;按键S3按下,p0.1为0,进入反转程序jnb p0.2,JITING ;按键S4按下,p0.2为0,进入急停程序jnb p0.3,JIASU ;按键S5按下,p0.3为0,进入加速程序jnb p0.4,JIANSU ;按键S6按下,p0.4为0,进入减速程序jnb p0.5,TINGZHI ;按键S7按下,P0.5为0,进入停止程序ajmp start;************启动程序,默认为顺时针转动,转速为2000RPM*********** QIDONG:LCALL YANSHI ;调用延时子程序,目的:软件消除按键抖动JNB P0.0,QILJMP START ;软件消抖后,若p0.0为1,则认为按键未按下,回到检测按键状态程序QI:clr p0.6 ;p0.6接电机R/S端,将其清零表示电机可以运行setb p0.7 ;p0.7接DIR端,为1,则与COM端断开,电机正转mov p2,#0Bh ;p2.0接CH1,p2.1接CH2,p2.2接CH3,将速度设定为2000RPM lcall XIANSHI ;显示设定速度LJMP START ;执行完启动程序后,回到检测按键状态程序;***************反转程序,也即逆时针转动***************** FANZHUAN:LCALL YANSHI ;调用延时子程序,目的:软件消除按键抖动JNB P0.1,FANLJMP START ;软件消抖后,若p0.0为1,则认为按键未按下,回到检测按键状态程序FAN:clr p2.3 ;接通BRK端,使电机急停lcall PANTING ;调用判停程序,能从判停程序中返回,说明机已停setb p2.3 ;断开BRK端,解除急停状态clr p0.7 ;接通DIR端,使电机逆时针转动lcall XIANSHI ;显示设定速度LJMP START ;执行完启动程序后,回到检测按键状态程序;*****************急停程序*********************JITING:LCALL YANSHI ;调用延时子程序,目的:软件消除按键抖动JNB P0.2,JILJMP START ;软件消抖后,若p0.0为1,则认为按键未按下,回到检测按键状态程序JI:clr p2.3 ;接通BRK端,使电机急停lcall PANTING ;调用判停程序,若能从中返回,说明电机已停LJMP START ;执行完启动程序后,回到检测按键状态程序;***************加速程序,每按一次键,加速500rpm**************** JIASU:LCALL YANSHI ;调用延时子程序,目的:软件消除按键抖动JNB P0.3,JIALJMP START ;软件消抖后,若p0.0为1,则认为按键未按下,回到检测按键状态程序JIA:mov a,p2 ;将p2的值复制到累加器a中anl a,#07h ;取ch3ch2ch1的值,并放到累加器a中jz START ;若a中值为0,则速度已经最大,不再加速,回到检测按键状态程序mov r0,p2dec r0mov p2,r0 ;加速500rpm(参考电机驱动器说明中的多段速度选择部分)lcall XIANSHI ;显示设定的速度LJMP START ;执行完启动程序后,回到检测按键状态程序;********************减速程序,每按一次键,减速500rpm**************** JIANSU:LCALL YANSHI ;调用延时子程序,目的:软件消除按键抖动JNB P0.4,JIANLJMP START ;软件消抖后,若p0.0为1,则认为按键未按下,回到检测按键状态程序JIAN:mov a,p2anl a,#07h ;取ch3ch2ch1的值cjne a,#07h,JS ;若a中数值为07h,则速度已为0,ljmp START ;若速度为0,则程序回到开始程序,不再减速,以防出错JS:mov a,P2inc amov P2,a ;减速500rpm(参考电机驱动器说明中的多段速度选择部分)lcall XIANSHI ;显示设定的速度ljmp START ;执行完启动程序后,回到检测按键状态程序;********************停止程序***********************TINGZHI:LCALL YANSHI ;调用延时子程序,目的:软件消除按键抖动JNB P0.5,TINGLJMP START ;软件消抖后,若p0.0为1,则认为按键未按下,回到检测按键状态程序TING:setb p0.6 ;p0.6接R/S端,为1,则与COM端断开lcall PANTING ;调用判停程序,若能从中返回,说明电机已停LJMP START ;执行完启动程序后,回到检测按键状态程序;*****************延时10ms,这是一个子程序,功能是延时10毫秒************* YANSHI:mov a,#0 ;对累加器a置零,延时用y:mov r1,#00h ;对寄存器r1置零,延时用inc r1cjne r1,#0ffh,y ;延时1msinc acjne a,#10,y ;延时10×1=10msret;*******判停程序,这是一个子程序,若能从判停程序中返回,则说明电机已停******** PANTING:jnb p2.4,yanshi250ms ;若speed端为0,则进入延时程序ajmp PANTING ;若speed端为1,则返回PANTING,等待speed端出现0电平yanshi250ms:clr p2.6 ;允许对计数器置数mov p3,#08h ;对计数器置入数8setb p2.6 ;计数器开始计数mov a,#0 ;对累加器a置零,延时用y250:mov r1,#00h ;对寄存器r1置零,延时用inc r1jb p2.5,PANTING ;若期間Tc为1,则电机未停,返回PANTING,继续判断cjne r1,#0ffh,y250 ;延时1msinc acjne a,#250,y250 ;延时250ms,ret;若至延时结束Tc一直不改变状态,则说明speed端口无脉冲输出,认为电机停转,程序;返回。
附录1. C语言源程序:#include"stdio.h"#include"myapp.h"#include"ICETEK-VC5502-EDU.h"#include"scancode.h"#include"lcd.h"#define CTRSTATUS (*(unsigned int * )0x608000) //port8000#define CTRLED (*(unsigned int * )0x608004) //port8004#define MCTRKEY (*(unsigned int * )0x608005) //port8005#define CTRCLKEY (*(unsigned int * )0x608006) //port8006#define CTRMOTORBSPEED (*(unsigned int * )0x608003)void InitMcBSP();void INTR_init( void );void InitForMotorB( void );void showparameters();void LCDPutString(unsigned int * pData,int x,int y,unsigned int nCharNumber,unsigned color);void PIDControl(int rk,int yk);void PrintParameters();//定时器分频参数#define T100 99 // 100个时钟周期中断一次#define T2Hz 20000 // 20000个时钟周期读取速度一次//工作变量usigned int uWork,uN,nCount,nCount1,nCount2,nCount3,nCount4;int nSSS,nJSSpeed,pwm1;int md,wc;unsigned int nScreenBuffer[30*128];float a=0.6f,b=0.2f,c=0.1f,duk;int ek,ek1,ek2,tz;int nInput;unsigned int *www=(unsigned int *)0x608003;Int m_nSpeed,m_bPCSet;// 主函数main(){unsigned char ccc;int speed[100],sp,lj;float ljh;int i,w1,w2,w3;unsigned int uWork1;unsigned int bWork1,*pWork;int breakflage;// 初始化工作变量for ( sp=0;sp<100;sp++ )speed[sp]=0;for ( sp=0;sp<1024;sp++ ) nScreenBuffer[sp]=0;sp=nSSS=nCount=nCount1=nCount2=nCount3=nCount4=nJSSpeed=0;nInput=tz=wc =0;ek=ek1=ek2=0;uN=40;md=70;pwm1=60;m_nSpeed=70;m_bPCSet=0;inputspeed=0;uWork1=0;breakflage=0;initemif();CLK_init();*(int*)0x400001=1;CREG=1; //使能外部总线接口InitCTR();CTRGR=0x80;CTRGR=0;CTRGR=0x80;LCDTurnoff();// 设置显示参数和内容LCDSetDelay(1); //设置延时等待参数LCDSetScreenBuffer(nScreenBuffer); // 显示缓冲区for (bWork=0,pWork=nScreenBuffer;bWork<30*128;bWork++,pWork++) (*pWork=0)LCDTurnOn();//打开显示LCDCLS();//清除显示内存LCDPutCString(str1,0,127,8,0);LCDPutCString(str2,0,111,2,1);LCDPutCString(str3,68,111,2,1);LCDPutCString(str4,68,79,2,1);LCDPutCString(str5,68,95,2,1);LCDPutCString(str6,0,95,2,1);LCDPutCString(str7,0,79,3,1);ShowParamctors();//参数显示InitMcBSP();INTR-init();InitForMotorB();While(!breakflage){if(nCount==0) //读取键盘标志{uWork=MCTRKEY;CTRCLKEY=0;Switch(uWork1){Casc 128;if(inputspecd!=0){Md=inputspecd;Inputspecd=0;LCDPutCString(numbers+104,104,79,1,1);LCDPutCString(numbers+104,112,79,1,1);LCDPutCString(numbers+104,120,79,1,1);LCDRefreshScreen();}break;case 64;breakflage=1;case 1;inputspeed=inputspeed+1break;case 2;inputspeed=inputspeed-1;break;case 4;inputspeed=inputspeed+10;break;case 8;inputspeed=inputspeed-10;break;}if(inputspeed>90){inputspeed=90;}if(inputspeed<0){inputspeed=0;}w1=inputspeed%1000/100;w2=inputspeed%100/10;w3=inputspeed%10; LCDPutString(numbers+w1*8,104,79,1,1);LCDPutString(numbers+w2*8,112,79,1,1);LCDPutString(numbers+w3*8,120,79,1,1);LCDRefreshScreen();}if(m-bPCSet){m-bPCSst=0;if (m-nSpeed>=0&&m-nSpeed<256){md=m-nSpeed;LCDPutCString(numbers+104,104,79,1,1); LCDPutCString(numbers+104,112,79,1,1); LCDPutCString(numbers+104,120,79,1,1); LCDRefreshScreen();printparameters();}}if(nJSSpeed==0) //读取速度标志{LED=1;nJSSpeed=0;ccc=CTRMOTORBSPEED; //读取端口速度计数ccc=ccc&0xff;nSSS=ccc;if(nSSS>=0 && nSSS<400) //合法性检测{speed(sp)=Nssssp++;sp%=33;}if(sp==0) //读取实际速度{lj=0;ljh=0;for(i=0;i<33;i++){if(speed(i)>=0&&speed(i)<400){ljh+=speed(i);lj++;}}nCount3++;nCount3%=3;if(nCount3==2){PIDControl(md,wc); //调用PID算法控制程序uN=100-pwml; //利用占空比调整控制Showparameters(); //显示各参数到LCD}CloseCTR();exit(0);}//PID算法控制子程序void PIDControl(int rk,int yk){ek=rk-yk;duk=a*ek+b*ek1+c*ek2; //计算控制输出ek2=ek1; ek1=ek;tz=(int)duk;pwm1+=tz; //计算当前占空比if(pwml<0) pwml=0;else if(pwml>99) pwml=99;}void interrupt Timer(){uWork=PCR1; //pwml输出if(nCont1>u N){uWork=4; //根据占空比设置FSR状态}else{uWork&=0x0fffb;}PCR1=uWork;//设置中断控制寄存器void INTR-init(void){asm(“BSET INTM”);IVPD=0x01;IVPH=0x01;IERO=0x10;DBIERO=0x10;IFRO=0xffff;asm(“BCLR INTM”);}void InitForMotorB(void){ioport unsigned int *GPTCTL1-0;ioport unsigned int *GPTPRD1-0;ioport unsigned int *GPTGCTL1-0;*GPTCTL1-0=0;*GPTPRD1-0=0x1d8;*GPTGCTL1-0=0x3;}//显示参数到LCDvoid ShowParameters(){int w1,w2,w3;w1=md%1000/100;w2=md%100/10,w3=md%10; LCDPutString(numbers+w1*8,36,111,1,1); LCDPutString(numbers+w2*8,44,111,1,1); LCDPutString(numbers+w3*8,52,111,1,1);if (ek>=0){LCDPutString(numbers+88,36,95,1,1);w3=((int)ek)%100;}else{LCDPutString(numbers+96,36,95,1,1);w3=((int)(-ek))%100;}for (j=0;j<16;j++,k<<=1){if (color==2) mcolor=2;else{mcolor=(pData(1*8+i)&k)(1):(0);if(color==0) mcolor=1-mcolor;}LCDPutPixel(x+1*8+I,y-j,mcolor);}int wwss;void PrintParameters(){wwcc=wc-md;printf(“测速(%3d) 设置(%3d) 误差(%+4d) PID调整量(%+3d) 占空比(%3d%%)\n”,wc,md,wwcc,tz,pwm1);}。
《无刷直流电动机调速控制程序》.INCLUDE "240x.H";--------------------------------------以下定义变量和常数---------------------------------------------------- .DATAKP .SET 015 ;速度调节比例系数KI .SET 004 ;速度调节积分系数.BSS CAPT,1 ;换相控制字.BSS COMP,1 ;比较值.BSS IDC,1 ;线电流.BSS IDC_REF,1 ;电流参考值.BSS SPEED_REF,1 ;速度参考值.BSS SPEED_COUNT,1 ;速度调节循环计数器.BSS STACK,6 ;软堆栈初始地址;--------------------------------------定义主向量------------------------------------------------------------- .SECT "VECTORS"RSVECT B _C_INT0 ;复位INT1 B PHANTOM ;INT1INT2 B PHANTOM ;INT2INT3 B PHANTOM ;INT3INT4 B CAPINT ;捕捉中断INT5 B PHANTOM ;INT5INT6 B ADCINT ;ADC中断…;略;--------------------------------------以下是程序------------------------------------------------------------- .TEXT;--------------------------------------初始化程序-------------------------------------------------------------- _C_INT0SETC CNFCLRC OVMSETC SXM ;符号扩展SETC INTM ;关中断MAR *,AR2 ;速度调节变量区指针LAR AR2,#0300H ;速度调节变量区初始化SPLK #0,*+SPLK #0,*+SPLK #0FFFFH,*+SPLK #029H,*+SPLK #029H,*+SPLK #0,*LAR AR2,#0300HLAR AR1,#STACK ;软堆栈指针LDP #0E0HSPLK #68H, WDCR ;不用看门狗SPLK #0284H,SCSR1 ;10MCLKIN,20MCLKOUTLDP #0E8HSPLK #0FFFFH,T2PR ;最大周期SPLK #00000H,T2CNTSPLK #17C0H,T2CON ;连续增计数,128分频,T1启动SPLK #500,T1PR ;PWM设置,周期50微秒SPLK #0000H,T1CNTSPLK #0FFFH,ACTRA ;PWM1~6全部高电平输出SPLK #01F4H,DBTCONA ;死区1.6微秒SPLK #250,CMPR1 ;占空比为50%SPLK #250,CMPR2SPLK #250,CMPR3SPLK #8200H,COMCONA ;允许比较,T1下溢重载SPLK #0840H,T1CON ;连续增减计数,内部时钟,不分频SPLK #0100H,GPTCONA ;T1周期中断标志启动AD转换SPLK #0B0FCH,CAPCONA ;捕捉设置.使用捕捉1,2,3,双沿触发SPLK #00FFH,CAPFIFOA ;清空捕捉堆栈LDP #0E1HSPLK #0FF80H, MCRA ;引脚设置为PWM和捕捉功能LDP #0LACC #028HSACL IMR ;允许INT4和INT6中断LACC IFR ;清标志SACL IFRLDP #0E8HLACC EV AIFRA ;清标志SACL EV AIFRALACC EV AIFRBSACL EV AIFRBLACC EV AIFRCSACL EV AIFRCSPLK #0,EV AIMRASPLK #0,EV AIMRBSPLK #7,EV AIMRC ;允许捕捉1,2,3中断,其它关闭LDP #0E1H ;AD设置SPLK #0500H,ADCTRL2 ;允许EVA启动AD转换SPLK #0900H,ADCTRL1 ;10分频SPLK #0000H,MAXCONV ;一个转换通道SPLK #0000H,CHSELSEQ1 ;ADCIN00通道CLRC INTM ;开总中断LDP #0 ;变量初始化SPLK #001FH,IDC_REFSPLK #0040H,SPEED_REFSPLK #0500,COMPSPLK #0000H,SPEED_COUNTSPLK #0000H,CAPT;--------------------------------------检测转子初始位置----------------------------------------------------- LDP #0E8HSPLK #8000H,CAPCONA ;关闭捕捉功能SPLK #00FFH,CAPFIFOA ;清空捕捉堆栈LDP #00E1HSPLK #0FC00H, MCRA ;CAP1~CAP3设为I/O口SPLK #0000H, PADATDIR ;设为输入LACC PADA TDIR ;读IOPA3~IOPA5AND #038H ;屏蔽其它位LDP #0SACL CAPTLACC CAPT,13 ;相当于右移3位SACH CAPT ;保存并初始化CAPTLDP #0E1HSPLK #0FF80H, MCRA ;恢复捕捉功能LDP #0E8HSPLK #0B0FCH,CAPCONA ;允许捕捉SPLK #00FFH,CAPFIFOA ;清空捕捉堆栈;--------------------------------------以下可添加应用程序------------------------------------------------------ LOOP NOPB LOOP ;循环;--------------------------------------假中断处理------------------------------------------------------------------ PHANTOMCLRC INTMRET;--------------------------------------A/D中断处理子程序-------------------------------------------------------- ADCINTMAR *,AR1 ;保存现场MAR *+SST #1, *+ ;保存ST1SST #0, * ;保存ST0LDP #0LACC SPEED_COUNT ;检查是否应该速度调节SUB #1250BCND NO_SPEED_REG,NEQ ;不该调节,跳转CALL SPEED_REG ;否则调用速度调节子程序NO_SPEED_REGLACC SPEED_COUNTADD #1SACL SPEED_COUNT ;计数器加1LDP #0E0HLACC PIVR ;清ADC中断标志LDP #0E8HLACC EV AIFRA ;清T1周期中断标志SACL EV AIFRALDP #0E1HLACC ADCTRL2OR #0202HSACL ADCTRL2;--------------------------------------电流调节--------------------------------------------------------------------- CLRC SXMLACC RESULT0,10 ;读ADC转换结果LDP #0SUB IDC_REF,16 ;减电流参考值,计算电流偏差SETC SXMADD COMP,16 ;电流比例调节,K=1SACH COMPLACC COMPBCND SUP_LIM,GT ;检查COMP是否小于0SPLK #0,COMP ;小于0则令COMP=0B COMP_OKSUP_LIMSUB #0500BCDN COMP_OK,LT ;检查是否超过最大值500SPLK #0500,COMP ;超过则COMP=500;--------------------------------------改变占空比------------------------------------------------------------- COMP_OKCALL SEQUENCE ;改变占空比MAR *, AR1 ;恢复现场LST #0, *- ;恢复ST0LST #1, *- ;恢复ST1CLRC INTMRET;--------------------------------------捕捉中断处理子程序------------------------------------------------- CAPINTMAR *,AR1 ;保存现场MAR *+SST #1, *+ ;保存ST1SST #0, * ;保存ST0LDP #0E0HLACC PIVR ;清中断标志LDP #0E8HSPLK #0FH,EV AIFRC;--------------------------------------速度参数计算----------------------------------------------------------------- MAR *,AR2LACL T2CNT ;读T2的值SACL *+ ;保存为第K次捕捉时间SUB *+ ;减去第K-1次捕捉时间SACL *- ;保存时间增量ADD *SACL *- ;更新第K-1次捕捉时间;--------------------------------------获取换相控制字-------------------------------------------------------- LDP #0E8HSPLK #8000H,CAPCONA ;关闭捕捉功能SPLK #00FFH,CAPFIFOA ;清空捕捉堆栈LDP #00E1HSPLK #0FC00H, MCRA ;CAP1~CAP3设为I/O口SPLK #0000H, PADATDIR ;设为输入LACC PADA TDIR ;读IOPA3~IOPA5AND #038H ;屏蔽其它位LDP #0SACL CAPTLACC CAPT,13 ;相当于右移3位SACH CAPT ;保存并初始化CAPT;--------------------------------------换相------------------------------------------------------------------------ CALL SEQUENCE ;换相LDP #0E1HSPLK #0FF80H, MCRA ;恢复捕捉功能LDP #0E8HSPLK #0B0FCH,CAPCONA ;允许捕捉SPLK #00FFH,CAPFIFOA ;清空捕捉堆栈MAR *, AR1 ;恢复现场LST #0, *- ;恢复ST0LST #1, *- ;恢复ST1CLRC INTMRET;--------------------------------------换相或修改占空比子程序----------------------------------------------- SEQUENCELDP #0LACC CAPTSUB #1SFL ;乘2ADD #CAPT_DETER ;加BACCCAPT_DETERB FALLING3 ;H3下降沿B FALLING1 ;H1下降沿B RISING2 ;H2上升沿B FALLING2 ;H2下降沿B RISING1 ;H1上升沿RISING3 ;H3上升沿LACC COMP ;比较值,控制占空比LDP #0E8HSPLK #0DF7H,ACTRA ;PWM2,5低有效,其它输出高电平SACL CMPR3 ;修改PWM2,5的占空比SACL CMPR1SPLK #0,CMPR2B ENDDFALLING3LACC COMPLDP #0E8HSPLK #07FDH,ACTRA ;PWM1,6低有效,其它输出高电平SACL CMPR1 ;修改PWM1,6的占空比SACL CMPR3SPLK #0,CMPR2B ENDDRISING2LACC COMPLDP #0E8HSPLK #07DFH,ACTRA ;PWM3,6低有效,其它输出高电平SACL CMPR2 ;修改PWM3,6的占空比SACL CMPR3SPLK #0,CMPR1B ENDDFALLING2LACC COMPLDP #0E8HSPLK #0D7FH,ACTRA ;PWM4,5低有效,其它输出高电平SACL CMPR3 ;修改PWM4,5的占空比SACL CMPR2B ENDDRISING1LACC COMPLDP #0E8HSPLK #0F7DH,ACTRA ;PWM1,4低有效,其它输出高电平SACL CMPR1 ;修改PWM1,4的占空比SACL CMPR2SPLK #0,CMPR3B ENDDFALLING1LACC COMPLDP #0E8HSPLK #0FD7H,ACTRA ;PWM2,3低有效,其它输出高电平SACL CMPR2 ;修改PWM2,3的占空比SACL CMPR1SPLK #0,CMPR3ENDDRET;--------------------------------------速度调节子程序---------------------------------------------------------- SPEED_REGMAR *,AR2LAR AR2,#0302H ;捕捉时间增量LDP #0SPLK #0,SPEED_COUNT ;计数器清0CLRC SXMLACC #0OR #0FFFFH ;ACC=FFFFH无符号数RPT #15 ;除以捕捉时间增量SUBC *AND #0FFFFH ;屏蔽高16位SUB SPEED_REF ;计算速度偏差NEG ;求补SETC SXMLAR AR2,#0303HSACL *+ ;保存第K次偏差SUB *+ ;减第K-1次偏差SACL * ;保存两次偏差之差LT *MPY #KP ;偏差之差乘KPLAR AR2,#0303HLTP * ;积存ACCMPY #KI ;第K次偏差乘KI*TLTD * ;积累加ADD IDC_REF,4 ;累加SFR ;右移4位(由于乘T)SFRSFRSFRSACL IDC_REF ;保存RET .END。
#include <pic168xa.h> //2008.4.24--14点00分#include <math.h>#include <stdlib.h>int charge_delay,jm,lkk,trial,run_num,protect_num;char m,n,k,s,L,tri;char hall_num; //循环次数char hall_number; //1+3+2+10+8+9=33(一个循环和),hallless_protect()int pwm_hi; // pwm占空比上限int pwm_cycle; // pwm周期int pwm_lo; // pwm占空比下限,由A/D结果确定int pwm_real; // pwm占空比实际int ad_result; // A/D转换结果bit ghy,run_flag; //运行标志---0,未运行,停止bit flag_autohand; //开始为-----自动void delay(delay_num)int delay_num;{int j;for (j=delay_num;j>1;j--){asm("nop");}}union adres{int y1;unsigned char adre[2];}adresult;void para_chushihua(){protect_num=0;trial=0b10110000;tri=0x00;lkk=10;hall_num=0x00;hall_number=0x00;run_flag=0; //运行标志---0,未运行,停止flag_autohand=1; //开始为-----自动pwm_cycle= 240; // pwm周期// pwm_hi=pwm_cycle-5; // pwm占空比上限pwm_hi=pwm_cycle-1; // pwm占空比上限pwm_real=pwm_cycle; // 实际pwm占空比为pwm周期上限pwm_lo=0x0A; //设定下限+++++++++++++++++++++++++++++++++++++++ ++++++++}void nointerupt_chushihua(){INTCON=0X00; //禁止中断}void Io_chushihua(){// ADCON1=0x8e; //RA0/AN0--VOLTAGE 电压采样,右对齐1ADCON1=0x86; //设定RA0--RA6设定为I/O口;TRISA =0x09; //RA0---PROTECT保护(电流保护和过温保护)--输出,0--不保护,1--保护;//RA1----PSW1,继电器,输出,0,电源接通//RA2----指示灯,输出0--->>//RA3----按键,加,输入 1//RA4----指示灯,输出0--->>//RA5----RSW1,继电器,输出0,软启充电PORTA=PORTA&0x09; //RA1=0,----输出低电平,PSW1,继电器断//RA2=0,----输出低电平,指示灯灭//RA4=0,----输出低电平,指示灯灭//RA5=0,----输出低电平,RSW1,继电器断RBPU=0; //RB端口内部弱上拉电路禁止TRISB =0xfe; //RB7=1, 空----输入//RB6=1----HA,输入//RB5=1----HB,输入//RB4=1----HC,输入//RB3=1----停,输入,按钮//RB2=1----启,输入,按钮//RB1=1----自/手选择,输入,开关//RB0=0----ST/STOP,输出,控制GAL PORTB=PORTB&0xfe; //RB0=0,----输出低电平,禁止GAL输出TRISC =0x02; //RC7---A1+,PWMA1+,输出0//RC6---A1, 输出0//RC5---B1+,输出0//RC4---B1,输出0//RC3---C1+,输出0//RC2---CCP1(PWM),输出,死区0//RC1----减,输入,按钮 1//RC0---C1,输出0 PORTC=0x06;}void protect(){ //过流和过温保护GIE=0; //关全局中断pwm_real=pwm_hi; //PWM_real----PWM实时值CCPR1L=pwm_real; //设置PWM输出为最大CCPR1H=0x00; //CCP1CON=0x0c; //CCP1选择为PWM工作方式PR2=pwm_cycle; //设置PWM的周期TRISC=TRISC&0xfb; //设置RC2---PWM输出T2CON=0x00; //分频系数=0x00TMR2ON=1; //启用TMR2PORTC=0x00; //PORTB=PORTB&0xfe; //RB0=0,----输出低电平,禁止GAL输出while(1){PORTA^=0b00010100;delay(15000); //延时}}void protect_run(){ //过流和过温保护GIE=0; //关全局中断pwm_real=pwm_hi; //PWM_real----PWM实时值CCPR1L=pwm_real; //设置PWM输出为最大CCPR1H=0x00; //CCP1CON=0x0c; //CCP1选择为PWM工作方式PR2=pwm_cycle; //设置PWM的周期TRISC=TRISC&0xfb; //设置RC2---PWM输出T2CON=0x00; //分频系数=0x00TMR2ON=1; //启用TMR2PORTC=0x00; //PORTB=PORTB&0xfe; //RB0=0,----输出低电平,禁止GAL输出while(1){// PORTA^=0b00010000; //RA4闪动PORTA^=0b00000100; //RA2闪动delay(15000); //延时}}void PWM_chushihua(){// CCPR1L=0xa0;// CCPR1H=0x00;run_num=0;pwm_real=pwm_hi; //PWM_real----PWM实时值CCPR1L=pwm_real; //设置PWM输出为最大CCPR1H=0x00; //CCP1CON=0x0c; //CCP1选择为PWM工作方式PR2=pwm_cycle; //设置PWM的周期TRISC=TRISC&0xfb; //设置RC2---PWM输出T2CON=0x00; //分频系数=0x00TMR2ON=1; //启用TMR2}void open_loopf() //开环运行50次,启动{k=0b00011000; //5 //HA,HB,HC,s=PORTC&0b00000110; //1 0 1, B-C+PORTC=k|s; //delay(8000); //延时k=0b10010000; //4 //HA,HB,HC,s=PORTC&0b00000110; //1 0 0, A+B-PORTC=k|s; //delay(8000); //延时k=0b10000001; //6 //HA,HB,HC,s=PORTC&0b00000110; //1 1 0, C-A+PORTC=k|s; //delay(8000); //延时k=0b00100001; //2 //HA,HB,HC,s=PORTC&0b00000110; //0 1 0, B+C-PORTC=k|s; //delay(8000); //延时k=0b01100000; //3 //HA,HB,HC,s=PORTC&0b00000110; //0 1 1, A-B+PORTC=k|s; //delay(8000); //延时k=0b01001000; //1 //HA,HB,HC,s=PORTC&0b00000110; //0 0 1, C+A-PORTC=k|s; //delay(8000); //延时}void interrupt RB4_int(){char th;run_num++;if(run_num>10){run_num=10;}m=PORTB;//RB7-HA,RB5-HB,RB4-HCm&=0xB0; //1 0 1 1 m^=0x90;//A=/A,B=B,C=/C //1 1 n=m>>4; //switch(n){ //HA,HB,HC,// case 1: k=0b01001000;break; //0 0 1, C+A-// case 3: k=0b01100000;break; //0 1 1, A-B+// case 2: k=0b00100001;break; //0 1 0, B+C-// case 10:k=0b10000001;break; //1 1 0, C-A+// case 8: k=0b10010000;break; //1 0 0, A+B-// case 9: k=0b00011000;break; //1 0 1, B-C+// default:k=0b00000000; //其它(000,111),0x00,输出为无效case 1: k=0b00011000;break; //1 0 1, B-C+case 3: k=0b01001000;break; //0 0 1, C+A-case 2: k=0b01100000;break; //0 1 1, A-B+case 10:k=0b00100001;break; //0 1 0, B+C-case 8: k=0b10000001;break; //1 1 0, C-A+case 9: k=0b10010000;break; //1 0 0, A+B-default:k=0b00000000; //其它(000,111),0x00,输出为无效}s=PORTC&0b00000110; //取RC1,RC2状态PORTC=k|s; //输出PORTCif (RB7==0) {trial&=0b00110000;} //RB7=0if (RB5==0) {trial&=0b10010000;} //RB5=0if (RB4==0) {trial&=0b10100000;} //RB4=0if (lkk>1) {lkk--;} //每20次测试一次// tri=n;// if ((tri&=0b00001000)==0) {trial&=0b00110000;} //RB7=0// tri=n;// if ((tri&=0b00000010)==0) {trial&=0b10010000;} //RB5=0// tri=n;// if ((tri&=0b00000001)==0) {trial&=0b10100000;} //RB4=0// if (lkk>2) {lkk--;} //每20次测试一次else{while(trial!=0b00000000){GIE=0; //关全局中断pwm_real=pwm_hi; //PWM_real----PWM 实时值CCPR1L=pwm_real; //设置PWM输出为最大CCPR1H=0x00; //CCP1CON=0x0c; //CCP1选择为PWM工作方式PR2=pwm_cycle; //设置PWM的周期TRISC=TRISC&0xfb; //设置RC2---PWM输出T2CON=0x00; //分频系数=0x00TMR2ON=1; //启用TMR2PORTC=0x00; //PORTB=PORTB&0xfe; //RB0=0,----输出低电平,禁止GAL输出while(1){PORTA^=0b00010000; //RA4闪动for (jm=15000;jm>1;jm--){asm("nop");}}}trial=0b10110000;lkk=10;}RBIF=0;}void max_min_compare(){if (pwm_real>pwm_hi) pwm_real=pwm_hi;if (pwm_real<pwm_lo) pwm_real=pwm_lo;}main(void){para_chushihua(); //参数初始化nointerupt_chushihua(); //禁止中断初始化Io_chushihua(); //I/O初始化PWM_chushihua(); //PWM初始化RA1=0; //RA1-PSW1发送低电平,接通电源RA5=0; //RA5-RSW1发送低电平,主电路充电延时RA2=0; //RA2,指示灯灭RA4=0; //RA4,指示灯灭delay(100); //主电路充电延时RB0=0; //ST/(-STOP)发送低电平,禁止GAL输出delay(100);RA1=1; //RA1-PSW1发送高电平,接通电源for(charge_delay=0;charge_delay<50;charge_delay++){delay(15000);}RA5=1; //RA5-RSW1发送高电平,主电路充电延时delay(100); //主电路充电延时PP: asm(" nop"); //RBIF=0; //禁止RB4-7中断,清RBIF 标志设定RBIE=0; //禁止RB4-7中断,RBIE设定GIE=0; //关全局中断RA2=0; //RA2,指示灯灭RA4=0; //RA4,指示灯灭run_flag=0; //运行标志---由RB2按钮设置while(run_flag==0) //----------主程序-------------//{ //RB2启动键,低电平有效if (RB2==0) run_flag=1; //运行标志---由RB2按钮设置delay(100); //延时} //while(run_flag==1) //运行,则执行......{int ope; //设定开环运行次数为12次int openloopn; //RB0=1; //ST/(-STOP)发送高电平,开放GAL输出delay(100); //延时RA4=1;// pwm_real=180;pwm_real=230;delay(500); //延时// ope=10; //设定开环运行次数为20次ope=3; //设定开环运行次数为20次for (openloopn=0;openloopn<=ope;openloopn++){ //0 00000000000000000CCPR1L=pwm_real; //设置开环下PWM输出值----130open_loopf(); //开环运行20次,启动} //----------------------- //000000000000000000delay(6000); //延时RBIF=0; //RB4-7中断,RBIF标志设定RBIE=1; //RB4-7中断,RBIE设定GIE=1; //开全局中断RA2=1; //----------------------- pwm_real=pwm_hi; //-----------------------ghl: asm(" nop"); //if ((pwm_real<110)&&(run_num<10)) //如果pwm_real<140,但是run_num<10,表明未动,则{ //protect_run();protect_run();}while(RA0==1) //RA0=1,过流和过温保护{ //delay(150); //调用延时程序protect_num++; //if (protect_num>30)//如果30次保护,则认为是真正保护(过温和过流保护软件滤波){protect();} //过流和过温保护} //protect_num=0; //if(RB1==1) flag_autohand=1; //自/手标志设定,标志设定else flag_autohand=0; //RB1=1---AUTO;自动//RB1=0---HAND;手动//----------------------- if (flag_autohand==1){ //11 111111111111111111if (pwm_real>pwm_lo) pwm_real-=1; //自动else pwm_real=pwm_lo;}//11111111111111111111else{if(RA3==0) //加(低有效), 则{if (pwm_real<pwm_hi) pwm_real+=1;else pwm_real=pwm_hi;}if(RC1==0) //减(低有效),则{if (pwm_real>pwm_lo) pwm_real-=1;else pwm_real=pwm_lo;}}max_min_compare();CCPR1L=pwm_real; //设置PWM输出delay(4500); //调用延时子程序while(RA0==1) //RA0------过流和过温保护输入,高电平保护{ //protect(); //过流和过温保护} //while(RB3==0){ //RB3停机键,低电平有效run_flag=0; //运行标志---由RB3按钮设置}if (run_flag==0) //停机,则跳转至......{for(;pwm_real<pwm_hi;pwm_real++){delay(2000); //至上限否?CCPR1L=pwm_real; //设置PWM输出为最大}RB0=0; //ST/(-STOP)发送低电平,禁止GAL输出para_chushihua(); //参数初始化nointerupt_chushihua(); //禁止中断初始化PWM_chushihua(); //PWM初始化run_num=0;goto PP;}else{// run_num=0;goto ghl;}}// goto PP;}。