„Incremental Interface Mode“ des

Mikrocontrollers C167 von Infineon

 

1. Allgemeines:

Ein Timer ist ein mit Befehlen initialisierter Hardware-Zähler, der programmunabhängig läuft. Er wird vor allem für Aufgaben eingesetzt, die sich durch Software nur sehr aufwendig programmieren lassen, z.B.:

 

-          PWM-Signal zur Ansteuerung von Motoren

-          Ereigniszähler für Signalflanken

-          periodische Interrupts als Zeitgeber

-          Frequenzgenerator und -messer

 

Als Taktquelle dient der interne Prozessortakt oder ein externes Signal. Der Gate-Eingang steuert den Takt des Timers. Bei einem Nulldurchgang des Zählers wird ein Interrupt ausgelöst und kann ein Signal nach außen abgegeben werden. Hilfsregister dienen zum Nachladen, Vergleichen und Auslesen des Zählerstand es und mit Hilfe der Steuerregister können verschiedene Betriebsarten eingestellt werden, die wichtigsten sind:

 

-          Timer-Mode: programmierbarer Frequenzteiler mit internem Takt,

-          Gated Timer-Mode: Frequenzteiler mit Gate-Steuerung,

-          Count-Mode: Ereigniszähler für externe Signalflanken,

-          Reload-Mode: Nachladbare Frequenzteiler,

-          Capture-Mode: Auslesen des Zählerstandes bei einem bestimmten Ereignis,

-          Compare-Mode: Ausgabe eines Signals bei einem bestimmten Zählerstand,

-          Incremental Interface-Mode: Erfassen phasenverschobener Positionssignale.

 

Es ist allerdings zu beachten, dass nicht jede Betriebsart von jedem Timer unterstützt wird.

 

2. Mehrzweck-Timereinheiten:

Die Mehrzweck-Timereinheiten (General Purpose Timer) GPT1 (Abb. 1)  und GPT2  des Mikrocontrollers C167 arbeiten völlig unabhängig voneinander und setzen sich aus 3 (GPT1) bzw. 2 (GPT2) 16-Bit Einzelzählern zusammen, wobei jeweils einer der Hauptzähler ist (Core Timer). Jeder dieser 5 Timer kann entweder für sich alleine oder in Kombination (z.B. kaskadiert) betrieben werden. Die Auflösung reicht je nach Einstellung und Timer von 160 ns bis ca. 41 µs, die maximale Periode liegt damit zwischen 10 ms und 2,68 s (alle Werte bei 25 MHz Taktfrequenz).

 

Über die externen Steuereingänge TxEUD kann die Zählrichtung der Timer verändert werden. Welcher Pegel hier welche Zählrichtung einstellt, ist zudem wählbar, so dass eine Anpassung an die verschiedensten Einsatzbedingungen möglich ist. Die interne Hardware der Timer ist so aufgebaut, dass bei jedem Zählimpuls, sei er vom internen Takt abgeleitet oder durch eine Flanke am externen Zähleingang TxIN erzeugt, gleichzeitig der Zustand der Zählrichtungseinstellung überprüft und der Timer dann entsprechend inkrementiert oder dekrementiert wird. Insbesondere im Counter-Betrieb mit externer Richtungseinstellung werden die beiden Eingänge TxIN und TxEUD zum selben Zeitpunkt abgefragt. Liegt kein Zählimpuls vor, hat der Zustand der Richtungseinstellung keine Bedeutung.

 

 

 

Abbildung 1: General Purpose Timer Unit GPT1

 

3. Erfassen phasenverschobener Positionssignale:

Diese gleichzeitige Abfrage der Richtungseingänge lässt sich gut ausnutzen, um phasenverschobene Signale, wie sie durch Wegstrecken-Sensoren oder ähnliches erzeugt werden, zu verarbeiten.

 

 

Abbildung 2: Generierung phasenverschobener Positionssignale

 

Abb. 2 zeigt die Generierung solcher Signale über z.B. eine spezielle Skala mit gegeneinander verschobenen Schwarz/Weiß-Balken, die mit optischen Sensoren abgetastet wird. Durch die Phasenverschiebung steckt in den beiden Signalen der Sensoren nicht nur die Zählinformation (also z.B. das Wegstrecken-Inkrement), sondern auch eine Richtungsinformation. Kommt die steigende Flanke von Signal 1 vor der steigenden Flanke von Signal 2, bedeutet dies z.B. die Richtung Rechts. Dreht sich die Richtung der Bewegung um, so kommt diesmal die steigende Flanke von 1 nach der steigenden Flanke von Signal 2. Wie kann nun diese Information mit einem Timer verarbeitet werden?

 

Variante 1 (Count-Mode):

Die beiden Signale sind ja auf den ersten Blick nicht trennbar in ein Zählsignal, das an den Count-Eingang TxIN anzuschließen wäre, und ein Richtungssignal, das den Eingang TxEUD steuert. Es ist jedoch einfach und ohne zusätzliche externe Gatter möglich, diese beiden Signale korrekt zu verarbeiten, allerdings mit der Einschränkung der geringeren Frequenz. Die Lösung des Problems liegt in der oben beschriebenen Tatsache, dass die Richtungsinformation am Pin TxEUD nur dann benötigt wird, wenn ein Zählimpuls anliegt. Schließt man nun Signal 1 an den Count-Eingang TxIN an und programmiert den Timer im Zählerbetrieb so, dass er z.B. die positive Flanke des Signals zählt, so kann man aus Abb. 3 sehen, dass der momentane Zustand des Signals 2 zum Zeitpunkt der positiven Flanke von Signal 1 die Richtungsinformation wiedergibt.

 

 

 

Abbildung 3: Bewertung des Richtungseingangs nur bei positiver Zählflanke

 

Man kann also Signal 2 direkt an den Steuereingang TxEUD legen und erhält so die gewünschte Funktion ohne zusätzlichen Aufwand. Abb. 4 zeigt den Verlauf des Zählerstandes für verschiedene Bewegungsrichtungen.

 

 

Abbildung 4: Zählerstand bei verschiedenen Bewegungsrichtungen

 

Allerdings arbeitet diese Lösung nur mit einer geringeren Frequenz im Vergleich zu speziellen ASIC-Bausteinen für diesen Zweck (Quadratur-Zähler). Bei dieser Methode wird ja nur eine Flanke von einem der beiden Signale als Zähl-Inkrement benutzt, während es mit zusätzlichem Logik-Aufwand möglich ist, jede Flanke beider Signale auszuwerten und so eine zwei- oder vierfach höhere Zählfrequenz zu erreichen (= höhere Genauigkeit).

 

Variante 2 (Incremental Interface-Mode):

Der Mehrzweck-Timer GPT1 stellt diesen zusätzlichen Logik-Aufwand in Form des „Incremental Interface-Mode“ zur Verfügung. Dabei kann der Eingang TxEUD nicht nur für die Richtungsinformation, sondern auch zur Flankenzählung verwendet werden.

 

Weiters besteht nun die Möglichkeit, sowohl steigende als auch fallende Flanken mit entsprechender Richtung zu zählen. Somit erreicht man eine bis zu vierfach höhere Zählfrequenz gegenüber Variante 1. Die anschließenden Erklärungen beziehen sich immer auf Timer T2, sie gelten aber genauso für die beiden anderen Timer von GPT1 (Timer 1 und 3).

 

Folgende Register gehören zu T2:

 

T2: Timer Datenregister: Dieses Register enthält den aktuellen Zählerwert. Je nach Drehrichtung des Signalgebers wird der Wert erhöht oder verringert.

T2IC: Interrupt Control Register:

 

 

Beim Überlauf des Timerregisters T2 von FFFFH auf 0000H (Aufwärtszählen) bzw. 0000H auf FFFFH (Abwärtszählen) wird ein Interrupt ausgelöst und T2IR gesetzt. Sind gleichzeitig das Einzel-Freigabebit T2IE = 1 und das Gesamt-Freigabebit IEN=1, so liegt die Anforderung an der Interrupt-Steuerung an und es wird die passende Interrupt Service Routine aufgerufen. Die Bitfelder ILVL und GLVL legen die Interrupt-Prioritätsebene fest.

 

Die neuen 16bit Mikrocontroller der Serie XC16x von Infineon [2] bieten eine Erweiterung, die bei jeder Flanke aber auch bei einem Richtungswechsel einen Interrupt auslöst. Das Control Register enthält drei zusätzliche Flags für die aktuelle Richtung, Richtungswechsel- und Flankenerkennung.

 

T2CON: Control Register: Zum Setzen des Modus und Konfiguration des Timers.

 

 

 

Tabelle 1 und 2 erklärt die Bedeutung der einzelnen Bitfelder und Bits.

 

Bit

Funktion

T2I

Timer 2 Input Selection: abhängig von Modus T2M (siehe Tabelle 4)

T2M

Timer 2 Mode Control:

000: Timer Mode

001: Counter Mode

010: Gated Timer mit Gate active low

011: Gated Timer mit Gate active high

100: Reload Mode

101: Capture Mode

110: Incremental Interface Mode

111: Reserviert. Nicht verwenden.

T2R

Timer 2 Run Bit:

0: Timer 2 deaktiviert

1: Timer 2 aktiviert

T2UD

Timer 2 Up/Down Control:

Siehe Tabelle 2

T2UDE

Timer 2 External Up/Down Enable:

Siehe Tabelle 2

Tabelle 1: Timer 2 Control Register Bits

 

 

Pin T2EUD

Bit T2UDE

Bit T2UD

Zählrichtung

X

0

0

Aufwärts

X

0

1

Abwärts

0

1

0

Aufwärts

1

1

0

Abwärts

0

1

1

Abwärts

1

1

1

Aufwärts

Tabelle 2: Timer 2 Zählrichtungskontrolle

 

Um den Incremental Interface-Mode ausführen zu können, müssen folgende Bedingungen erfüllt sein:

 

-          Bitfeld T2M muss auf #110b gesetzt sein.

-          Beide Pins (T2IN und T2EUD) müssen auf Input geschaltet sein, d.h. die entsprechenden Direction Control Bits sind #0b.

-          Bit T3UDE muss #1b sein, damit die automatische Richtungskontrolle aktiviert wird. Tabelle 3 zeigt die daraus resultierenden Richtungskombinationen.

 

 

Level des entsprechend anderen Eingangs

T2IN Eingangsflanke

T2EUD Eingangsflanke

Steigend

Fallend

Steigend

Fallend

High

Abwärts

Aufwärts

Aufwärts

Abwärts

Low

Aufwärts

Abwärts

Abwärts

Aufwärts

Tabelle 3: Automatische Zählrichtungen bei Incremental Interface-Mode

 

 

Wie oben bereits erwähnt, kann in diesem Modus die Zählfrequenz variiert werden. Tabelle 4 zeigt die möglichen Einstellungen und Abb. 5 bzw. 6 passende Beispiele.

 

T2I

Funktion

000

Keine. Zähler T2 stoppt.

001

Bei jeder Flanke an T2IN zählen.

010

Bei jeder Flanke an T2EUD zählen.

011

Bei jeder Flanke an T2IN und T2EUD zählen.

1xx

Reserviert. Nicht verwenden.

Tabelle 4: Timer 2 Input Selection T2I bei Incremental Interface-Mode

 

 

 

Abbildung 5: Timer zählt bei jeder Veränderung von Eingang T2IN

 

 

Abbildung 6: Timer zählt bei jeder Veränderung von Eingang T2IN und T2EUD

 


 

4. Beispiel:

 

Der Timer T2 soll benutzt werden, um die zwei Ausgangssignale eines magnetischen Impulsgebers zu dekodieren. Diese sind an den I/O-Pins T2IN und T2EUD des C167 angeschlossen. Damit ergibt sich folgende Einstellung für T2CON (#0173h):

 

 

Programm Code:

 

Im folgenden Programmteil werden die Drehzahlen zweier Antriebsmotoren eines Roboters über die Ausgänge magnetischer Signalgeber gemessen. Dazu wird Timer 2 und 4 der Einheit GPT1 verwendet. Die Einstellungen zu Timer 4 erfolgen analog zu Timer 2 (siehe oben). Die Funktion „increm_initialize“ bereitet die notwendigen Register vor, „increm_update“ aktualisiert die Geschwindigkeiten „v_outL“ und „v_outR“ des linken bzw. rechten Rades. Die Funktion muss regelmäßig aufgerufen werden (in diesem Fall jede Millisekunde) um einen Timerüberlauf zu verhindern. Aus Performance-Gründen wurde der Programm-Code in Assembler geschrieben:

 

Datei „increm_f.A66”:

;/*****************************************************************************/

;/* ROBY-RUN - SUPERROBOT                                                                                                 */

;/* MOTION UNIT: INCREMENTAL DECODER                                                                    */

;/*                                                                                                                                                    */

;/* (c) 2003 by Bernhard Putz                                                                                                        */

;/*****************************************************************************/

 

$NOMACRO

$SEGMENTED CASE MOD167

$MODINF (43)

NAME INCREM_F

 

; Used registers:

P3           DEFR  0FFC4H

DP3        DEFR  0FFC6H

P5           DEFR  0FFA2H

T4           DEFR  0FE44H

T2           DEFR  0FE40H

T4IC       DEFR  0FF64H

T2IC       DEFR  0FF60H

T4CON  DEFR  0FF44H

T2CON  DEFR  0FF40H

 

ASSUME  DPP3 : SYSTEM

 

; global variables:

EXTRN  DPP3 : v_outL : WORD

EXTRN  DPP3 : increm_counterL : WORD

EXTRN  DPP3 : v_outR : WORD

EXTRN  DPP3 : increm_counterR : WORD

               

REGDEF   R0 - R15

 

 

 

 

?PR?INCREM_F  SECTION  CODE WORD 'NCODE'

;/*****************************************************************************/

;/* INCREM_INITIALIZE                                                                                            */

;/* Initializes the Incremental Decoders for measuring velocities                                  */

;/*****************************************************************************/

increm_initialize  PROC  NEAR

PUBLIC  increm_initialize

 

;               increm_counterL = 0x8000;   // middle position

                MOV      R4,#32768

                MOV      WORD increm_counterL,R4

;               increm_counterR = 0x8000;   // middle position

                MOV      WORD increm_counterR,R4

 

;               // Set Ports for Input and 0

;               P3     &= 0xFF7F;  // P3.7 =  T2IN

                AND       P3,#65407

;               DP3    &= 0xFF7F;                // P3.7 =  T2IN as input

                AND       DP3,#65407

;               P5    &= 0x7FFF;  // P5.15 = T2EUD

                AND       P5,#32767

 

;               P3     &= 0xFFDF; // P3.5 =  T4IN;

                AND       P3,#65503

;               DP3    &= 0xFFDF;               // P3.5 =  T4IN as input

                AND       DP3,#65503

;               P5     &= 0xBFFF  // P5.14 = T4EUD

                AND       P5,#49151

 

;               // Set GPT 2 and 4 for Incremental Mode 

;               T2=0x8000;                           // Reset Timer values in middle position

                MOV      T2,#32768

;               T4=0x8000;                           // Reset Timer values in middle position

                MOV      T4,#32768

;               T2CON=0x0173;   // Incremental Mode

                MOV      T2CON,#371

;               T4CON=0x0173;   // Incremental Mode

                MOV      T4CON,#371

 

;               T2IC=0x0000;                       // Set Interrupt Control Register (no interrupts !)

                MOV      T2IC,#0

;               T4IC=0x0000;                       // Set Interrupt Control Register (no interrupts !)

                MOV      T4IC,#0

                RET

 

increm_initialize  ENDP

?PR?INCREM_F  ENDS

 

 

?PR?FASTCODE  SECTION  CODE WORD PUBLIC 'XRAM'

;/*****************************************************************************/

;/* INCREM_UPDATE                                                                                                                 */

;/* Stores incremental inputs to counter variables and updates v_outL/R                      */

;/*****************************************************************************/

increm_update  PROC  NEAR

PUBLIC  increm_update

 

; Save Timer values:

                ATOMIC               #2

                MOV      R9,T2

                MOV      R8,T4

 

;           // Fast Encoder to Velocity (E2V) calculation:

;               // E2V_MF =          GEAR_FACTOR * DIAMETER_WHEEL * PI /

;                                             ENCODER_RESOLUTION / CONTROL_INTERVAL * 1000 * 2^E2V_SF

;               #define E2V_MF              8595L                          // multiplication factor

;               #define E2V_SF              10                   // shift factor          

 

;               v_outL = (E2V_MF * (increm_counterL - t4)) >> E2V_SF;

;               Shift number in R3:

                MOV      R3,#10                                                                  

                MOV      R5,WORD increm_counterL

                SUB        R5,R8

                MOV      R4,#8595

                MUL      R5,R4

                MOV      R5,MDH

                MOV      R4,MDL

                MOV      R6,R5

                ASHR     R5,R3

                SHR        R4,R3

                NEG       R3

                SHL        R6,R3

                OR          R4,R6

                MOV      WORD v_outL,R4

 

;               v_outR = (E2V_MF * (increm_counterR - t2)) >> E2V_SF;

;               Shift number in R3:

                MOV      R3,#10                                                                  

                MOV      R5,WORD increm_counterR

                SUB        R5,R9

                MOV      R4,#8595

                MUL      R5,R4

                MOV      R5,MDH

                MOV      R4,MDL

                MOV      R6,R5

                ASHR     R5,R3

                SHR        R4,R3

                NEG       R3

                SHL        R6,R3

                OR          R4,R6

                MOV      WORD v_outR,R4

 

;               save last counter values

                MOV      WORD increm_counterL,R8

                MOV      WORD increm_counterR,R9

 

                RET

 

increm_update  ENDP

 

?PR?FASTCODE  ENDS

END

 

5. Anwendung und Tests:

Die Funktionalität der Enkoder Unit wurde anhand einer Motorsteuerung getestet. Im vorliegenden Testfall wurde die Drehzahl zweier über ein PWM Signal angesteuerte DC Motoren geregelt. Als Referenzwert dienten die Impulse der direkt an den DC Motoren angebrachten digitalen 2-Kanal Enkoder. Dieser Enkoder lieferte pro Umdrehung 512 Impule auf 2 Kanälen. Die im C167er implementierte Enkoder Unit ist in der Lage diesen Wert intern zu vervierfachen, wodurch sich 2048 Impulsen pro Umdrehung ergaben. Als Testboard wurde das von Gregor Novak und Christian Perschl entwickelte ub167 verwendet. Das ub167 ist eine komplette, kostengünstige Plattform für einfache und komplexe Aufgaben der Steuerungs-, Regelungs- und Messtechnik. Zur Plattform gehört neben der universellen Hardware auch das Softwarekonzept: vorkonfigurierte Musterprojekte, Softwaremodule in C-Source und das Tool Minimon für Download und Test. Das Gehirn von ub167 ist ein 16-Bit Mikrocontroller der Firma Infineon, der C167CR, welcher mit 20 MHz getaktet wird (10 MIPS Rechenleistung). Er enthält einen 10 Bit A/D Wandler mit 16 Kanälen und 9.7µs Wandlungszeit, eine leistungsfähige CAN Bus Schnittstelle, eine asynchrone und eine schnelle synchrone serielle Schnittstelle, eine 4-Kanal PWM Einheit, mehr als 70 freikonfigurierbare digitale Ein-/Ausgänge, 9 Timer und vieles mehr. All diese Peripherie ist in Silicon und kann ohne zusätzliche Hardware verwendet werden. Nähere Information und die Bezugsquelle des ub167 findet sich unter www.bluetechnix.at/ub167.

 

6. Literatur:

-          C167CR Derivatives User’s Manual v3.1, Infineon Technologies AG, 2000

-          XC161 User’s Manual v2.0 – Peripheral Units, Infineon Technologies AG, 2003

-          MC-Tools 17 – Arbeiten mit C166-Controllern, Karl-Heinz Mattheis / Steffen Storandt, 1995

-          Mikrocomputertechnik mit dem Controller C167, Günter Schmitt, 2000

-          Einsatz von Mikrocontrollern in der Robotertechnik, Christian Perschl, 2000