//Electric vehicle double closed loop program, using double closed loop mode to control the motor to get the best zh speed performance, and can
// Limit the maximum current of the motor. This application uses two CCP components, of which CCP1 is used for PWM output to control
/ / Motor voltage; CCP2 is used to trigger AD, timer TMR2, TMR1, INT interrupt, RB port level change interrupt,
// watchdog and 6 general purpose I/O ports
#defineAND0xe0//Status acquisition 5,6,7 bit
#defineCURA0X0a//The sum of current loop ratio and integral coefficient
#defineCURB0X09//current loop proportional coefficient
#defineTHL0X6400//current loop maximum output
#defineFULLDUTY0X0FF//High time when the duty ratio is 1.
#defineSPEA0X1d//The sum of the speed loop ratio and the integral coefficient
#defineSPEB0X1c//Speed ​​loop proportional coefficient
#defineGCURHILO0X0330//Maximum output of the speed loop
#defineGCURH0X33//Maximum given current
#defineGSPEH0X67//Maximum speed reference
#defineTSON0X38//The handle opening voltage is 1.1V, and TSON*2 is the handle opening voltage after braking.
//2.2V
#defineVOLON0X4c//Low voltage protection re-opening voltage 3.0V or 33V
#defineVOLOFF0X49//Low voltage protection shutdown voltage 2.86V or 31.5V
volatileunsignedcharDELAYH,DELAYL,oldstate,speed,
Speedcount,tsh,count_ts,count_vol,gcur,currenth,
Voltage; / / register definition
Staticbitsp1,spe,ts,volflag,spepid,lowpower,
Off,shutdown,curpid;//flag definition
Staticvolatileunsignedcharnew[10]={0xaf,0xbe,0xff,0x7e,0xcf,
0xff, 0xd7, 0x77, 0xff, 0xff}; / / status register table
//------------ PIC16F877 initialization subroutine ------------
voidINIT877()
{
PORTC=0X0FF; / / turn off all MOSFET
TRISC=0X02; / / set C port output
PIE1=0X00; / / interrupt register initialization, turn off all interrupts
TRISA=0XCF; / / set RA4, RA5 output
TRISB=0XEF; / / RB port high three-bit input, collecting motor three-phase Hall signal
PORTC=new[(PORTB&AND)>>5];//Collect the first Hall signal, and output the corresponding signal, turn on
//Two MOS tubes
T2CON=0X01; // TMR24 crossover
CCPR1L=0X0FF; / / initial PWM output full height
CCP1CON=0X0FF; //CCP1 is set to PWM mode
CCP2CON=0X0B; //CCP2 is set to a special mode to trigger AD
ADCON0 = 0X81; / / AD clock is divided by 32, and AD is enabled, select AN0 channel acquisition hand
/ handle voltage
TMR2 = 0X00; / / TMR2 register initialization
TMR1H=0X00; // TMR1 register initialization
TMR1L=0X00;
T1CON=0X00; / / TMR1 is divided by 1
CCPR2H=0X08;
CCPR2L=0X00; / / current sampling period is set to TAD = 512μs
PR2=0XC7; / / PWM frequency is set to 5kHz
ADCON1=0X02; / / AD results left shift
OPTION=0XFB; / / INT rising edge trigger
TMR2ON=1; / / PWM starts working
INTCON=0XD8; / / interrupt setting GIE = ​​1, PEIE = 1, RBIE = 1
ADIE=1; // AD interrupt enable
Speedcount=0x00; / / speed count register
Speed=0x7f;//speed holding register
Spe=1;//low speed flag
Sp1=1;//low speed flag
Oldstate=0x0ff; / / initial state settings, different from other states
Count_ts=0x08; / ​​/ current sampling 8 times, collect 1 handle
Count_vol=0x00; / / sample 256 handles, collect 1 battery voltage
Ts=1; / / can collect the flag value of the handle value
ADGO=1; / / AD sampling enable
TMR1ON=1;//CCP2 parts start working
}
//------------ Delay subroutine ---------------
#pragmainterrupt_level1
voidDELAY1(x)
Charx;
{
DELAYH=x;//delay parameter setting
#asm
DELAY2MOVLW0X06
MOVWF_DELAYL
DELAY1DECFSZ_DELAYL
GOTODELAY1
DECFSZ_DELAYH
GOTODELAY2
#endasm
}
//----------- Status collection subroutine ----------------------
Voidsample()
{
Charstate1, state2, state3, x;
Do{
x=1;
State1=(PORTB&AND);//Hall signal acquisition
DELAY1(x);
State2=(PORTB&AND);
}while(state1-state2);//Continue to collect state when the three sampling results are different
If(state1-oldstate!=0)//See if the sampling result is the same as the last time, different
//execute
{oldstate=state1;//Set this state to the old state
State1=(oldstate>>5);
PORTC=new[state1];//C port output corresponding signal triggers two MOS tubes
If(sp1==1){spe=1;sp1=0;}
Else{//If the speed is very low, spe is set to 1
Spe=0; sp1=0;
Speedcount<<=1;
State3=(TMR1H>>2);//other, spe=0, count speed
Speed=speedcount+state3;//speed register adds 1 for every 256μs
}
Speedcount=0;
}
}
//-----------------AD sampling subroutine --------------------
voidAD()
{
Charx;
ADIF=0; / / clear AD interrupt flag
If(ts==1){//If the handle is sampled, the sample handle value
CHS0=1; / / select the current sampling channel
Count_vol=count_vol+1;//Battery sample count register
Spepid=1; / / set the speed closed loop operation flag
Ts=0;tsh=ADRESH;//Save the handle value
If(count_vol==0){//If the battery sampling time is up, select the AN2 channel and collect the battery voltage.
CHS0 = 0; CHS1 = 1; volflag = 1; x = 1; DELAY1 (x); ADGO = 1;
}
}
Elseif(volflag==1){//The battery is sampled and processed accordingly.
CHS1=0; CHS0=1; volflag=0; voltage=ADRESH; lowpower=1;
}
Else{//other, the interrupt is the sampling current interrupt
Speedcount=speedcount+1;//speedcount register plus 1, as the measurement speed
If(speedcount>0x3d)sp1=1;//If the speed is lower than 1000000μs/(512μs*3eh*3)
/ / is considered a low speed state
Currenth=ADRESH;
Curpid=1;
Count_ts=count_ts-1;
If(count_ts==0){//If the handle time is up, it will be transferred to the handle sampling channel.
CHS0 = 0; count_ts = 0x08; ts = 1; x = 1; DELAY1 (x); ADGO = 1;
}
}
}
//-------------Brake processing subroutine ------------------
VoidBREAKON()
{
Charx;
Off=0; / / off clear, if it is interference, it is not reset
Shutdown=0;
If(RB0==1){//If the brake signal is true, stop the output voltage
ADIE=0; / / off AD interrupt
INTE=0;//Off brake interrupt
CCPR1L=FULLDUTY;//output voltage 0
TMR1ON=0; / / off CCP2, no longer trigger AD
For(;ADGO==1;)continue;//If sampling is taking place, wait for sampling to end
ADIF=0; // ADIF bit is cleared
CHS0=0;//Select channel 0 sampling handle
CHS1=0;
x=1;
DELAY1(x);
Do{
ADGO=1;
For(;ADIF==0;)continue;
ADIF=0;
CCPR1L=FULLDUTY;
Asm("CLRWDT");
Tsh=(ADRESH>>1);
}while(tsh>TSON||RB0==1);//When the handle value is greater than 2.2V or the brake continues, execute
/ / Upper statement
Off=1; / / reset flag
}
}
//---------Underprotected subroutine -------------------
voidPOWER()
{
Charx;
Lowpower=0;
Voltage>>=1;//The voltage value is changed to 7 bits to facilitate single-byte operation
If(voltage
INTE=0;
TMR1ON=0;
CCPR1L=FULLDUTY;
For(;ADGO==1;)continue;
ADIF=0;
CHS0=0; CHS1=1;
x=1;
DELAY1(x);
Do{ADGO=1;
For(;ADIF==0;)continue;
ADIF=0;
Voltage=(ADRESH>>1);
CCPR1L=FULLDUTY;
Asm("CLRWDT");
}while(voltage
}
}
//------------ Current loop operation subroutine -----------------
voidCURPI()
{staticintcurep=0x00, curek=0x00, curuk=0x00;
Uniondata{intpwm;
Chara[2];}b;//Define current loop arithmetic register
Curpid=0;//clear current operation flag
Curep=curek*CURB;//calculate the product of the last deviation and the scale factor
If(currenth<2)currenth=2;//If the sampling current is zero, then a small current is considered to facilitate
/ / make the speed drop
Currenth>>=1;
Curek=gcur-currenth;//calculate this deviation
Curuk=curuk+curek*CURA-curep;//This output result is obtained by closed-loop PI operation.
/ / Face the result of processing
If(curuk<0x00){//If the output is less than zero, the output is considered to be zero
Curuk=0; CCPR1L=FULLDUTY; CCP1X=0; CCP1Y=0;
}
Elseif(curuk-THL>=0){//If the output is greater than the limit value, the maximum voltage is output.
Curuk=THL; CCPR1L=0; CCP1X=0; CCP1Y=0;
}
Else{//other, proportionally output the corresponding high time to the CCPR1 register
B.pwm=THL-curuk;
B.pwm<<=1;
CCPR1L=ba[1];//CCPR1L=(b.pwm>>8)&0x0ff; will be the high nibble of the PWM register
If(b.pwm&0x80!=0)CCP1X=1;
elseCCP1X=0;
If(b.pwm&0x40!=0)CCP1Y=1;
elseCCP1Y=0;
}
}
//---------------Speed ​​loop operation subroutine -----------------------
voidSPEPI()
{staticintspeep=0x00,speek=0x00,speuk=0x00;
Inttsh1, speed1; / / speed register definition
Spepid=0;//clear speed calculation flag
If(spe==1)speed1=0x00;//If the speed is too low, the speed is considered to be zero
Elsespeed1=0x7f-speed;//other calculate the actual speed
If(speed1<0)speed1=0;
Speep=speek*SPEB;
Tsh1=tsh-0x38;//Get the handle value for calculation
Speek=tsh1-speed1;
If(tsh1<0){speuk=0;gcur=0;}//When the handle value is lower than 1.1V, the handle is considered to be zero
Else{//other, calculate the corresponding speed loop output
If(tsh1>=GSPEH)//limit maximum speed
Tsh1=GSPEH;
Speuk=speuk+speek*SPEA-speep;//calculated speed loop output
If(speuk<=0X00){speuk=0x00;gcur=0x00;}//speed loop output processing
Elseif (speuk>GCURHILO) { / / speed loop output limit, that is, limit the maximum current of about 12A
Speuk=GCURHILO;gcur=GCURH;}
Else{//output in speed state
Gcur=(speuk>>4)&0x0ff;
}
}
}
//----------- main program -------------------------
Main()
{
For(;;){
INIT877 (); / / After the microcontroller reset, initialize it first
Off=0;//clear reset flag
For(;off==0;){//The reset flag is zero, then execute the following program, otherwise reset
If(curpid==1)CURPI();//current PI operation
Elseif(spepid==1)SPEPI();//Speed ​​PI operation
Elseif(lowpower==1)POWER();
Elseif(shutdown==1)BREAKON();
Asm("CLRWDT");
}
}
}
//---------Interrupt service subroutine ---------------------
#pragmainterrupt_level1
voidinterruptINTS(void)
{
If(RBIF==1){RBIF=0;sample();}
Elseif (ADIF==1) AD();
Elseif(INTF==1){shutdown=1;INTF=0;}//Brake interrupted, set the brake sign
}
Fiber Optic Patch Panel,Fiber Patch Panel,Fiber Distribution Panel,Optical Patch Panel
Cixi Dani Plastic Products Co.,Ltd , https://www.dani-fiber-optic.com