Meinst Du so was:
Code:/**************************************************** Chip type : ATmega8 Program type : Application Clock frequency : 8,000000 MHz Memory model : Small External SRAM size : 0 Data Stack size : 256 *****************************************************/ #include <mega8.h> #include <delay.h> volatile bit ub_newcalc=0; /* Flag Phasenwinkel neu berechnen */ volatile bit ub_ms100=0; /* Flag, das alle 100ms durch Counter 0 getriggert wird */ volatile unsigned char uc_init=0; /* Counter für die Phasendauerermittlung */ volatile unsigned int ui_phasenwinkel; /* Berechneter Timerwert für den Phasenwinkel */ volatile unsigned int ui_leistungswinkel; /* Wert für den Phasenanschnittwinkel */ const unsigned int ui_defaultwinkel=10000; /* Defaultwert bei 50 Hz= 10000, bei 60 Hz= 8333 */ volatile unsigned int ui_oldtimer=0; /* Zwischenspeicher für den vorherigen Timerwert */ volatile signed long int li_leistung; /* Gewünschte Leistung in 0,1% Schritten */ volatile unsigned char uc_tim0counter=0; /* Überlaufcounter für timer 0*/ #asm .EQU PORTB=0x18 #endasm // External Interrupt 0 service routine interrupt [EXT_INT0] void ext_int0_isr(void) { #asm("wdr"); if(uc_init>0&&uc_init<5) /* Zweiter Schritt der Initialisierung */ { ui_phasenwinkel+=(TCNT1-ui_oldtimer); ui_oldtimer=TCNT1; uc_init++; } else { if(uc_init==0) /* Erster Schritt der Initialisierung */ { ui_phasenwinkel=0; ui_oldtimer=TCNT1; uc_init=1; } else { OCR1A=TCNT1+ui_leistungswinkel; /* normaler Betrieb */ ub_newcalc=1; /* Werte können neu berechnet werden */ if(li_leistung<990) { PORTB.3=1; /* Zündspannung im Nulldurchgang abschalten */ }; }; }; } // Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr(void) { uc_tim0counter++; if(uc_tim0counter>2) { uc_tim0counter=0; ub_ms100=1; /* Flag für "100ms" vorbei setzen */ }; // Place your code here } #pragma savereg- /* Retten der Register abschalten */ // Timer 1 output compare A interrupt service routine interrupt [TIM1_COMPA] void timer1_compa_isr(void) { // Inline Assembler für maximale Geschwindigkeit #asm push r26; Register retten in r26,SREG push r26 lds r26,_uc_init; Initialisierung abgeschlossen ? cpi r26,5 brcs endintcp0 cbi PORTB,3; Zündpuls ausgeben endintcp0: pop r26; Register zurückspielen out SREG,r26 pop r26 #endasm } #pragma savereg+ /* Retten der Register aktivieren */ // Phasenwinkel berechnen void calcphase(void) { uc_init=0; while (uc_init<5); /* Warten auf Periodendauerermittlung */ ui_phasenwinkel=ui_phasenwinkel/((uc_init-1)); // Abfangen ungültiger Phasenwerte if (ui_phasenwinkel>(ui_defaultwinkel+1000)||ui_phasenwinkel<(ui_defaultwinkel-1000)) { ui_phasenwinkel=ui_defaultwinkel; }; ui_phasenwinkel-=200; /* Phasenwinkel auf die sichere Seite ziehen */ } #define ADC_VREF_TYPE 0xC0 // Read the AD conversion result unsigned int read_adc(unsigned char adc_input) { ADMUX=adc_input | (ADC_VREF_TYPE & 0xff); // Delay needed for the stabilization of the ADC input voltage delay_us(10); // Start the AD conversion ADCSRA|=0x40; // Wait for the AD conversion to complete while ((ADCSRA & 0x10)==0); ADCSRA|=0x10; return ADCW; } // Declare your global variables here void main(void) { // Input/Output Ports initialization // Port B initialization // Func7=In Func6=In Func5=In Func4=Out Func3=Out Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=0 State3=1 State2=T State1=T State0=T PORTB=0x08; DDRB=0x18; // Port C initialization // Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTC=0x00; DDRC=0x00; // Port D initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTD=0x00; DDRD=0x00; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 7,813 kHz TCCR0=0x05; TCNT0=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 1000,000 kHz // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: On // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x02; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer 2 Stopped // Mode: Normal top=FFh // OC2 output: Disconnected ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00; // External Interrupt(s) initialization // INT0: On // INT0 Mode: Rising Edge // INT1: Off GICR|=0x40; MCUCR=0x03; GIFR=0x40; // Timer(s)/Counter(s) Interrupt(s) initialization TIFR=0x11; TIMSK=0x11; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00; // ADC initialization // ADC Clock frequency: 125,000 kHz // ADC Voltage Reference: Int., cap. on AREF ADMUX=ADC_VREF_TYPE & 0xff; ADCSRA=0x86; // Ist der Shutdown Eingang freigegeben ? while (PIND.5==0); // 100ms Warten delay_ms(100); // 2 Nulldurchgänge abwarten while(PIND.2==0); while(PIND.2>0); while(PIND.2==0); while(PIND.2>0); GIFR=0x40; /* Anstehende Interupts löschen */ // EEPROM Variablen holen li_leistung=0; // Watchdog Timer initialization // Watchdog Timer Prescaler: OSC/1024k #pragma optsize- WDTCR=0x1E; WDTCR=0x0E; #ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif // Global enable interrupts #asm("sei") //Phasenwinkel ermitteln calcphase(); while (1) { li_leistung=read_adc(0); li_leistung=(li_leistung*1000)/1023; /* Auf 1000 normieren */ if(li_leistung>1000){li_leistung=1000;}; /* Überläufe verhindern */ // Enable Eingang gesperrt Ausgang deaktiviert while(PIND.5==0) { PORTB.3=1; /* Zündausgang gesperrt */ TIMSK&=0b11101111; /* Weitere Zündimpulse durch sperren des Timerinterrupts verhindern */ TIFR|=0b000100000; /* Anstehende Zündimpulse löschen */ calcphase(); /* Phasenwinkel berechnen */ delay_ms(100); li_leistung=0; if(li_leistung>1000) { li_leistung=1000; /* Ungültige Werte abfangen */ PORTB.4=1; /* Full LED an */ }; }; // Routine zur Leistungsregelungseinstellung, wird in INT0 getriggert if(ub_newcalc>0) { if(li_leistung<5) /* Weniger als 0,5% Leistungsanforderung schaltet den Dimmer ab */ { li_leistung=0; TIMSK&=0b11101111; /* Weitere Zündimpulse durch sperren des Timerinterrupts verhindern */ TIFR|=0b00010000; /* Anstehende Zündimpulse löschen */ ub_newcalc=0; calcphase(); } else { if(li_leistung>=995) /* Mehr als 99,5% Leistungsanforderung gibt Daueraktivierung auf den Zündausgang */ { TIMSK&=0b11101111; /* Weitere Zündimpulse durch sperren des Timerinterrupts verhindern */ TIFR|=0b00010000; /* Anstehende Zündimpulse löschen */ PORTB.3=0; /* Zündausgang dauerhaft aktivieren */ ub_newcalc=0; } else { ui_leistungswinkel=ui_phasenwinkel-((li_leistung*ui_phasenwinkel)/1000); /* Delta Timerwert für Leistung berechnen */ TIFR|=0b00010000; /* Anstehende Zündimpulse löschen */ TIMSK|=0b00010000; /* Zündimpulse wieder freigeben */ ub_newcalc=0; }; } }; // Full Power LED if(li_leistung>990) { PORTB.4=1; /* Full Power LED ein */ } else { PORTB.4=0; /* Full Power LED aus */ } }; }






Zitieren



Lesezeichen