//################################################### Include's #################################################################################################### #include <12F683.h> //################################################### Set Fuse Bits ################################################################################################ //#device ICD=TRUE //Support ICD-Debugger nicht möglich #device adc=10 //ADC mit 10bit #FUSES NOWDT //Kein Watch Dog Timer #FUSES INTRC_IO //Interner RC Osc, kein Takt am Ausgang (no CLKOUT) #FUSES NOPUT //No Power Up Timer (delay 64ms!!!) #FUSES NOBROWNOUT //Kein reset bei Spannungszusammenbruch #FUSES NOPROTECT //Kein Leseschutz des Programmcodes #FUSES NOCPD //Kein Leseschutz des EEPROM #use delay(clock=8000000) //Oszi.-Clock = > :4 = System-Clock=2'000'000 //################################################### Definitionen ################################################################################################# #bit TMR2IF = 0x0C.1 //Definiere Register PIR1 (0x0C) Bit 1 (TMR2IF) #bit T0IF = 0x0B.2 //Definiere Register INTCON(0x0B,0x8B) Bit 2 (T0IF) #define Kpr 24002 #define KiTa 410 #define KdTa 0 //=========================================================== Definition globaler Variablen ======================== signed long w=0; signed long x=0; signed int32 e=0; signed long ealt=0; signed long y=0; signed long Dwert=0; signed int32 Isum=0; signed int32 Pwert=0; signed int32 Iwert=0; //============================================================ Interrupt Service Routines ========================== #INT_RTCC void pi_sample_isr(void) { output_toggle(PIN_A5); //Test um Ta zu messen set_adc_channel( 1 ); //ADC-Kanal 1 auswählen delay_us( 10 ); //Delay für Setup w = read_adc( ); //Einlesen der Spannung am Pin7 (AN0) set_adc_channel( 0 ); //ADC-Kanal 0 auswählen delay_us( 10 ); //Delay für Setup x = read_adc( ); //Einlesen der Spannung am Pin6 (AN1) e=w-x; if(e>964) e=964; if(e<-964) e=-964; //Berechnung P-Anteil Pwert=(Kpr*e)>>13; //Pwert=e*24002/8192 = e*2.93 /* Dwert=e-ealt; //Berechnung D-Anteil //Dwert=Dwert*Kd/Ta Dwert=Dwert*KdTa; if(Dwert>964) Dwert=964; if(Dwert<-964) Dwert=-964; */ if(y<964) //Berechnung I-Anteil Isum=Isum+((KiTa*e)>>13); //Isum=Isum+Ki*Ta*e=Isum+e*410/8192=Isum+e*0.05 if(Isum>964) Isum=964; //Begrenzung if(Isum<-964) Isum=-964; y=Pwert+Isum; //Stellgrösse if(y>964) y=964; //Begrenzung auf 0...964 if(y<1) y=0; // ealt=e; set_pwm1_duty(y); //Ausgabe PWM T0IF=0; //Timer0 Interrupt-Flag löschen } /* #################################################################################################################### ################################################### Hauptprogramm ################################################## */ void main( ) //Start Hauptprogramm > { //################################################# Initialisierung ############################################ //--------------------------------------------- Definition lokaler Variablen -------------------------------- //--------------------------------------------- Setup's ----------------------------------------------------- setup_oscillator ( OSC_8MHZ ); //interner Oszillator auf 8MHz Taktfrequenz set_tris_a( 0xDB ); //GP2,GP5 als Ausgang setup_ccp1( CCP_PWM ); //CCP-Modul auf PWM-Modus setup_timer_2( T2_DIV_BY_1, 255, 1 ); //Setup Timer 2 (Prescaler=1, Periodregister PR2=255, Postscaler=1) //Bei 8Mhz Taktfrequenz: Inkrementierung jeweils nach 0.5us, // Überlauf nach 128us // Interrupt nach 128us. //Mit den Einstellungen von Timer2 ergibt sich eine PWM-Periodendauer // fpwm von (1/fosc)*4*Timer2_mode*(Timer2_period+1), Tcy=4*Tosc // Tpwm=(1/8MHz)*4*1*256=128us, fpwm=7.8125kHz // range=CCPR1L:CCP1CON<5:4> =DCR*4*(PR2+1)=0.94*4*256=963max bei DCR=0.94 // Pulsbreite=(CCPR1L:CCP1CON<5:4>)*Tosc*(TMR2 Prescale Value)=120.375us // Auflösung=log(4*(PR2+1))/log(2)=log(1024)/log(2)=10bits maximale Auflösung setup_adc_ports( sAN0 | sAN1 | VSS_VDD ); //Pins sAN2, sAN3 als analog; VDD als Referenz setup_adc( ADC_CLOCK_DIV_16 ); //Setzt A/D-Wandler Taktrate Tad = 4us set_pwm1_duty( 0 ); //PWM auf 0 setup_timer_0( RTCC_INTERNAL | RTCC_8_BIT | RTCC_DIV_1 ); //Timer0 (internal, 8 bit, Vorteiler 2, OV: 512us) enable_interrupts( GLOBAL ); //Aktivierung Interrupts uC T0IF=0; //Timer 0 Interrupt-Flag löschen enable_interrupts( INT_RTCC ); //Aktivierung Interrupt Timer0 //--------------------------------------------- Hauptschleife --------------------------------------------------- while( 1 ) //Hauptschleife { } //end while(1) } //Ende Hauptprogramm