;************** Flugregler ***************** ;Kanaleingang an PB2 (Int0) ;Interner Quarz: 1,6 MHz ;Steuerausgang PB1 (OC1A) PWM ;Steuerausgang Bremse PB0 ;Temperaturüberwachung PB3(ADC2) ;Spannungsüberwachung PB4(ADC3) .include "tn15def.inc" ; GENERELLE FUNKTIONSWEISE ; ______________________________________ ; jede ansteigende Impulsflanke des Kanalimpulses löst einen Interrupt 0 aus, wobei Flags gesetzt ; und relevante Counter zurückgesetzt werden ; über den Overflow-Interrupt des Timers 0 wird durch hochzählen eines Counters während der Dauer ; des anliegenden positiven Kanalimpulses die Länge dieses Kanalimpulses ermittelt ; der endgültige Wert wird durch Bildung des arithmetischen Mittelwertes ermittelt ; beim Einschalten wird je nach Stellung des Steuerknüppels über die Funktionalität- ; mit oder ohne Bremse - entschieden Standard is Bremse ON ; ist der Kanalimpuls Null, wird die Bremse aktiviert ; es werden die Analogwerte für Spannung eingelesen sowie auch Temperaturwerte eingelesen ; deren Auswertung erfolgt nach der arithmethischen Mittelwertbildung ; werden entsprechende Schwellwerte unter- bzw. überschritten, wird die Speedgeschwindigkeit auf Null ; gesetzt. Erst wenn der Steuerknüppel wieder auf Null gestellt wurde, ist der Regler wieder aktiv ; vor der Programmierung muss das Kalibrierungsbyte eingelesen und im Quelltext eingesetzt werden ; dann erst wird der Quelltext kompiliert ; ------------------------------------------------------------ .def rm_1 = r16 ; Multifunktionsregister .def rm_2 = r17 ; Multifunktionsregister .def rm_1int = r18 ; Multifunktionsregister bei Interrupts .def rm_2int = r19 ; Multifunktionsregister bei Interrupts ; --------------------------------------------------------------------- .def rFlags = r20 ; Flagregister ; --------------------------------------------------------------------- .def rcountT0 = r21 ; Counter zur Ermittlung der Eingangsimpulsbreite .def rcount_help = r22 ; Hilfs-Counter ; --------------------------------------------------------------------- .def rDelay1 = r23 .def rDelay2 = r24 ; für Verzögerungsanwendungen ; --------------------------------------------------------------------- .def rADCValue = r25 .def rCount_UT = r26 .def roldValue = r27 ; --------------------------------------------------------------------- .def rImpValue = r13 ; Impulswert -> Wert entspricht der ausgezählten Impulsbreite ; --------------------------------------------------------------------- .def rTempLow = r0 .def rTempHigh = r1 ; --------------------------------------------------------------------- .def rTemp_Ulow = r2 .def rTemp_Uhigh = r3 .def rTemp_Tlow = r4 .def rTemp_Thigh = r5 ; *************************** Konstanten(Wert) Definitionen ******************************** .equ cfreq = 1600000 ; ############# interne Quarzfrequenz ######################## .equ cTimer0Init = 235 ; 2,1 ms => ca.100 Durchläufe bei Timer0 - OV ; unter Zurechnung 7 PC für Hinsprung-Rücksprung ; 7 PC innerhalb des Interruptaufrufes zur Programmabarbeitung ; CK wird nicht geteilt ; (0,625µs*20)+(14*0,625µs)= 21,25µs // 21,25µs*100 = 2,125ms ;---------------------------------------------------------- .equ cCalibration = 0x80 ; Kalibrierungsbyte ; vorher auslesen hier war es 0x80 ;---------------------------------------------------------- .equ cMinV = 0x34 ; minimale Einstellung / unterer Endpunkt ; d52*21,25µs = 1,1 ms(minimaler Kanalimpuls) ; In Flagregister .equ fl_ImpEnd = 0 .equ flBremse_ON = 1 .equ fl_Int0aktiv = 2 .equ fl_readADC = 3 ;---------------------------------------------------------------------------------------------- ; Interrupt table ;---------------------------------------------------------------------------------------------- .cseg .org 0 rjmp StartInit ; jump to Start-Handling .org INT0addr ; External Interrupt0 Vector Address rjmp Int0Handler .org PCaddr ; Pin Change Interrupt Vector Address reti .org T1CPaddr ; Timer1 Compare Interrupt Vector Address reti .org T1OVaddr ; Timer1 Overflow Interrupt Vector Address reti .org T0OVaddr ; Timer0 Overflow Interrupt Vector Address rjmp OV0Handler .org ERDYaddr ; EEPROM Ready Interrupt Vector Address reti .org ACaddr ; Analog Comparator Interrupt Vector Address reti .org ADCaddr ; AD Converter Interrupt Vector Address reti StartInit: ldi rm_1, 0b00000011 out DDRB,rm_1 ; data-direction for PortB ('1' = Output) cbi PORTB, PINB0 cbi PORTB, PINB1 ; Bremse off, PWM Output low -> no Speed ldi rm_1, cCalibration ; Kalibrierungsbyte in entsprechendes Register out OSCCAL, rm_1 ; The System Clock Oscillator Calibration Register – ldi rDelay2, 208 ; 100ms warten / Delayerklärung siehe bei Delay rcall Delay sbr rFlags, 1< 0,625µs out TCCR0, rm_1 ; Timer/Counter0 Control Register ; ******************************* Timer 0 konfigurieren E N D E ******************************* ; ******************************* Interrupt0 konfigurieren ************************************** ldi rm_1, 0b00000011 ; The rising edge of INT0 generates an interrupt request out MCUCR, rm_1 ; MCU Control Register ldi rm_1, 0b01000000 ; Bit 6 – INT0: External Interrupt Request 0 Enable out GIMSK, rm_1 ; General Interrupt Mask Register ; ******************************* Interrupt0 konfigurieren E N D E ****************************** sei ; Set Global Interrupt Flag Wait_firstImp: ldi rDelay2, 208 ; 100ms warten / Delayerklärung siehe bei Delay rcall Delay ldi rDelay2, 208 ; 100ms warten / Delayerklärung siehe bei Delay rcall Delay ldi rDelay2, 208 ; 100ms warten / Delayerklärung siehe bei Delay rcall Delay ldi rDelay2, 208 ; 100ms warten / Delayerklärung siehe bei Delay rcall Delay sbrs rFlags,fl_ImpEnd ; Warte so lange bis ein Kanalimpuls ausgewertet ist rjmp Wait_firstImp mov rm_1, rImpValue clc cpi rm_1, 80 ; Vergleich Knüppelstellung brsh Bremse_OFF ; wenn größer oder gleich, dann Bremse off rjmp Wait_toStart Bremse_OFF: cbr rFlags, 1< wenn Steuerknüppel auf Null stand (rImpValue=0) ; -------------------------------------- Control_Temp: clc ; Division durch 64 lsr rTemp_Thigh ror rTemp_Tlow lsr rTemp_Thigh ror rTemp_Tlow lsr rTemp_Thigh ror rTemp_Tlow lsr rTemp_Thigh ror rTemp_Tlow lsr rTemp_Thigh ror rTemp_Tlow lsr rTemp_Thigh ror rTemp_Tlow mov rm_1, rTemp_Tlow ; Mittelwert ist ermittelt mov rm_2, rTemp_Thigh clr rTemp_Tlow ; in Ausgangszustand clr rTemp_Thigh clr rCount_UT ; Counter in Ausgangszustand ; Kontrolle Temperatur cpi rm_2, 0x02 brlo WorkNorm ; High -Wert kleiner ->kein Temperaturproblem cpi rm_2, 0x04 ; Schwellwert errechnet Hex 03E8 brsh Abschalten_T ; Temperatur (High) weit ueber Sollwert cpi rm_1, 0xE8 ; Temperatur (Low) über Sollwert X°C (Bedingung: Teiler aus (R=2k und PTC=1k) brsh Abschalten_T ; Temperatur liegt über Schwellwert rjmp WorkNorm Abschalten_T: clr rm_1 out OCR1A,rm_1 ; Wert für PWM Null Abschalten_T_1: tst rImpValue breq WorkNorm ; Schleife rjmp Abschalten_T_1 ; erst weiter -> wenn Steuerknüppel auf Null stand (rImpValue=0) ; Ende A/D -Werte auswerten ; ------------------------------------------------------------ ;------------------------------------------------------------ WorkNorm: cbr rFlags,1< sollte in der Zeit vorgekommen sein clr rImpValue ; sonst Null / zur Störungsunterdrückung und Senderausfallerkennung tst rImpValue brne No_Bremsen rjmp Soft No_Bremsen: cbi PORTB, PINB0 ; Bremse off ; Softanlaufrealisierung Soft: cp rImpValue, roldValue breq SetOne brlo SetOne mov rm_1, roldValue SetUP_1: out OCR1A,rm_1 ; Wert für PWM eintragen ldi rDelay2, 10 ; für Warten 4,8ms rcall Delay inc rm_1 cp rm_1, rImpValue brlo SetUP_1 SetOne: mov roldValue, rImpValue out OCR1A,rImpValue ; Wert für PWM eintragen tst rImpValue breq BremseYes_No cbi PORTB, PINB0 ; Bremse off rjmp main BremseYes_No: sbrs rFlags, flBremse_ON ; Bremse 0n/Off je nach Flag rjmp NoBremse sbi PORTB, PINB0 ; Bremse on rjmp main NoBremse: cbi PORTB, PINB0 ; Bremse off ;wdr ; Watchdog Reset rjmp main ;##################################################################################################### ; ******************************************************************************************************* ; Int0Handler ; ******************************************************************************************************* ; wird ausgelöst wenn am Eingang ein Pegel von L/H auftritt (positive Flanke) ; Interruptroutine aktiviert den Timer/Counter0 Overflow Interrupt (enable) Int0Handler: sbr rFlags, 1< Anfang des Zählmodusses ; dann werden die OV0 hochgezählt, solange der PINB2 High ist ; ist PINB2 nicht mehr High, ist die Impulsbreite ausgemessen und der Counterwert wird verarbeitet OV0Handler: sbis PINB, PINB2 ; Portabfrage -> ist Signal immer noch HIGH rjmp ImpEnde inc rcountT0 ; Eingangsimpuls liegt noch an rjmp EndOV0 ImpEnde: ; kein Eingangsimpuls mehr / Messung fertig subi rcountT0, cMinV ; Minimumwert wird von eingelesenen Wert abgezogen tst rcountT0 breq isNull brmi isNull ; ergibt sich NULL oder Minus -> dann gleich weiter rjmp Multiplikation isNull: clr rcountT0 ; Dieser Wert wird mit Acht multipliziert ; daraus ergibt sich nach Mittelwertberechnung der Ansteuerwert des PWM - Signals ; --------- Multiplikation: ; mit 8 clr rm_2int clc lsl rcountT0 rol rm_2int clc lsl rcountT0 rol rm_2int clc lsl rcountT0 rol rm_2int tst rm_2int breq MultEnde ; wenn kein Überlauf ser rm_2int ; wenn Überlauf mov rcountT0,rm_2int ; auf Wert FF clr rm_2int MultEnde: ; ''''''''''''''''''''''''''''''' clr rm_2int clc ; Mittelwertermittlung add rTempLow, rcountT0 ; durch Addition von 4 Werten adc rTempHigh, rm_2int ; und anschließender Division durch acht inc rcount_help cpi rcount_help,4 brsh MittelWert ; wenn 4 dann rjmp EndOV0_1 MittelWert: ; Division durch 4 clc lsr rTempHigh ror rTempLow lsr rTempHigh ror rTempLow mov rcountT0,rTempLow clr rTempLow clr rTempHigh clr rcount_help mov rImpValue, rcountT0 ; PWM - Wert in rImpValue sbr rFlags,1< ca.100 Durchläufe out TCNT0, rm_1int RETI ; ***************************************************************************************************** ; ************************************** Verzögerung **************************************************** ; 769 PC bei rDelay2 = 1 ; daraus folgt 769 * 0,625µs = 480,62µs für einen Schleifendurchlauf ; Übergabeparameter in rDelay2 Delay: ser rDelay1 ; Wert auf 255 setzen Delay1: dec rDelay1 ; 1 decrementieren brne Delay1 ; wenn noch nicht Null erreicht ser rDelay1 ; Register wieder setzen, es war Null dec rDelay2 ; um 1 den übergebenen Wert decrementieren brne Delay1 ; wenn der zweite Wert auch noch nicht Null erreicht hat ; wieder in die innere Schleife ret ; *******************************************************************************************************