;------------------------------------------------------------------------- ; Krabbler für ATmega8 ;------------------------------------------------------------------------- ;funktioniert ; dient der Entwicklung des SPI für die dargestellte Schaltung ; Funktion : ATmega8 ist SPI-Master; wählt durch SoftwareSlaveSelect (PORT c1 oder C2) einen der ; ATTinys (PIN B0) als Slave aus, dieser antwortet über Port B1 (PIN C3); jeder Slave steuert sechs Servos ; Die Servos 1 bis 6 hängen an Slave 1, Nr. 9 bis 14 an Slave 2 ; zur Datenübertragung wird die Servonummer ins obere Nibbel des ersten Bytes gepackt, das untere Nibbel ; des Highbytes ins untere Nibbel des ersten Bytes und das Lowbyte in das zweite Byte ; ATmega8 steuert das Radarservo, das LCD-Display, treibt den Distanzsensor und berechnet die Wege ; Die Pulsdauer für das Radarservo ist interruptgesteuert ; Zur Gerätjustierung wird per Taster in den Programmiermodus umgeschaltet (LED an!) ; Dazu werden die Servos per Joystick eingestellt und die so ermittelten Pulslängen anschließend im EEPROM gespeichert; ; zu jedem der sechs Servopaare gibt es je fünf Positionen (vorn-Mitte-hinten;oben-unten) mit Low und High-Byte ; Schaltung : SPI: MOSI, SCK ATMega8 zu ATTinys, ISP und LCD-shielt lt. Datenblatt B3,B4,B5 ; ATMega8 - ATTiny2313 ; C1 - B0 ; C2 - B0 ; C3 - B1 ; ATMega8 - LCD-shield ; C0 - A0 ADC für Joystick ; D2 - RST Taster zur Umschaltung auf Programmierung ; D4 - D4 Displaycontroller-Umschaltung ; D5 - D5 Displaycontroller select ; D6 - D6 LCD-Reset ; D7 - D7 LCD-Beleuchtung ; C4: Radarservo ;------------------------------------------------------------------------- ; Prozessor : ATmega8 ; Takt : 3686400 Hz ; Sprache : Assembler (GNU) ; Datum : 13.10.2012 ; Version : 1.3.1 ; Autor : U.S. ;------------------------------------------------------------------------- ; ; Registerfestlegungen: R0 zum Auslesen des FlashRAM und für Multiplikation ; R1 Multiplikation ; R0 + R1 Multiplikationsergebnis mul (R1h:R0l) ; R2 EEPROM-Tabellenindex (Nummer der aktuellen Position im PModus) ; R3 Nr. des aktuellen Servopaars im PModus (1 bis 6) ; R4 Nr. der aktuellen Servoposition im PModus (1 bis 5: vorn-Mitte-hinten;oben-unten) ; R15 Servonummer ; R16 temporär ; R17 temporär 2 und Datenübergaberegister ; R18 Datenübergabe an SPI (LCD Daten und Steuerung) und an EEPROM Routinen ; R20 + R21 Übergabe eines Word (R21h:R20l) ; R22 + R23 Pulsdauer Radarservo (R23h:R22l) ; R24 + R25 Servopulsdauer (R25h:R24l) ; .include "avr.h" begin: rjmp main ; 1 POWER ON RESET rjmp ISR_Taster ; 2 Int0-Interrupt reti ; 3 Int1-Interrupt reti ; 4 TC2 Compare Match reti ; 5 TC2 Overflow reti ; 6 TC1 Capture rjmp ISR_Vergl_A ; 7 TC1 Compare Match A rjmp ISR_Vergl_B ; 8 TC1 Compare Match B reti ; 9 TC1 Overflow reti ;10 TC0 Overflow reti ;11 SPI, STC Serial Transfer Complete reti ;12 UART Rx Complete reti ;13 UART Data Register Empty reti ;14 UART Tx Complete reti ;15 ADC Conversion Complete reti ;16 EEPROM Ready reti ;17 Analog Comparator reti ;18 TWI (I²C) Serial Interface reti ;19 Store Program Memory Ready ;------------------------------------------------------------------------ ; Initialisierungen ;------------------------------------------------------------------------ main: ldi R16,hi8(RAMEND) ; Stack Initialisierung out SPH,R16 ldi R16,lo8(RAMEND) out SPL,R16 ; Ports B2-5 werden durch SPI-Init festgelegt ; PORTC0 für ADC sbi DDRC,1 ; PORTC1 als Ausgang (SS1) sbi PORTC,1 ; Pegel high sbi DDRC,2 ; PORTC2 als Ausgang (SS2) sbi PORTC,2 ; Pegel high cbi DDRC,3 ; PORTC3 als Eingang (Slave-Rückmeldung) sbi PORTC,3 ; mit Pullup sbi DDRC,4 ; PORTC4 als Ausgang für Radarservo cbi DDRD,2 ; PORTD2 als Eingang für Taster (RST an LCD-shield) sbi PORTD,2 ; mit Pullup sbi DDRD,4 ; PORTD4-7 als Ausgang für LCD-shield sbi DDRD,5 sbi DDRD,6 sbi DDRD,7 ldi R22,lo8(691) ; Timerstartwert liegt bei 1500µS (Mittelstellung) ldi R23,hi8(691) ; errechnet sich nach (= Impulsdauer * Prozessorfrequenz / Timerprescaler) ldi R16,lo8(9216) ; Timerendwert liegt bei 20ms (umgerechnet wie vorstehend) ldi R17,hi8(9216) out OCR1AH,R17 out OCR1AL,R16 ldi R16,0b00011000 ; Interrupt OCIE1A und OCIE1B eingeschaltet out TIMSK,R16 ldi R16,0b0001010 ; CTC-Mode, Prescaler 8 out TCCR1B,R16 in R16,GICR ; INT0 Interrupt an Eingang PORTD2 bei fallender Flanke sbr R16,0b01000000 out GICR,R16 in R16,MCUCR ; fallende Flanke sbr R16,0b00000010 out MCUCR,R16 ldi R16,0b00100000 ; ADC initialisieren: Port, Referenzspannung und Auflösung out ADMUX,R16 ldi R16,0b10000101 ; Modus, Interrupt und Start out ADCSRA,R16 rcall SPI_init rcall LCD_init rcall EEPROM_init ; EEPROM-Tabelle für Justierpositionen prüfen ; RAM-Tabelle der aktuellen Servopositionen anlegen rcall Warte500ms ; Pause 500 ms; warten bis die Initialisierung der Slaves sicher beendet ist ;rcall WDT_init sei ; Interrupts erlauben ;------------------------------------------------------------------------ ; Hauptprogramm-Schleife ;------------------------------------------------------------------------ mainloop: wdr ; Arbeitsmodus clr R2 ; falls anschließend PModus, dazu Merker vorbereiten sbic PORTD,7 ; Programmiermodus an? angezeigt durch eingeschaltete LCD-Beleuchtung rjmp PModus ; ja -> Programmiermodus ; Erkennung der Umgebung per Radar ; Steuerung der Servos ;welcher Slave wird angesteuert? rjmp mainloop ;------------------------------------------------------------------------ PModus: wdr ; Programmiermodus sbis PORTD,7 ; Programmiermodus an? rjmp mainloop ; nein -> Arbeitsmodus tst R2 ; erster Durchgang? brne PM_2 ; nein, dann weiter ldi R16,1 ; ja, zunächst Bildschirm aufbauen, ab Textzeile1 rcall LCD_Bildschirm_darstellen ; rcall Servos_Grundstellung;alle Servos in eine noch zu bestimmende Grundstellung bringen z.B. alle Mitte bzw. unten inc R2 ; beginnt mit Servoposition Nr.1 (beinhaltet Servopaar Nr. 1 in Position vorn) ldi R16,1 mov R15,R16 ; Servo Nr 1 rcall Pos_txt ; Wort1 (vorn) rcall EELesen ; jetzt wird die Pulsdauer zu Position 1 aus dem EEPROM ausgelesen und in (R25h:R24l) abgelegt rcall Pulsd_aktl ; auf dem Display angezeigt und an Slave übertragen werden PM_2: rcall Progmodif rjmp PModus ;------------------------------------------------------------------------ ; Initialisierungsroutinen ;------------------------------------------------------------------------ ; SPI-Initialisierung als Master SPI_init: sbi DDRB,2 ; SS als Ausgang - wird nicht benutzt sbi DDRB,3 ; MOSI als Ausgang cbi DDRB,4 ; MISO als Eingang sbi DDRB,5 ; SCK als Ausgang ldi R16,0b01010001 ; enable SPI, Master, fosc/16 out SPCR,R16 ret ;------------------------------------------------------------------------ WDT_init: push R16 wdr ldi R16,0b00011000 ; Watchdog Startsequenz out WDTCR,R16 ldi R16,0b00001011 ; Watchdog ein ca. 100 ms out WDTCR,R16 pop R16 ret ;------------------------------------------------------------------------ LCD_init: cbi PORTD,6 ; Display reset nop nop nop sbi PORTD,6 cbi PORTD,5 ; Displaycontroller select nop nop nop sbi PORTD,5 nop nop nop ;sbi PORTD,7 ; Beleuchtung an ldi R18,0x21 ; LCD erw.Kommandos rcall LCD_Steuerungsbyte ldi R18,0xC0 ; LCD Kontrast rcall LCD_Steuerungsbyte ldi R18,0x06 ; LCD Temp. Koeffizient rcall LCD_Steuerungsbyte ldi R18,0x13 ; LCD Verst.Fakt. 1:48 rcall LCD_Steuerungsbyte ldi R18,0x20 ; Adressierungsmodus horizontal rcall LCD_Steuerungsbyte rcall LCD_leeren ldi R18,0x0C ; LCD Normalmodus rcall LCD_Steuerungsbyte cbi PORTD,5 ret LCD_leeren: ldi R18,0x0C ; LCD Normalmodus rcall LCD_Steuerungsbyte ldi R18,0x80 ; X-Koordinate auf Null rcall LCD_Steuerungsbyte ldi r18,0 rcall Halbleeren ; 1. Hälfte rcall Halbleeren ; 2. Hälfte ret Halbleeren: ldi R16,252 ; halbes Display leeren n_Ch: rcall LCD_Datenbyte dec R16 brne n_Ch ret ;------------------------------------------------------------------------ ; Interruptserviceroutinen ;------------------------------------------------------------------------ ;ISR: TIMER1 Compare Match A - 20ms abgelaufen ISR_Vergl_A:sbi PORTC,4 ; Port C.4 auf high out OCR1BH,R23 ; die aktuelle Pulsdauer ist in R22 (high) out OCR1BL,R22 ; und R21 (low) abgelegt reti ;------------------------------------------------------------------------ ;ISR: TIMER1 Compare Match B - Pulsdauer für Radarservo abgelaufen ISR_Vergl_B:cbi PORTC,4 ; Port C.4 auf low reti ;------------------------------------------------------------------------ ;ISR: INT0 für Taster Programmiermodus - wird bei Betätigung ein- bzw. ausgeschaltet ISR_Taster: push R16 ldi R16,25 ; 50 µs sind erforderlich Entprell: dec R16 ; einfache Warteroutine zum Entprellen brne Entprell ; abgezählt? sbic PORTD,7 ; war ausgeschaltet? rjmp Abschalten ; nein sbi PORTD,7 ; Einschalten rjmp ISR_T_Ende Abschalten: cbi PORTD,7 ISR_T_Ende: pop R16 reti ;------------------------------------------------------------------------ ; Unterprogramme ;------------------------------------------------------------------------ ; Warte-Routine für 500 ms (480,6 ms) Warte500ms: push R16 ldi R16,9 W500_3: push R16 ldi R16,255 W500_2: push R16 ldi R16,255 W500_1: dec R16 brne W500_1 pop R16 dec R16 brne W500_2 pop R16 dec R16 brne W500_3 pop R16 ret ;-------------------------------------------------------------------- ; Warte-Routine für 300 ms Warte300ms: push R16 ldi R16,150 w300_3: push R16 ldi R16,10 w300_2: push R16 ldi R16,255 w300_1: dec R16 brne w300_1 pop R16 dec R16 brne w300_2 pop R16 dec R16 brne w300_3 pop R16 ret ;-------------------------------------------------------------------- ; Warte-Routine für 10 ms Warte10ms: push R16 ldi R16,10 w10_3: push R16 ldi R16,5 w10_2: push R16 ldi R16,255 w10_1: dec R16 brne w10_1 pop R16 dec R16 brne w10_2 pop R16 dec R16 brne w10_3 pop R16 ret ;-------------------------------------------------------------------- ; Warte-Routine für 1 ms (1,052 ms) Warte1ms: push R16 ldi R16,1 w1_3: push R16 ldi R16,5 w1_2: push R16 ldi R16,255 w1_1: dec R16 brne w1_1 pop R16 dec R16 brne w1_2 pop R16 dec R16 brne w1_3 pop R16 ret ;------------------------------------------------------------------------ ; ein Byte übertragen per SPI, die Daten werden in R18 übergeben SPI_senden: out SPDR,R18 ; SPI Datenregister füllen und damit Übertragung starten komplett: sbis SPSR,SPIF ; Übertragung vollständig? rjmp komplett ; nein - warten ret ;------------------------------------------------------------------------ ;Joystickwerte: nach AD-Wandlung wird die Position als Wert 0-5 in R0 übergeben ;gemessene Werte daraus resultierende Grenzwerte ;ohne Betätigung 255 0: 0- 20 (links) ;gedrückt 38 1: 21- 60 (gedrückt) ;oben 186 2: 30-105 (unten) ;unten 84 3: 106-156 (rechts) ;rechts 126 4: 157-220 (oben) ;links 1 5: 221-255 (ohne Betätigung) Joystick: rcall ADCeinlesen ; abfragen clr R0 ldi R17,20 cp R16,R17 brlo J_Ende ; kleiner als der Grenzwert 0 inc R0 ldi R17,60 cp R16,R17 brlo J_Ende ; Grenzwert 1 inc R0 ldi R17,105 cp R16,R17 brlo J_Ende ; Grenzwert 2 inc R0 ldi R17,156 cp R16,R17 brlo J_Ende ; Grenzwert 3 inc R0 ldi R17,220 cp R16,R17 brlo J_Ende ; Grenzwert 4 inc R0 J_Ende: ret ;-------------------------------------------------------------------- ; digitalisiert einen Analogwert und wartet auf das Ergebnis; Rückgabewert in R16 ADCeinlesen:sbi ADCSRA,6 ; Start ADC ADCeinl2: sbic ADCSRA,6 ; Test ob fertig rjmp ADCeinl2 ; wenn nicht fertig in R16,ADCH ; Einlesen des Analogwertes ret ;------------------------------------------------------------------------ ; ein Byte an LCD senden (wird in R18 übergeben) LCD_Datenbyte: cbi PORTD,5 ; Displaycontroller selektiert sbi PORTD,4 ; Displaycontroller: Datenbyte rcall SPI_senden sbi PORTD,5 ; Displaycontroller deselektiert ret LCD_Steuerungsbyte: cbi PORTD,5 ; Displaycontroller selektiert cbi PORTD,4 ; Displaycontroller: Steuerungsbyte rcall SPI_senden sbi PORTD,5 ; Displaycontroller deselektiert ret ;-------------------------------------------------------------------- ; Word (begrenzt auf Werte unter 10000) wird auf dem Bildschirm als Dezimalwert angezeigt ; Übergabe in r21h:r20l, die Ausgabeposition wurde zuvor festgelegt (XY) LCD_Word_in_Dez: ldi R17,48 ; ASCII Null mov R0,R17 ldi R17,hi8(1000) ; Tausenderstelle ldi R16,lo8(1000) rcall LCD_WiD_Div ldi R17,48 ; ASCII Null mov R0,R17 ldi R17,0 ; Hunderterstelle ldi R16,100 rcall LCD_WiD_Div ldi R17,48 ; ASCII Null mov R0,R17 ldi R17,0 ; Zehnerstelle ldi R16,10 rcall LCD_WiD_Div ldi R17,48 ; ASCII Null mov R0,R17 add R0,R20 ; in R20 sind jetzt nur noch die Einer übrig rcall LCD_Zeichen_darstellen ret LCD_WiD_Div:cp R20,R16 ; Word größer oder gleich Vergleichswert? cpc R21,R17 brlo LCD_WiD_Aus ; nein -> Ausgabe sub R20,R16 ; ja -> subtrahieren sbc R21,R17 inc R0 ; Dezimalstelle erhöhen rjmp LCD_WiD_Div LCD_WiD_Aus:rcall LCD_Zeichen_darstellen ret ;------------------------------------------------------------------------ LCD_Zeichen_darstellen: ; ein einzelnes Zeichen wird an der zuvor festgelegten Pos. dargestellt push ZL ; die Nummer des ASCII-Zeichen ist in R0 abgelegt push ZH ; die graphische 5x7 Darstellung findet sich im Flash-RAM unter push R16 ; Datensatz+Asciiwert*5 ff. push R17 mov R16,R0 subi R16,32 ; die Asciicodes beginnen mit Leerzeichen an Nr. 32 ldi R17,5 mul R16,R17 ldi ZL,lo8(Zeichensatz) ldi ZH,hi8(Zeichensatz) add ZL,R0 adc ZH,R1 ldi R18,0x00 ; Zwischenraum zum Nachbarzeichen (eine Punktspalte) rcall LCD_Datenbyte ldi R16,5 ; fünf Spalten zu 7 Punkten LCD_Z_2: lpm R18,Z+ rcall LCD_Datenbyte dec R16 brne LCD_Z_2 pop R17 pop R16 pop ZH pop ZL ret ;------------------------------------------------------------------------ LCD_Zeile_darstellen: ; eine Zeile von 14 Zeichen wird aus dem Flashspeicher geholt push ZL ; und an der zuvor festgelegten Position (XY-Koordinaten) dargestellt push ZH ; die Nummer der Textzeile im Flashspeicher wird in R16 übergeben push R16 push R17 dec R16 ; Offset ist eins kleiner als die Nummer ldi R17,15 ; die Textstrings sind nullterminiert: 14+1 ! mul R16,R17 ; Ergebnis wird in ldi R16,14 ; 14 Zeichen sind einzulesen ldi ZL,lo8(Textzeile1) ldi ZH,hi8(Textzeile1) add ZL,R0 adc ZH,R1 LCD_Zl_2: lpm rcall LCD_Zeichen_darstellen adiw ZL,1 ;nächstes Zeichen dec R16 brne LCD_Zl_2 pop R17 pop R16 pop ZH pop ZL ret ;------------------------------------------------------------------------ LCD_Bildschirm_darstellen: ; der ganze Bildschirm wird dargestellt durch 6 aufeinander folgende Textzeilen ; die Nummer der ersten Zeile wird in r16 übergeben ldi R18,0x40 ; Bildschirmkoordinaten auf 0, zuerst die Spalte rcall LCD_Steuerungsbyte ldi R18,0x80 ; jetzt die Reihe auf 0 rcall LCD_Steuerungsbyte ldi R17,6 ; 6 Zeilen LCD_B_2: rcall LCD_Zeile_darstellen inc R16 ; nächste Zeile dec R17 ; fertig? brne LCD_B_2 ret ;------------------------------------------------------------------------ LCD_Wort_darstellen: ; ein Wort (Position) wird aus dem Flashspeicher geholt push ZL ; und an der zuvor festgelegten Position (XY-Koordinaten) dargestellt push ZH ; die Nummer des Worts im Flashspeicher wird in R16 übergeben push R16 push R17 dec R16 ; Offset ist eins kleiner als die Nummer ldi R17,7 ; die Textstrings sind nullterminiert: 6+1 ! mul R16,R17 ldi R16,6 ; 6 Zeichen sind einzulesen ldi ZL,lo8(Wort1) ldi ZH,hi8(Wort1) add ZL,R0 adc ZH,R1 LCD_W_2: lpm rcall LCD_Zeichen_darstellen adiw ZL,1 ;nächstes Zeichen dec R16 brne LCD_W_2 pop R17 pop R16 pop ZH pop ZL ret ;------------------------------------------------------------------------ ;EEPROM-Tabelle für Justierpositionen prüfen ;------------------------------------------------------------------------ EEPROM_init:ldi R24,lo8(1500) ; falls sich dort leere Werte finden (unzulässig!), ldi R25,hi8(1500) ; wird die Mittelstellung 1500(µS) eingetragen ldi R16,30 ; zu jedem der sechs Servopaare mit fünf Positionen (vorn-Mitte-hinten;oben-unten) Low und High-Bit mov R2,R16 ; R2 Zähler auf 30 (Position) clr R17 ; die Tabelle beinhaltet 60 Werte, d.h. das Highbit für den EEPROM-Zugriff ist immer 0 EE_i2: mov R16,R2 dec R16 ; der Speicher beginnt bei 0 lsl R16 ; immer Lo- und Hi-Byte abwechselnd gespeichert rcall EELesen ; Lo-byte lesen tst R18 ; leer? brne EE_i2_nP ; nein - nächste Position inc R16 ; ja rcall EELesen ; Hi-Byte lesen tst R18 ; auch leer? brne EE_i2_nP ; nein - nächste Position rcall InEEPROM ; ja: Mittelstellung 1500(µS) speichern EE_i2_nP: dec R2 brne EE_i2 ret ;------------------------------------------------------------------------ ; der aktuelle Wert der Servopulsdauer (R25h:R24l) wird im EEPROM abgelegt, die Position steht in R2 ;------------------------------------------------------------------------ InEEPROM: clr R17 ; ist immer 0, da nur 60 Werte mov R16,R2 dec R16 ; der Speicher beginnt bei 0 lsl R16 ; immer Lo- und Hi-Byte abwechselnd gespeichert mov R18,R24 rcall EESchreiben inc R16 mov R18,R25 rcall EESchreiben ret ;------------------------------------------------------------------------ ; der aktuelle Wert für die Servopulsdauer (R25h:R24l) wird aus dem EEPROM geholt, die Position steht in R2 ;------------------------------------------------------------------------ AusEEPROM: clr R17 ; ist immer 0, da nur 60 Werte mov R16,R2 dec R16 ; der Speicher beginnt bei 0 lsl R16 ; immer Lo- und Hi-Byte abwechselnd gespeichert rcall EELesen mov R24,R18 inc R16 rcall EELesen mov R25,R18 ret ;---------------------------------------------------------------------- ;Daten aus EEPROM lesen, R17:R16 = Adresse, R18 = Wert aus EEPROM ;---------------------------------------------------------------------- EELesen: out EEARH,R17 ;AdresseH out EEARL,R16 ;AdresseL sbi EECR,0 ;Leseaufforderung WarteEEL: sbic EECR,0 ;warte auf Fertigmeldung rjmp WarteEEL in R18,EEDR ;Daten übernehmen ret ;---------------------------------------------------------------------- ;Daten in EEPROM schreiben, R17:R16 = Adresse, R18 = Wert für EEPROM ;---------------------------------------------------------------------- EESchreiben:out EEARH,R17 ;AdresseH out EEARL,R16 ;AdresseL out EEDR,R18 ;Daten übergeben sbi EECR,2 ;Schreiben erlauben sbi EECR,1 ;Schreibaufforderung warteEES: sbic EECR,1 ;warten bis fertig rjmp warteEES ret ;------------------------------------------------------------------------ ; Pulsdauer für ein Servo übertragen, die Daten liegen in R15 (Servonummer), R24 (Lowbyte) und R25 (Highbyte) ;------------------------------------------------------------------------ Warte_100us:push R16 ldi R16,1 ; Anzahl der 100 µs W_100us_3: push R16 ldi R16,1 W_100us_2: push R16 ldi R16,115 W_100us_1: dec R16 brne W_100us_1 pop R16 dec R16 brne W_100us_2 pop R16 dec R16 brne W_100us_3 pop R16 ret ByteTransf: sbic PINC,3 ; Antwort v. ATTiny durch low-Signal auf PIN C3 rjmp ByteTransf ; ATTiny noch nicht bereit rcall SPI_senden ; Byte senden fertig: sbis PORTC,3 ; Antwort v. ATTiny durch high-Signal auf PIN C3 rjmp fertig ; ATTiny noch nicht bereit ret Datentransfer: mov R18,R15 swap R18 or R18,R25 ; das obere Nibbel in R15 und R25 ist immer 0 - zur Übertragung in ein Byte gepackt rcall ByteTransf rcall Warte_100us mov R18,R24 rcall ByteTransf rcall Warte_100us ret Daten_An_Slave: sbrs R15,3 ; welcher Slave? rjmp Daten_An_Slave1 ; Servonummer 1-6 ldi R16,0b11110111 and R15,R16 ; Bit 3 löschen Daten_An_Slave2: cbi PORTC,2 ; Slaveselect durch PORTC2 auf low rcall Datentransfer sbi PORTC,2 ; deselektieren ret Daten_An_Slave1: cbi PORTC,1 ; Slaveselect durch PORTC1 auf low rcall Datentransfer sbi PORTC,1 ; deselektieren ret ;------------------------------------------------------------------------ ; Pulsdauer des aktuellen Servos aktualisieren: anzeigen (R25h:R24l) und an slave übertragen ;------------------------------------------------------------------------ Pulsd_aktl: ldi R18,0x45 ; Zeile 6 (40h+(6-1)) rcall LCD_Steuerungsbyte ldi R18,0x98 ; Spalte 5 (80h+4x6) rcall LCD_Steuerungsbyte movw R20,R24 rcall LCD_Word_in_Dez ; anzeigen rcall Daten_An_Slave ; und übertragen rcall Warte300ms ret ;------------------------------------------------------------------------ ;auf dem LCD-Display wird der Text zur aktuellen Position angezeigt; die Nummer des anzuzeigenden Worts steht in R16 ;------------------------------------------------------------------------ Pos_txt: ldi R18,0x43 ; Zeile 4 (40h+(4-1)) (Cursorposition Zeile4 zentriert) rcall LCD_Steuerungsbyte ldi R18,0x98 ; Spalte 5 (80h+(5-1)x6) rcall LCD_Steuerungsbyte rcall LCD_Wort_darstellen ret ;------------------------------------------------------------------------ Progmodif: ; Modifikation der Servoprogrammierung ;hier gehts weiter, opt 5, dann 3 und 6 rcall Joystick ; Joystick betätigt? ldi r16,5; cp r16,r0 ; ohne Betätigung? brne Option2 ret ; ohne Betätigung (Joystickantwort 5) Option2: dec r16 cp r16,r0 ; oben? brne Option3 adiw R24,1 ; oben: Pulsdauer verlängert (Joystickantwort 4) rcall Pulsd_aktl ; neue Pulsdauer angezeigt und an Slave gesendet ret Option3: dec r16 cp r16,r0 ; rechts? brne Option4 ;rechts: nächste Position (für jedes Servo vorn-Mitte-hinten bzw. oben-unten) (3) ret Option4: dec r16 cp r16,r0 ; unten? brne Option5 sbiw R24,1 ; unten: Pulsdauer verkürzt (Joystickantwort 5) rcall Pulsd_aktl ; neue Pulsdauer angezeigt und an Slave gesendet ;unten: Pulsdauer verKürzt (2) ret Option5: dec r16 cp r16,r0 ; gedrückt? brne Option6 ; gedrückt: aktuellen Wert im EEPROM speichern (1) ret Option6: ; links: vorherige Position (0) ret ; bei geänderter Position Pulsdauer aus dem EEPROM auslesen in (R25h:R24l) ablegen, Pos. auf LCD anzeigen (Servo und Stellwert) ;------------------------------------------------------------------------ Zeichensatz: .byte 0x00,0x00,0x00,0x00,0x00 ; sp .byte 0x00,0x00,0x2f,0x00,0x00 ; ! .byte 0x00,0x07,0x00,0x07,0x00 ; " .byte 0x14,0x7f,0x14,0x7f,0x14 ; # .byte 0x24,0x2a,0x7f,0x2a,0x12 ; $ .byte 0x62,0x64,0x08,0x13,0x23 ; % .byte 0x36,0x49,0x55,0x22,0x50 ; & .byte 0x00,0x05,0x03,0x00,0x00 ; ' .byte 0x00,0x1c,0x22,0x41,0x00 ; ( .byte 0x00,0x41,0x22,0x1c,0x00 ; ) .byte 0x14,0x08,0x3E,0x08,0x14 ; * .byte 0x08,0x08,0x3E,0x08,0x08 ; + .byte 0x00,0x00,0xA0,0x60,0x00 ; , .byte 0x08,0x08,0x08,0x08,0x08 ; - .byte 0x00,0x60,0x60,0x00,0x00 ; . .byte 0x20,0x10,0x08,0x04,0x02 ; / .byte 0x3E,0x51,0x49,0x45,0x3E ; 0 .byte 0x00,0x42,0x7F,0x40,0x00 ; 1 .byte 0x42,0x61,0x51,0x49,0x46 ; 2 .byte 0x21,0x41,0x45,0x4B,0x31 ; 3 .byte 0x18,0x14,0x12,0x7F,0x10 ; 4 .byte 0x27,0x45,0x45,0x45,0x39 ; 5 .byte 0x3C,0x4A,0x49,0x49,0x30 ; 6 .byte 0x01,0x71,0x09,0x05,0x03 ; 7 .byte 0x36,0x49,0x49,0x49,0x36 ; 8 .byte 0x06,0x49,0x49,0x29,0x1E ; 9 .byte 0x00,0x36,0x36,0x00,0x00 ; : .byte 0x00,0x56,0x36,0x00,0x00 ; ; .byte 0x08,0x14,0x22,0x41,0x00 ; < .byte 0x14,0x14,0x14,0x14,0x14 ; = .byte 0x00,0x41,0x22,0x14,0x08 ; > .byte 0x02,0x01,0x51,0x09,0x06 ; ? .byte 0x32,0x49,0x59,0x51,0x3E ; @ .byte 0x7C,0x12,0x11,0x12,0x7C ; A .byte 0x7F,0x49,0x49,0x49,0x36 ; B .byte 0x3E,0x41,0x41,0x41,0x22 ; C .byte 0x7F,0x41,0x41,0x22,0x1C ; D .byte 0x7F,0x49,0x49,0x49,0x41 ; E .byte 0x7F,0x09,0x09,0x09,0x01 ; F .byte 0x3E,0x41,0x49,0x49,0x7A ; G .byte 0x7F,0x08,0x08,0x08,0x7F ; H .byte 0x00,0x41,0x7F,0x41,0x00 ; I .byte 0x20,0x40,0x41,0x3F,0x01 ; J .byte 0x7F,0x08,0x14,0x22,0x41 ; K .byte 0x7F,0x40,0x40,0x40,0x40 ; L .byte 0x7F,0x02,0x0C,0x02,0x7F ; M .byte 0x7F,0x04,0x08,0x10,0x7F ; N .byte 0x3E,0x41,0x41,0x41,0x3E ; O .byte 0x7F,0x09,0x09,0x09,0x06 ; P .byte 0x3E,0x41,0x51,0x21,0x5E ; Q .byte 0x7F,0x09,0x19,0x29,0x46 ; R .byte 0x46,0x49,0x49,0x49,0x31 ; S .byte 0x01,0x01,0x7F,0x01,0x01 ; T .byte 0x3F,0x40,0x40,0x40,0x3F ; U .byte 0x1F,0x20,0x40,0x20,0x1F ; V .byte 0x3F,0x40,0x38,0x40,0x3F ; W .byte 0x63,0x14,0x08,0x14,0x63 ; X .byte 0x07,0x08,0x70,0x08,0x07 ; Y .byte 0x61,0x51,0x49,0x45,0x43 ; Z .byte 0x00,0x7F,0x41,0x41,0x00 ; [ .byte 0x55,0x2A,0x55,0x2A,0x55 ; \ .byte 0x00,0x41,0x41,0x7F,0x00 ; ] .byte 0xFC,0x20,0x40,0x40,0x3C ; ^ umdefiniert zu µ .byte 0x40,0x40,0x40,0x40,0x40 ; _ .byte 0x00,0x01,0x02,0x04,0x00 ; ' .byte 0x20,0x54,0x54,0x54,0x78 ; a .byte 0x7F,0x48,0x44,0x44,0x38 ; b .byte 0x38,0x44,0x44,0x44,0x20 ; c .byte 0x38,0x44,0x44,0x48,0x7F ; d .byte 0x38,0x54,0x54,0x54,0x18 ; e .byte 0x08,0x7E,0x09,0x01,0x02 ; f .byte 0x18,0xA4,0xA4,0xA4,0x7C ; g .byte 0x7F,0x08,0x04,0x04,0x78 ; h .byte 0x00,0x44,0x7D,0x40,0x00 ; i .byte 0x40,0x80,0x84,0x7D,0x00 ; j .byte 0x7F,0x10,0x28,0x44,0x00 ; k .byte 0x00,0x41,0x7F,0x40,0x00 ; l .byte 0x7C,0x04,0x18,0x04,0x78 ; m .byte 0x7C,0x08,0x04,0x04,0x78 ; n .byte 0x38,0x44,0x44,0x44,0x38 ; o .byte 0xFC,0x24,0x24,0x24,0x18 ; p .byte 0x18,0x24,0x24,0x18,0xFC ; q .byte 0x7C,0x08,0x04,0x04,0x08 ; r .byte 0x48,0x54,0x54,0x54,0x20 ; s .byte 0x04,0x3F,0x44,0x40,0x20 ; t .byte 0x3C,0x40,0x40,0x20,0x7C ; u .byte 0x1C,0x20,0x40,0x20,0x1C ; v .byte 0x3C,0x40,0x30,0x40,0x3C ; w .byte 0x44,0x28,0x10,0x28,0x44 ; x .byte 0x1C,0xA0,0xA0,0xA0,0x7C ; y .byte 0x44,0x64,0x54,0x4C,0x44 ; z .byte 0x00,0x06,0x09,0x09,0x06 ; { umdefiniert zu ° .byte 0x3E,0x22,0x22,0x22,0x3E ; | umdefiniert zu Leerkästchen .byte 0x3E,0x3E,0x3E,0x3E,0x3E ; } umdefiniert zu ausgefülltem Kästchen ;------------------------------------------------------------------------ ;hier werden die Texte definiert, jeweils 14 Zeichen lang Textzeile1: .string "}1| |2|" Textzeile2: .string " Puls " Textzeile3: .string "|3| |4|" Textzeile4: .string " " Textzeile5: .string "|5| |6|" Textzeile6: .string " ^S " Wort1: .string " vorn " Wort2: .string " Mitte" Wort3: .string "hinten" Wort4: .string " oben " Wort5: .string " unten"