6121 views|2 replies

1379

Posts

0

Resources
The OP
 

Programming the electric bicycle drive system controlled by a single-chip microcomputer using C language [Copy link]

#include <pic.h>

// Electric vehicle dual closed loop program, using dual closed loop method 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, CCP1 is used for PWM output to control

// Control motor voltage; CCP2 is used to trigger AD , timer TMR2 , TMR1 , INT interrupt, RB port level change interrupt,

// Watchdog and 6 general I/O ports

#define AND 0xe0 // Status collection 5 , 6 , 7 bits

#define CURA 0X0a // Sum of current loop proportional and integral coefficients

#define CURB 0X09 // Current loop proportional coefficient

#define THL 0X6400 // current loop maximum output

#define FULLDUTY 0X0FF // High level time when duty cycle is 1

#define SPEA 0X1d // Sum of the speed loop proportional and integral coefficients

#define SPEB 0X1c // Speed loop proportional coefficient

#define GCURHILO 0X0330 // Maximum output of speed loop

#define GCURH 0X33 // Maximum given current

#define GSPEH 0X67 // Maximum speed setting

#define TSON 0X38 // handle opening voltage 1.1 V , TSON*2 is the handle opening voltage after braking, that is

//2.2 V

#define VOLON 0X4c // Low voltage protection reset voltage 3.0 V or 33 V

#define VOLOFF 0X49 // Low voltage protection shutdown voltage 2.86 V or 31.5 V

volatile unsigned char DELAYH,DELAYL,oldstate,speed,

speedcount,tsh,count_ts,count_vol,gcur,currenth,

voltage; // register definition

static bit sp1,spe,ts,volflag,spepid,lowpower,

off,shutdown,curpid; // flag definition

static volatile unsigned char new[10]={0xaf,0xbe,0xff,0x7e,0xcf,

0xff,0xd7,0x77,0xff,0xff}; // Status register table

//------------PIC16F877 Initialization subroutine ------------

void INIT877()

{

PORTC=0X0FF; // Turn off all MOSFETs

TRISC=0X02; // Set port C output

PIE1=0X00; // Initialize interrupt register and turn off all interrupts

TRISA=0XCF; // Set RA4, RA5 output

TRISB=0XEF; //RB port high three-bit input, collect the Hall signal of the three-phase motor

PORTC=new[(PORTB&AND)>>5]; // Collect the first Hall signal and output the corresponding signal to turn on

// Two MOS tubes

T2CON=0X01; //TMR2 4- division

CCPR1L=0X0FF; // Initially PWM output is full high

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

// 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; // The current sampling period is set to TAD = 512 μs

PR2=0XC7; //PWM frequency is set to 5 kHz

ADCON1=0X02; //AD result shift left

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 setting, different from other states

count_ts=0x08; // Current sampling 8 times , handle acquisition 1 time

count_vol=0x00; // sample the handle 256 times and collect the battery voltage once

ts=1; // The flag that can collect the handle value

ADGO=1; //AD sampling enable

TMR1ON=1; //CCP2 component starts working

}

//------------ Delay subroutine ---------------

#pragma interrupt_level 1

void DELAY1(x)

char x;

{

DELAYH=x; // delay parameter setting

#asm

DELAY2 MOVLW 0X06

MOVWF _DELAYL

DELAY1 DECFSZ _DELAYL

GOTO DELAY1

DECFSZ _DELAYH

GOTO DELAY2

#endasm

}

This post is from MCU
 

1379

Posts

0

Resources
2
 
//-----------State acquisition subroutine---------------------- void sample() { char state1,state2,state3,x; do { x=1; state1=(PORTB&AND); //Hall signal acquisition DELAY1(x); state2=(PORTB&AND); }while(state1-state2); //When the three sampling results are different, continue to collect the state if(state1-oldstate!=0) //See if the sampling result is the same as the last time, if not, execute {oldstate=state1; //Set this state to the old state state1=(oldstate>>5); PORTC=new[state1]; //Port C outputs the corresponding signal to trigger the two MOS tubes if(sp1==1){spe=1;sp1=0;} else { //If the speed is very low, set spe to 1 spe=0;sp1=0; speedcount<<=1; state3=(TMR1H>>2); //Otherwise, spe=0, count the speed speed=speedcount+state3; //speed register increases by 1 every 256 μs } speedcount=0; } } //-----------------AD sampling subroutine----------------------- void AD() { char x; ADIF=0; //clear AD interrupt flag if(ts==1){ //if it is handle sampling, then sample handle value CHS0=1; //select current sampling channel count_vol=count_vol+1; //battery sampling count register spepid=1; //set speed closed loop operation flag ts=0;tsh=ADRESH; //store handle value if(count_vol==0) { //if battery sampling time is up, select AN2 channel to collect battery voltage CHS0=0;CHS1=1;volflag=1;x=1;DELAY1(x);ADGO=1; } } else if(volflag==1) { //battery sampling is completed, perform corresponding processing CHS1=0;CHS0=1;volflag=0;voltage=ADRESH;lowpower=1; } else { //Otherwise, the interrupt is a sampling current interrupt speedcount=speedcount+1; //speedcount register plus 1, used as the speed measurement if(speedcount>0x3d) sp1=1; //If the speed is lower than 1 000 000 μs/(512 μs*3eh*3) //, it is considered to be in a low speed state currenth=ADRESH; curpid=1; count_ts=count_ts-1; if(count_ts==0) { //If the handle time is up, then switch to the handle sampling channel CHS0=0;count_ts=0x08;ts=1;x=1;DELAY1(x);ADGO=1; } } } //-------------Brake processing subroutine------------------ void BREAKON() { char x; off=0; //off is cleared, if it is interference, it will not be reset shutdown=0; if(RB0==1) { //If the brake signal is true, then stop outputting voltage ADIE=0; //Turn off AD interrupt INTE=0; //Turn off brake interrupt CCPR1L=FULLDUTY; //Output voltage 0 TMR1ON=0; //Turn off CCP2 and stop triggering AD for(;ADGO==1;) continue;//If sampling is in progress, wait for sampling to end ADIF=0; //ADIF bit cleared CHS0=0; //Select channel 0 for 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.2 V or the brake is still on, execute the following //statements off=1; //Set the reset flag} }
This post is from MCU
 
 

1379

Posts

0

Resources
3
 
//---------Under-power protection subroutine------------------- void POWER() { char x; lowpower=0; voltage>>=1; //Convert the voltage value to 7 bits to facilitate single-byte operation if(voltage>1); CCPR1L=FULLDUTY; asm("CLRWDT"); }while(voltage>=1; curek=gcur-currenth; //Calculate this deviation curuk=curuk+curek*CURA-curep; //According to the closed-loop PI operation method, get the output result this time, and //process the result below if(curuk<0x00) { //If the output is less than zero, it is considered to be zero curuk=0;CCPR1L=FULLDUTY;CCP1X=0;CCP1Y=0; } else if(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 { //Otherwise, output the corresponding high level time to the CCPR1 register in proportion b.pwm=THL-curuk; b.pwm<<=1; CCPR1L=ba[1]; //CCPR1L=(b.pwm>>8)&0x0ff; Set the high nibble of the PWM register if(b.pwm&0x80!=0) CCP1X=1; else CCP1X=0; if(b.pwm&0x40!=0) CCP1Y=1; else CCP1Y=0; } } //---------------Speed loop calculation subroutine----------------------- void SPEPI() { static int speep=0x00,speek=0x00,speuk=0x00; int tsh1,speed1; //Speed register definition spepid=0; //Clear speed calculation flag if(spe==1) speed1=0x00; //If the speed is too low, it is considered to be zero else speed1=0x7f-speed; //Otherwise calculate the actual speed if(speed1<0) speed1=0; speep=speek*SPEB; tsh1=tsh-0x38; //Get the handle value used for calculation speek=tsh1-speed1; if(tsh1<0) {speuk=0;gcur=0;} //When the handle value is lower than 1.1 V, the handle is considered to be zero else { //Otherwise, calculate the corresponding speed loop output if(tsh1>=GSPEH) //Limit the maximum speed tsh1=GSPEH; speuk=speuk+speek*SPEA-speep; //Calculate the speed loop output if(speuk<=0X00) {speuk=0x00;gcur=0x00;}//Speed loop output processing else if(speuk>GCURHILO) { //Speed loop output limit, that is, limit the maximum current to about 12 A speuk=GCURHILO;gcur=GCURH;} else { //Output in speed regulation state gcur=(speuk>>4)&0x0ff; } } } //-----------Main program------------------------- main() { for(;;){ INIT877(); //After the MCU is reset, initialize it first off=0; //Clear reset flag for(;off==0;) { //If the reset flag is zero, execute the following program, otherwise reset if(curpid==1) CURPI(); //Current PI calculation else if(spepid==1) SPEPI(); //Speed PI calculation else if(lowpower==1) POWER(); else if(shutdown==1) BREAKON(); asm("CLRWDT"); } } } //---------Interrupt service subroutine------------------------- #pragma interrupt_level 1 void interrupt INTS(void) { if(RBIF==1) {RBIF=0;sample();} else if(ADIF==1) AD(); else if(INTF==1) {shutdown=1;INTF=0;} //Brake interrupt comes, set brake flag }
This post is from MCU
 
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list