Keine Überraschung: Es geht schneller mit Inline ASM
von
am 23.11.2011 um 10:31 (2963 Hits)
Der Geschwindigkeitssucht nachgebend ist nun die ISR zur Quadratursignalauswertung in Inline ASM geschrieben. Da das erst mein zweiter µC-ASM Versuch ist, ist der Code mehr oder weniger aus dem Artikel des weiterführenden Links aus dem RN-Wissen ins mikrocontroller.net abgeschrieben.
Laut BASCOM Simulator benötigt die ISR jetzt ca 7,5µs (20µs weniger als vorher).
Hab dann das 2kHz Simulatorsignal parallel auf PortA und PortB gegeben und über PCINT0 und PCINT1 zählen lassen. Sieht aus, als wenn jede Zustandsänderung mindestens bis hinunter auf 20µs Phasenversatz richtig erfaßt wird.
Sollte auch funktionieren, da jetzt durch die Parallelschaltung ein PCINT0 und PCINT1 gleichzeitig auftreten können. In 7,5µs wird der erste PCINT0 vom Quadratursignal-A-rechter Encoder (Q-A-R) abgearbeitet und in weiteren 7,5µs der PCINT1 vom Q-A-Links (das Interrupt flag steht ja solange, bis es glöscht wird bzw die ISR abgearbeitet wird). Also noch 5µs Zeit, bis die nächsten Interrupts von Q-B-R und Q-B-L auftreten können.
Damit bin ich sehr zufrieden. Das angestrebte Ziel, die Quadratursignale von zwei Encodern mit 2kHz und minimalem Phasenversatz jedes Encoders von 40µs zu verarbeiten, wird locker erreicht und der µC kann auch noch ein bischen mehr machen als zu zählen.
Jetzt muß ich mir wohl langsam überlegen, was ich mit den Meßwerten überhaupt mache
PS. ich schreibe relativ ausführlich, weil ich hoffe auf Denkfehler aufmerksam gemacht zu werden. Jegliche andere Kommentare, Fragen und Verbesserungsvorschläge natürlich auch willkommen.
Gruß
Searcher
Auszug aus Testprogramm mit ASM
Code:Dim Encoder_right As Byte Dim Encoder_right_value As Word Set Pcmsk0.pcint1 : Set Pcmsk0.pcint2 'Pin Change Interrupt 0 auf PA1 und PA2 möglich On Pcint0 Isr_pcint0 Nosave Enable Pcint0 'Enable Pin Change Interrupt auf PortA Isr_pcint0: $asm push r17 'Altes Drehgeberbitmuster, später Drehgeberzähler in r17,sreg push r17 push r18 'work register push r30 '=ZL push r31 '=ZH lds r17, {Encoder_right} 'altes Drehgeberbitmuster von vorherigem INT laden lsl r17 'altes Drehgeberbitmuster um 1 links schieben lsl r17 'altes Drehgeberbitmuster nochmal um 1 nach links schieben in r18,pinA 'drehgeber port einlesen lsr r18 'benutzte pina.2 und pina.1 auf untere bitpositionen schieben andi r18, 3 'die oberen nicht benutzten bits auf 0 setzen or r17, r18 'in Drehgeberbitmuster einblenden andi r17, 15 'index auf untere 4 bits begrenzen - uralt werte löschen ldi ZL, low (Encoder_table*2) 'Adresse der Drehgeber-Increment Tabelle ldi ZH, high (Encoder_table*2) 'Adresse der Drehgeber-Increment Tabelle add ZL, r17 'index aufaddieren ldi r18, 0 adc ZH, r18 'Übertrag auch sts {Encoder_right}, r17 'Drehgeberbitmuster sichern lpm r18, z 'increment wert holen lds r17, {Encoder_right_value} 'low byte drehgeberzähler holen add r17, r18 'increment wert aufaddieren sts {Encoder_right_value},r17 'low byte drehgeberzähler sichern lds r17, {Encoder_right_value} + 1 'high byte drehgeberzähler holen ldi r18, 0 adC r17, r18 'übertrag auf high byte addieren sts {Encoder_right_value} + 1,r17 'high byte drehgeberzähler sichern pop r31 pop r30 Pop r18 pop r17 out sreg,r17 pop r17 reti $end Asm Encoder_table: 'Orginaltabelle ' Data 0 , 0 , 1 , 0 , 0 , 0 , 0 , -1 , -1 , 0 , 0 , 0 , 0 , 1 , 0 , 0 'angepaßte Tabelle addiert auch bei umgekehrter Drehrichtung Data 0 , 0 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 0 , 0