Sie sind auf Seite 1von 15

Teil A Klausur GTI 2018-09-19

Teil A Kennen und Techniken beherrschen:


1. Fragenteil (10 Punkte)
Geben Sie durch Ankreuzen von „ja“ oder „nein“ an, ob die Aussage zutrifft oder nicht
zutrifft. Begründungen sind nicht erforderlich.
Hinweis: Ein richtiges Kreuz bringt 1,0 Punkte, für ein falsches werden 0,5 Punkte
abgezogen. Es werden aber keine Minuspunkte aus Teilaufgaben "mitgenommen".
a) Welche Aussagen zur folgenden Funktion f 𝑥2, 𝑥1, 𝑥0 ∑ 𝑚 0,1,4,6,7 ist richtig:
Aussage Ja nein
𝑓 1,0,1 1  X
𝑓 𝑥2, 𝑥1, 𝑥0 𝑥2⨂𝑥1 𝑥1 ∙ 𝑥0 ist ebenfalls eine Darstellung
X 
der o.a. Funktion.

𝑓 𝑥2, 𝑥1, 𝑥0 𝑥2⨁𝑥1 𝑥2 ∙ 𝑥0) ist ebenfalls eine Darstellung


X 
der o.a. Funktion.

gti_2018_09_lsg_v3 Seite 1/15


Teil A Klausur GTI 2018-09-19

b) Der folgende Code in ANSI-C ist gegeben

bool fqs(uint8_t w, uint8_t *pqs)


{
static uint8_t qs_alt=0;
uint8_t anz=1;
uint16_t md=100;

for(anz=1;anz<4;++anz)
{
*pqs+= w/md;
w%=md;
md/=10;
}

qs_alt=(*pqs>qs_alt)?*pqs:qs_alt;
if ( *pqs==qs_alt)return true;
return false;
}
int main() {
uint8_t val[4] = {0,231,19,112};
uint8_t i, qs = 0;
bool result;
for (i = 0; i < 4; i++) {
result = fqs(val[i], &qs);
// (*)
}
// andere Programmaufgaben
}
Welche Aussagen hierzu sind richtig?
Aussage Ja nein
Die Funktion fqs berechnet mit jedem Aufruf in *pqs die Summe aus  X
dem aktuellen Wert von w und dem alten Wert von *pqs.
Wenn der neue Wert für *pqs gleich dem Ergebnis des letzten Aufrufs X 
ist, gibt die Funktion den Wert true zurück.
Der Wert von qs_alt kann maximal 19 erreichen.  X
Bei i=1 an der Stelle (*) hat qs den Wert 6. X 
Bei i=2 an der Stelle (*) hat result den Wert false.  X

Zu Frage
i) Die Funktion fqs berechnet mit jedem Aufruf in *pqs die Summe aus der
Quersumme von w und dem alten Wert von *pqs.
ii) qs_alt enthält immer den alten Wert von *pqs. Ändert sich dieser nicht, wird qs-alt
auch nicht geändert, und die Abfrage "if (*pqs==qs_alt) ist wahr. Also wird true
zurückgegeben.
iii) Da *pqs in der Funktion nicht initialisiert wird, kann der Wert bis 255 steigen.
iv) Bei i=1 wird val[1]=231 als w übergeben; die Quersumme von 231 ist 6.
v) Die Funktion gibt immer true zurück. Die Überlegung dazu ist ähnlich wie in ii)

gti_2018_09_lsg_v3 Seite 2/15


Teil A Klausur GTI 2018-09-19

c) Die folgende VHDL Entity ist gegeben:


library ieee;
use ieee.std_logic_1164.all;
entity coder is
port(X: in std_logic_vector(1 downto 0); -- 0,..,3 binary coded
Y: out std_logic_vector(2 downto 0);
end coder;
architecture klausur of coder is
begin
Y <= "110" when X = "01" else
"101" when X = "10" else
"011" when X = "00" else
"000";
end klausur;

Stellen Sie zuerst eine Funktionstabelle auf.

Aussage Ja nein
Die architecture beschreibt einen Codeumsetzer vom Dualcode in
einen einschrittigen Code.  X

Der Code hat ungerade Parität.  X

gti_2018_09_lsg_v3 Seite 3/15


Teil A Klausur GTI 2018-09-19

2. Techniken beherrschen (20 Punkte)


a) Die folgende Schaltung ist gegeben:

i. Geben Sie den Reset-Zustand an.


ii. Stellen Sie die zugehörige Schaltwerkstabelle auf für A = 0
iii. Welcher Festzustand wird bei A = 1 nach ein paar Takten erreicht?

i. Reset-Zustand: (Q2, Q1, Q0) = (1,1,1)


ii. Tabelle s.u.

Z Q0 Q1 Q2 A0 D0
0 1 1 1 0 0
1 0 1 1 0 1
2 1 0 1 0 0
3 0 1 0 0 0
4 0 0 1 0 1
5 1 0 0 0 1
6 1 1 0 0 1
7=0 1 1 1

iii. Endzustand nach spätestens 2 Zuständen 1,1,1: Da D0 dann 1 ist, schiebt sich die 1
in max 3 Zuständen zunächst in Q0, dann Q1, dann Q2.

gti_2018_09_lsg_v3 Seite 4/15


Teil A Klausur GTI 2018-09-19

b) Das folgende STD mit Ein- und Ausgabevektor für eine C-Umsetzung ist gegeben:

/* (a) input signal type */


typedef struct {
uint16_t x; // x
bool x2; // x
uint16_t xmin; // x
uint16_t xmax; // x
} InVector_STD_1809 ;
typedef InVector_STD_1809 *PtrInVector_STD_1809 ;
/* (b) output signal type */
typedef struct {
uint16_t y; // x
} OutVector_STD_1809;
typedef OutVector_STD_1809 *PtrOutVector_STD_1809;

bool fsm_STD_1809(
bool reset, // reset of fsm
PtrInVector_STD_1809 inV, // input signals
PtrOutVector_STD_1809 outV // output signals
);

gti_2018_09_lsg_v3 Seite 5/15


Teil A Klausur GTI 2018-09-19

i. Warum ist das STD nicht eindeutig? Markieren Sie die entsprechende Stelle im STD mit
einem '*' und geben Sie hier eine für Eindeutigkeit ausreichende Übergangsbedingung
an.

Bedingung für den mit * markierten Übergang: xmin<=x && x<=xmax


ii. Schreiben Sie die Funktion fsm_STD_1809 in C gemäß dem nun eindeutigen STD.
bool fsm_STD_1809(
bool reset, // reset of fsm
PtrInVector_STD_1809 inV, // input signals
PtrOutVector_STD_1809 outV // output signals
) {
static bool initialized = false;
static enum {Start, NewVal, Small, Normal, NEW_STATE, Wait}
state = Start;
if (reset) {
initialized = true;
state = Start;
}
else if (initialized) {
switch(state) { // find next state
case Start:
if (inv->x2) state = NewVal;
break;
case NewVal:
if (inv->x < inv->xmin) {
state = Small;
}
else if ((inv->xmin <= inv->x)
&& (inv->x <= inv->xmax)) {
state = Normal;
}
else { // else inv->x > inv->xmax
state = NEW_STATE;
}
break;
case Small: case Normal: case NEW_STATE:
if (!inv->x2) {
state = Wait;
}
break;
case Wait:
if (inv->x2) {
state = NewVal;
}
break;
} // end switch for next state
} // end if initialized
else return false; // nothing to do if not initialized
switch (state) { // output function
case Start: case NewVal: case NEW_STATE: case Wait:
outV->y = 0;
break;
case Small :

gti_2018_09_lsg_v3 Seite 6/15


Teil A Klausur GTI 2018-09-19

outV->y = xmin;
case Normal:
outV->y = x;
}
return (true);
}

gti_2018_09_lsg_v3 Seite 7/15


Teil B Klausur GTI 2018-09-19

Teil B: Anwenden und Analysieren


1. Programmierung technischer Systeme (15 Punkte)
An ein Mikrocomputersystem ist an den Ports PA, PB und PC ein 12-Bit-
Schadstoffsensor mit Vorheizung angeschlossen. Da das System autonom mit
Batterie laufen soll, soll nur alle 15 min eine Messung durchgeführt werden. Dazu
muss jeweils der Sensor 30'' vorgeheizt werden und anschließend wird der Wert
gelesen. In der (dann 14'30'' dauernden) Pause wird die Vorheizung ausgestellt.
Der Wert wird in einen Messwertepuffer geschrieben, der in einem anderen Teil der
Software von Zeit zu Zeit ausgelesen wird. Sie haben die Aufgabe, das Einlesen
und Abspeichern der Werte zu programmieren.
Die Ports des Mikrocomputers sind wie folgt mit dem Sensor verbunden:

Port B Port C
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
v7 v6 v5 v4 v3 v2 v1 v0 v11 v10 v9 v8
Sensorwert v mit den Bitstellen 11..0

Port A, Kanal 2: Vorheizungsanschluss, L-aktiv (0(1) schaltet Heizung ein (aus))

a) Schreiben Sie auf Basis der IO-Bibliothek (s. Anhang) eine Funktion
uint8_t readSensValue(DSCB bhdl, uint16_t *val)
zum sofortigen Lesen eines Sensorwerts (kein Vorheizen). Der Wert wird über
val zurückgegeben, der Ergebniscode des letzten IO-Aufrufs ist der
Rückgabewert. Bei einem IO-Fehler ist die Funktionsbearbeitung abzubrechen.
BYTE readSensValue(DSCB bhdl, uint16_t *val) {
BYTE valPB, valPC, ioresult;
if ((ioresult=InputByte(bhdl, PB, &valPB))!= IO_OK)
return ioresult;
if ((ioresult=InputByte(bhdl, PC, &valPC))!= IO_OK)
return ioresult;
*val = (((uint16_t) valPC &0xf0 ) <<4) | valPB ;
// 16-Bit-Wert bilden
// |Bit 7..4 von valPC nehmen |
// |links nach Pos.11..8 verschieben|
// |valPB in 7..0 einfügen |
return IO_OK;
}

gti_2018_09_lsg_v3 Seite 8/15


Teil B Klausur GTI 2018-09-19

b) Schreiben Sie auf Basis der IO-Bibliothek eine Funktion


uint8_t vorheizAnAus(DSCB bhdl, uint8_t *valPA,
bool vorheizenAn)
zum sofortigen Einschalten (vorheizenAn==true) oder Ausschalten
(vorheizenAn==false) der Vorheizung. Dabei darf der Wert der anderen
Portkanäle von PA nicht überschrieben werden. Der neue Wert von PA (also mit
geändertem Kanal 2) ist über *valPA zurückzugeben, der Funktionsrückgabewert
ist der Ergebniscode der IO-Funktion.

uint8_t vorheizAnAus(DSCB bhdl, uint8_t *valPA,


bool vorheizenAn) {
uint8_t ioResult;
if (vorheizenAn) { // K2 ist zu loeschen, da 0 die Vorheizung
einschaltet (0-aktiv)
*valPA = *valPA & ~(1<<2);
}
else { // K2 ist zu setzen
*valPA = *valPA | (1<<2);
}
ioResult = OutputByte(bhdl, PA, *valPA);
return ioResult;
}

gti_2018_09_lsg_v3 Seite 9/15


Teil B Klausur GTI 2018-09-19

c) Die Steuerungsfunktion für den Sensor ist die Schnittstelle zum Rest der
Software. Sie wird wie eine Automatenfunktion zyklisch immer wieder aufgerufen
und arbeitet auf der Basis eines intern gehaltenen Zeitstempels wie folgt:
a. Ist seit der letzten Messung 14'30'' vergangen, wird die Heizung
angestellt. Die Funktion merkt sich, dass sie im Zustand Vorheizen ist,
und gibt über den Parameter status eine 1 zurück.
b. Wird sie im Zustand Vorheizen aufgerufen und ist die Zeit für das
Vorheizen (30'') abgelaufen, führt sie die Messung aus, speichert den
Wert im Messwertespeicher values an Stelle (Index) ix, schaltet die
Vorheizung wieder aus, startet eine neue Zeitnahme für den nächsten
Messvorgang und gibt über den Parameter status eine 2 zurück.
c. Wird die Funktion in den Wartezeiten aufgerufen, führt sie keine Aktion
durch und gibt den Statuswert 0 zurück.
d. Der Rückgabewert ist im Fall a) und b) der Ergebniscode der DIO-
Funktion und bei c) 0.
Schreiben sie die Funktion mit folgender Schnittstelle:

uint8_t ctrlSensor(DSCB bhdl, uint16_t values[], uint16_t ix,


uint8_t *status, uint8_t *valPA) {
uint8_t ctrlSensor(DSCB bhdl, uint16_t values[], uint16_t ix,
uint8_t *status, uint8_t *valPA) {
typedef enum {Aus, Vorheizen} TState;
static TState cstate=Aus;
static clock_t lastClk = 0;
clock_t now;
uint8_t ioResult;
switch(state) {
case Aus:
now=clock();
if ((lastClk == 0) // start
|| (now-lastClk >= (14*60+30)*CLK_PER_SEC)){
// 14'30'' abgelaufen
// Vorheizung anschalten, *status auf 1 setzen,
// Zeitstempel setzen, cstate aendern
ioResult=vorheizAnAus(bhdl, true);
lastClk = now;
*status=1;
cstate = Vorheizen;
return ioResult;
}
else { // weiter auf naechste Messung warten
*status = 0;
return 0;
}
break;
case Vorheizen:
now = clock();
if (now - lastClk >= 30*CLK_PER_SEC) {
// Vorheizen beendet, nun messen und ausschalten
ioResult=readSensValue(bhdl, &values[ix]);
// Sensorwert direkt in gewuenschten Platz einlesen

gti_2018_09_lsg_v3 Seite 10/15


Teil B Klausur GTI 2018-09-19

ioResult=vorheizAnAus(bhdl, false);
// Heizung wieder ausschalten
*status = 2;
// Statuswert 2 setzen
lastClk = now;
// Zeitstempel setzen
cstate = Aus;
// nun ist wieder aus
return ioResult;
}
else { // weiter auf Vorheiz-Ende warten
*status = 0;
return 0;
}
}
}

gti_2018_09_lsg_v3 Seite 11/15


Teil B Klausur GTI 2018-09-19

2. Modellierung eines Automaten (15 Punkte)


Sie sollen einen Automaten entwerfen, der die Tür eines Lagerbereichs steuert. Dazu ist ein
Motorantrieb eingebaut, der die Tür öffnen und schließen kann. In beiden Richtungen stehen je
eine langsame und eine schnelle Geschwindigkeit zur Verfügung. Zur Steuerung stehen die
Sensoren TG (Tür geschlossen), TO (Tür offen), ELG (Endschalter langsame Fahrt Schliessen)
sowie ELO (Endschalter langsame Fahrt Öffnen) zur Verfügung.
Die jeweilige Fahrt (Öffnen bzw. Schliessen) soll ab dem jeweiligen Endschalter ELO bzw. ELG
bis zum Erreichen des offenen bzw. geschlossenen Zustands auf langsame Geschwindigkeit
reduziert werden.
Bei Auslösen des Blockadesensors beim Schließvorgang soll die Tür sofort gestoppt werden.

Die zu verarbeitenden/erzeugenden Signale sind in der folgenden Tabelle zusammengefasst:


Signalname Typ Richtung1 Erläuterungen/Bemerkungen
TTO bool In Taster Anforderung Tür öffnen
TTS bool In Taster Anforderung Tür schließen
BT bool In Blockadesensor Tür
TO bool In Endschalter Tür geöffnet
TG bool In Endschalter Tür geschlossen
ELG bool In Endschalter langsame Geschwindigkeit Schließen
ELO bool In Endschalter langsame Geschwindigkeit Öffnen
MGS byte Out Motordrehbewegung Geschwindigkeit Schließen (langsam: 50,
schnell:255)
MGO byte Out Motordrehbewegung Geschwindigkeit Öffnen (langsam: 50,
schnell: 255)
MAn bool Out Motor an

1
Aus Sicht der Steuerung

gti_2018_09_lsg_v3 Seite 12/15


Teil B Klausur GTI 2018-09-19

Die Anforderungen an den Automaten sind in den folgenden Punkten (Requirements R1,..,R7)
zusammengefasst:
R1) Nach dem Einschalten soll die Tür geöffnet werden, wenn sie nicht bereits vollständig
geöffnet ist.
R2) Durch Betätigung des jeweiligen Tasters soll die Tür geöffnet (geschlossen) werden.
R3) Während der Bewegung soll die Tür durch Betätigen eines beliebigen Tasters
angehalten werden.
R4) Nach einem Halt durch einen Taster soll die Tür nach erneutem Betätigen eines
beliebigen Tasters in die damit angeforderte Richtung wieder gestartet werden.
R5) Bei Erreichen der jeweiligen Endschalter für langsame Fahrt soll die Tür mit
entsprechend verringerter Geschwindigkeit bis zum Erreichen des offenen
(geschlossenen) Zustands weiterfahren.
R6) Bei Fahrt mit geringer Geschwindigkeit darf kein Anhalten über einen Taster mehr
erfolgen.
R7) Wird während des Schließvorgangs der Blockadesensor ausgelöst, so soll die Tür
angehalten werden.
R8) Nach dem Halt durch den Bockadesensor soll die Tür nur durch Betätigen des Tasters
für die Öffnung geöffnet werden können. Ein weiteres Schließen soll nicht möglich sein.
Beschreiben Sie das gewünschte Verhalten mit einem Zustands-Übergangsdiagramm unter
Verwendung der o.g. Ein- und Ausgabesignale des Automaten.

gti_2018_09_lsg_v3 Seite 13/15


Teil B Klausur GTI 2018-09-19

gti_2018_09_lsg_v3 Seite 14/15


Anhang E/A-Schnittstelle

Anhang
C-Vorgaben
Die folgenden Typen sind für alle C-Aufgaben bereits definiert:
Typname Bedeutung Typname Bedeutung
uint8_t Positive Zahl, 8 Bit int8_t Ganze Zahl, 8 Bit
BYTE
uint16_t Positive Zahl, 16 Bit int16_t Ganze Zahl, 16 Bit
uint32_t Positive Zahl, 32 Bit int32_t Ganze Zahl, 32 Bit
BOOL Aufzählungstyp mit Werten FALSE = 0 und TRUE = 1

Die Treiberbibliothek DIO (Digital Input/Output) stellt die folgenden Vereinbarungen und
Portzugriffsfunktionen zur Verfügung:
typedef enum {PA=0,PB,PC} PORT;
typedef enum {K0=0,K1,K2,K3,K4,K5,K6,K7} CHANNEL;
Digitale Eingabe:
BYTE InputByte (DSCB BoardHandle, PORT PortName, BYTE* ReadValue)
Eingabe: PortName  {PA, PB, PC}
Ausgaben: *ReadValue = gelesenes Byte, Returnwert <> 0: Fehler
Digitale Ausgabe:
BYTE OutputByte(DSCB BoardHandle, PORT PortName, BYTE WriteValue)
Eingaben: PortName  {PA, PB, PC}, WriteValue = auszugebendes Byte
Ausgabe: Returnwert <> 0: Fehler

Die folgenden Konstanten und Funktionen stehen zur Zeiterfassung basierend auf dem
ganzzahligen Typ clock_t zur Verfügung:
clock_t CLK_PER_SEC; // Anzahl der Clock-Werte (Ticks) pro Sekunde
clock_t clock(); // Abfrage der Clock; Ergebnis in Ticks

Die folgenden Funktionen stehen für dynamischen Speicher zur Verfügung:


// size Byte reservieren, nicht init.
void *malloc(uint32_t size)
// Feld mit bs Elementen, je bk Byte (also bs*bk Byte)
void *calloc(uint32_t bs, uint32_t bk)

gti_2018_09_lsg_v3 Seite 15/15