Übungen zu Systemnahe Programmierung in C (SPiC) Wintersemester 2017/18

Ähnliche Dokumente
Übungen zu Grundlagen der systemnahen Programmierung in C (GSPiC) im Wintersemester 2017/18

Übungen zu Systemnahe Programmierung in C (SPiC) Wintersemester 2018/19

Übungen zu Systemnahe Programmierung in C (SPiC)

Inhalt. Übungen zu Systemnahe Programmierung in C (SPiC) Schnittstellenbeschreibung. Inhalt

Sebastian Maier (Lehrstuhl Informatik 4) Übung 4. Sommersemester 2017

Inhalt. Übungen zu Systemnahe Programmierung in C (SPiC) Inhalt. Globale Variablen

Inhalt. Aufgabe 4: LED-Modul Hinweise Testen des Moduls Sommersemester 2015

Übungen zu Systemnahe Programmierung in C (SPiC)

Wiederholung: Zugriff auf AVR-Prozessor-Register. Aufgabe 3: 7seg-Modul der SPiCboard-Bibliothek

Inhalt. Übungen zu Systemnahe Programmierung in C (SPiC) Inhalt

U3-1 Register beim AVR-μC. U3 3. Übung. U3-2 I/O-Ports des AVR-μC. 1 Überblick. 2 Makros für Register-Zugriffe. 1 Überblick

Wiederholung: Zugriff auf AVR-Prozessor-Register. Aufgabe 3: 7seg-Modul der SPiCboard-Bibliothek

Wiederholung: Zugriff auf AVR-Prozessor-Register

Übungen zu Grundlagen der systemnahen Programmierung in C (GSPiC) im Sommersemester 2018

U2-1 Register beim AVR- C. U2-2 I/O-Ports des AVR- C. 1 Überblick. 2 Makros für Register-Zugriffe. 1 Überblick

Systemnahe Programmierung in C (SPiC)

U3 3. Übung U3 3. Übung. Systemnahe Programmierung in C Übungen Moritz Strübe Universität Erlangen-Nürnberg Informatik 4, 2009 U3.fm

Besprechung Aufgabe 1. Pointer. Register und Ports. SPiC - Ü U3.1

Systemnahe Programmierung in C Übungen Moritz Strübe, Michael Stilkerich Universität Erlangen-Nürnberg Informatik 4, 2010 U2.fm

Globale Variablen Diverses. Globale Variablen. Globale Variablen

Zeiger vom Typ (void *) sind am besten für Zeigerarithmetik geeignet, da sie kompatibel zu jedem Zeigertyp sind.

Programmierung mit C Zeiger

IR NEC Empfänger mit 4x7 LED Anzeige (ATtiny2313)

Grundlagen der Systemnahen Programmierung in C (GSPiC)

Serielle Schnittstelle, erstes Testprogramm (a)

Praxis der Programmierung

Inhalt. Übungen zu Systemnahe Programmierung in C (SPiC) Inhalt. Tafelübungen. Organisatorisches. Entwicklungsumgebung

Makros sind Textersetzungen, welche vom Präprozessor aufgelöst werden. Dies Passiert bevor der Compiler die Datein verarbeitet.

Einführung in die Programmiersprache C

Einführung in die Programmiersprache C

Einführung in die Programmiersprache C

Speicherklassen (1) Lokale Variablen

Hinweise C-Programmierung

Einführung in die Programmiersprache C

Einführung Sprachfeatures Hinweise, Tipps und Styleguide Informationen. Einführung in C. Patrick Schulz

C++ Klassen, Vererbung. Philipp Lucas. Sebastian Hack. Wintersemester 2008/09. saarland.

Inhalt. Übungen zu Systemnahe Programmierung in C (SPiC) Tafelübungen. Inhalt. Organisatorisches. Entwicklungsumgebung

Übungen zu Systemnahe Programmierung in C (SPiC)

C.1 Serielle Schnittstelle, erstes Testprogramm (a)

Inhalt. 4.9 Typen, Variable und Konstante

Grundlagen der Informatik 2 Modul Systemnahe Programmierung in C (SPiC) Klausur am 25. Juli 2008

4 Formelsammlung C/C++

Programmierung mit C Modularisierung von Programmen. Präprozessor-Anweisungen nutzen.

Erste Schritte der Programmierung in C

U4 Grundlagen der C-Programmierung

Repetitorium Informatik (Java)

Die UART-Schnittstelle

U5-2 Register beim AVR-µC

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf Seite 1 von 29

Herzlich willkommen!

Tag 7 Repetitorium Informatik (Java)

Laborübung aus Systemnahe Programmierung

Programmierung und Angewandte Mathematik

C++ - Einführung in die Programmiersprache Header-Dateien und Funktionen. Leibniz Universität IT Services Anja Aue

Systempraktikum im Wintersemester 2009/2010 (LMU): Vorlesung vom Foliensatz 2

Crashkurs C++ Wiederholung

myavr Programmierung in C

Propädeutikum. Dipl.-Inf. Frank Güttler

7. Übung Informatik II - Objektorientierte Programmierung

Vorkurs Informatik: Erste Schritte der Programmierung mit C++

f) Was versteht man beim Zugriff auf I/O-Register unter dem Begriff "Memory-mapped"?

Implementieren von Klassen

Algorithmen und Datenstrukturen

C++ Teil 5. Sven Groß. 12. Nov IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil Nov / 16

Inhalt. 1 Einstieg in die Welt von C Erste Schritte in C 31. Vorwort... 15

Programmierung in C: Vermischtes (Teil 1)

Programmierkurs C++ Kapitel 6 Module Seite 1

Prozeduren vs. Funktionen

Programmiertechnik. Teil 4. C++ Funktionen: Prototypen Overloading Parameter. C++ Funktionen: Eigenschaften

Modul Entscheidungsunterstützung in der Logistik. Einführung in die Programmierung mit C++ Übung 4

Zeiger vom Typ void* benötigen weniger Speicher als andere Zeiger, da bei anderen Zeigertypen zusätzlich die Größe gespeichert werden muss.

Datentypen mit fester Größe. Bitoperatoren. Funktionen. Nachtrag Compiler. Aufgabe 2. SPiC - Ü U2.1

Repetitorium Programmieren I + II

Inhalt. Übungen zu Systemnahe Programmierung in C (SPiC) Implementierung von Interruptbehandlungen. Interrupts

GdI2 - Systemnahe Programmierung in C Übungen Jürgen Kleinöder Universität Erlangen-Nürnberg Informatik 4, 2006 U4.fm

Übungen zu Systemnahe Programmierung in C (SPiC) Wintersemester 2017/18

Grundlagen der Informatik 2 Modul Systemnahe Programmierung in C (SPiC) Klausur am 9. April 2008

Tag 8 Repetitorium Informatik (Java)

Einführung in die Programmierung Wintersemester 2016/17

Friedrich-Alexander-Universität Erlangen-Nürnberg

Kapitel 9. Programmierkurs. Attribute von Klassen, Methoden und Variablen. 9.1 Attribute von Klassen, Methoden und Variablen

8. Referenzen und Zeiger

Einführung in die Programmierung

C-Crashkurs. Praktikum Systemmanagement und Sicherheit

Java Einführung Methoden. Kapitel 6

C++ - Objektorientierte Programmierung Konstante und statische Elemente

Überblick: Teil C Systemnahe Softwareentwicklung

Kapitel 5: Interfaces

Tag 4 Repetitorium Informatik (Java)

b) Was bewirken folgende Programmanweisungen? uint8_t x = 42; x ^= x;

Programmübersetzung & modulare Programme INE2 M. Thaler, Office TG208

Serielle Schnittstelle

Transkript:

Übungen zu Systemnahe Programmierung in C (SPiC) Wintersemester 2017/18 Übung 3 Benedict Herzog Sebastian Maier Lehrstuhl für Informatik 4 Friedrich-Alexander-Universität Erlangen-Nürnberg Lehrstuhl für Verteilte Systeme und Betriebssysteme

Beliebte Fehler

Sichtbarkeit & Lebensdauer Sichtbarkeit nicht und Lebensdauer static static lokale Variable Sb Block Sb Block Ld Block Ld Programm globale Variable Sb Programm Sb Modul Ld Programm Ld Programm Funktion Sb Programm Sb Modul Lokale Variable, nicht static = auto Variable automatisch allokiert & freigegeben Funktionen als static, wenn kein Export notwendig 1

Globale Variablen 01 static uint8_t state; // global static 02 uint8_t event_counter; // global 03 04 void main(void) { 05... 06 } 07 08 static void f(uint8_t a) { 09 static uint8_t call_counter = 0; // local static 10 uint8_t num_leds; // local (auto) 11... 12 } Sichtbarkeit/Gültigkeit möglichst weit einschränken Globale Variable lokale Variable in f() Globale static Variablen: Sichtbarkeit auf Modul beschränken wo möglich, static für Funktionen und Variablen verwenden 2

Verwendung falscher Datentypen Die Größe von int ist in C nicht genau definiert zum Beispiel beim ATmega328PB: 16 bit Gerade auf µc führt dies zu Fehlern und/oder langsameren Code Für die Übung: Verwendung von int ist ein Fehler Stattdessen: Verwendung der in der stdint.h definierten Typen: int8_t, uint8_t, int16_t, uint16_t, etc. Wertebereich: limits.h: INT8_MAX, INT8_MIN,... Speicherplatz ist sehr teuer auf µc Nur so viel Speicher verwenden, wie tatsächlich benötigt wird! 3

Typedefs & Enums 01 #define PB3 3 02 typedef enum { BUTTON0 = 4, BUTTON1 = 8 } BUTTON; 03 #define MAX_COUNTER 900 04... 05 void main(void) { 06... 07 PORTB = (1 << PB3); // nicht (1 << 3) 08... 09 BUTTONSTATE old, new; // nicht uint8_t old, new; 10... 11 // Deklaration: BUTTONSTATE sb_button_getstate(button btn); 12 old = sb_button_getstate(button0);//nicht sb_button_getstate(4) 13... 14 } Vordefinierte Typen verwenden Explizite Zahlenwerte nur verwenden, wenn notwendig 4

Module

Ablauf vom Quellcode zum laufenden Programm test.c com.c gcc gcc test.o com.o ld aufgabe3.elf libspicboard com.h adc.h led.h libspicboard.a 7seg.o timer.o adc.o button.o led.o 1. Präprozessor 2. Compiler 3. Linker 4. Programmer/Flasher 5

Schnittstellenbeschreibung Header Dateien enthalten die Schnittstelle eines Moduls Funktionsdeklarationen Präprozessormakros Typdefinitionen Header Dateien können u.u. mehrmals eingebunden werden led.h bindet avr/io.h ein button.h bindet avr/io.h ein Funktionen aus avr/io.h mehrmals deklariert Mehrfachinkludierung/Zyklen vermeiden Include-Guards Definition und Abfrage eines Präprozessormakros Konvention: Makro hat den Namen der.h-datei,. ersetzt durch _ Inhalt nur einbinden, wenn das Makro noch nicht definiert ist Vorsicht: flacher Namensraum möglichst eindeutige Namen 6

Schnittstellenbeschreibung Erstellen einer.h-datei (Konvention: gleicher Name wie.c-datei) 01 #ifndef COM_H 02 #define COM_H 03 /* fixed-width Datentypen einbinden (im Header verwendet) */ 04 #include <stdint.h> 05 06 /* Datentypen */ 07 typedef enum { 08 ERROR_NO_STOP_BIT, ERROR_PARITY, 09 ERROR_BUFFER_FULL, ERROR_INVALID_POINTER 10 } COM_ERROR_STATUS; 11 12 /* Funktionen */ 13 void sb_com_sendbyte(uint8_t data); 14... 15 #endif //COM_H 7

Initialisierung eines Moduls Module müssen Initialisierung durchführen zum Beispiel Portkonfiguration Java: mit Klassenkonstruktoren möglich C: kennt kein solches Konzept Workaround: Modul muss bei erstem Aufruf einer seiner Funktionen ggf. die Initialisierung durchführen muss sich merken, ob die Initialisierung schon erfolgt ist Mehrfachinitialisierung vermeiden Anlegen einer Init-Variable Aufruf der Init-Funktion bei jedem Funktionsaufruf Init-Variable anfangs 0 Nach der Initialisierung auf 1 setzen 8

Initialisierung eines Moduls initdone ist initial 0 wird nach der Initialisierung auf 1 gesetzt Initialisierung wird nur ein mal durchgeführt 01 static void init(void){ 02 static uint8_t initdone = 0; 03 if (initdone == 0) { 04 initdone = 1; 05... 06 } 07 } 08 09 void mod_func(void) { 10 init(); 11... 9

Zeiger & Felder

Wiederholung: Zeiger Variable: uint8_t x Zeiger: uint8_t *y Adressoperator: &x Verweisoperator: *y 01 uint8_t a = 23; 02 uint8_t b = 42; 03 uint8_t * p = &a; 04 *p = 66; 05 p = &b; 06 *p = 2; 07 uint8_t c = *p; 0x10 0x11 0x12 0x13 0x14 0x15 Achtung: ATmega328PB hat 8-bit Register und 16-bit Adressen 10

Wiederholung: Zeiger Variable: uint8_t x Zeiger: uint8_t *y Adressoperator: &x Verweisoperator: *y 01 uint8_t a = 23; 02 uint8_t b = 42; 03 uint8_t * p = &a; 04 *p = 66; 05 p = &b; 06 *p = 2; 07 uint8_t c = *p; 0x10 a 23 0x11 0x12 0x13 0x14 0x15 Achtung: ATmega328PB hat 8-bit Register und 16-bit Adressen 10

Wiederholung: Zeiger Variable: uint8_t x Zeiger: uint8_t *y Adressoperator: &x Verweisoperator: *y 01 uint8_t a = 23; 02 uint8_t b = 42; 03 uint8_t * p = &a; 04 *p = 66; 05 p = &b; 06 *p = 2; 07 uint8_t c = *p; 0x10 a 23 0x11 b 42 0x12 0x13 0x14 0x15 Achtung: ATmega328PB hat 8-bit Register und 16-bit Adressen 10

Wiederholung: Zeiger Variable: uint8_t x Zeiger: uint8_t *y Adressoperator: &x Verweisoperator: *y 01 uint8_t a = 23; 02 uint8_t b = 42; 03 uint8_t * p = &a; 04 *p = 66; 05 p = &b; 06 *p = 2; 07 uint8_t c = *p; 0x10 a 23 0x11 b 42 0x12 p 0x11 0x13 0x14 0x15 Achtung: ATmega328PB hat 8-bit Register und 16-bit Adressen 10

Wiederholung: Zeiger Variable: uint8_t x Zeiger: uint8_t *y Adressoperator: &x Verweisoperator: *y 01 uint8_t a = 23; 02 uint8_t b = 42; 03 uint8_t * p = &a; 04 *p = 66; 05 p = &b; 06 *p = 2; 07 uint8_t c = *p; 0x10 a 66 0x11 b 42 0x12 p 0x11 0x13 0x14 0x15 Achtung: ATmega328PB hat 8-bit Register und 16-bit Adressen 10

Wiederholung: Zeiger Variable: uint8_t x Zeiger: uint8_t *y Adressoperator: &x Verweisoperator: *y 01 uint8_t a = 23; 02 uint8_t b = 42; 03 uint8_t * p = &a; 04 *p = 66; 05 p = &b; 06 *p = 2; 07 uint8_t c = *p; 0x10 a 66 0x11 b 42 0x12 p 0x12 0x13 0x14 0x15 Achtung: ATmega328PB hat 8-bit Register und 16-bit Adressen 10

Wiederholung: Zeiger Variable: uint8_t x Zeiger: uint8_t *y Adressoperator: &x Verweisoperator: *y 01 uint8_t a = 23; 02 uint8_t b = 42; 03 uint8_t * p = &a; 04 *p = 66; 05 p = &b; 06 *p = 2; 07 uint8_t c = *p; 0x10 a 66 0x11 b 2 0x12 p 0x12 0x13 0x14 0x15 Achtung: ATmega328PB hat 8-bit Register und 16-bit Adressen 10

Wiederholung: Zeiger Variable: uint8_t x Zeiger: uint8_t *y Adressoperator: &x Verweisoperator: *y 01 uint8_t a = 23; 02 uint8_t b = 42; 03 uint8_t * p = &a; 04 *p = 66; 05 p = &b; 06 *p = 2; 07 uint8_t c = *p; 0x10 a 66 0x11 b 2 0x12 p 0x12 0x13 c 2 0x14 0x15 Achtung: ATmega328PB hat 8-bit Register und 16-bit Adressen 10

Wiederholung: Felder Konstanter Zeiger: uint8_t a[] Variabler Zeiger: uint8_t *b Aktuelle Element: *b x-te Element: b[x] x-te Element: *(b+x) 0x10 01 uint8_t a[] = {2,4,8,16}; 02 uint8_t *b = a; 03 uint8_t c = a[0]; 04 c = *b; 05 b = b+1; 06 c = *b; 07 c = a[7]; 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 11

Wiederholung: Felder Konstanter Zeiger: uint8_t a[] Variabler Zeiger: uint8_t *b Aktuelle Element: *b x-te Element: b[x] x-te Element: *(b+x) 01 uint8_t a[] = {2,4,8,16}; 02 uint8_t *b = a; 03 uint8_t c = a[0]; 04 c = *b; 05 b = b+1; 06 c = *b; 07 c = a[7]; 0x10 2 0x11 4 0x12 8 0x13 16 0x14 a 0x11 0x15 0x16 0x17 0x18 11

Wiederholung: Felder Konstanter Zeiger: uint8_t a[] Variabler Zeiger: uint8_t *b Aktuelle Element: *b x-te Element: b[x] x-te Element: *(b+x) 01 uint8_t a[] = {2,4,8,16}; 02 uint8_t *b = a; 03 uint8_t c = a[0]; 04 c = *b; 05 b = b+1; 06 c = *b; 07 c = a[7]; 0x10 2 0x11 4 0x12 8 0x13 16 0x14 a 0x11 0x15 b 0x11 0x16 0x17 0x18 11

Wiederholung: Felder Konstanter Zeiger: uint8_t a[] Variabler Zeiger: uint8_t *b Aktuelle Element: *b x-te Element: b[x] x-te Element: *(b+x) 01 uint8_t a[] = {2,4,8,16}; 02 uint8_t *b = a; 03 uint8_t c = a[0]; 04 c = *b; 05 b = b+1; 06 c = *b; 07 c = a[7]; 0x10 2 0x11 4 0x12 8 0x13 16 0x14 a 0x11 0x15 b 0x11 0x16 c 2 0x17 0x18 11

Wiederholung: Felder Konstanter Zeiger: uint8_t a[] Variabler Zeiger: uint8_t *b Aktuelle Element: *b x-te Element: b[x] x-te Element: *(b+x) 01 uint8_t a[] = {2,4,8,16}; 02 uint8_t *b = a; 03 uint8_t c = a[0]; 04 c = *b; 05 b = b+1; 06 c = *b; 07 c = a[7]; 0x10 2 0x11 4 0x12 8 0x13 16 0x14 a 0x11 0x15 b 0x11 0x16 c 2 0x17 0x18 11

Wiederholung: Felder Konstanter Zeiger: uint8_t a[] Variabler Zeiger: uint8_t *b Aktuelle Element: *b x-te Element: b[x] x-te Element: *(b+x) 01 uint8_t a[] = {2,4,8,16}; 02 uint8_t *b = a; 03 uint8_t c = a[0]; 04 c = *b; 05 b = b+1; 06 c = *b; 07 c = a[7]; 0x10 2 0x11 4 0x12 8 0x13 16 0x14 a 0x11 0x15 b 0x12 0x16 c 2 0x17 0x18 11

Wiederholung: Felder Konstanter Zeiger: uint8_t a[] Variabler Zeiger: uint8_t *b Aktuelle Element: *b x-te Element: b[x] x-te Element: *(b+x) 01 uint8_t a[] = {2,4,8,16}; 02 uint8_t *b = a; 03 uint8_t c = a[0]; 04 c = *b; 05 b = b+1; 06 c = *b; 07 c = a[7]; 0x10 2 0x11 4 0x12 8 0x13 16 0x14 a 0x11 0x15 b 0x12 0x16 c 4 0x17 0x18 11

Wiederholung: Felder Konstanter Zeiger: uint8_t a[] Variabler Zeiger: uint8_t *b Aktuelle Element: *b x-te Element: b[x] x-te Element: *(b+x) 01 uint8_t a[] = {2,4,8,16}; 02 uint8_t *b = a; 03 uint8_t c = a[0]; 04 c = *b; 05 b = b+1; 06 c = *b; 07 c = a[7]; // 0x10 2 0x11 4 0x12 8 0x13 16 0x14 a 0x11 0x15 b 0x12 0x16 c??? 0x17 0x18 11

const uint8_t* vs. uint8_t* const const uint8_t* ein Pointer auf einen uint8_t-wert, der konstant ist Wert nicht über den Pointer veränderbar uint8_t* const ein konstanter Pointer auf einen (beliebigen) uint8_t-wert Pointer darf nicht mehr auf eine andere Speicheradresse zeigen 12

Kommunikation

SPiCboard verbinden PD1 Ausgang (TX) wird mit RX des Kommunikationspartners verbunden PD0 Eingang (RX) analog mit Ausgang (TX) verbinden GND wird mit GND verbunden 14

Voraussetzungen für den Datenaustausch gleiches Protokoll wir nehmen 8-E-1 8 Anzahl der Datenbits E gerades (even) Paritätsbit 1 Stopbit sowie (implizit) ein Startbit das Datenbit mit dem niedrigsten Stellenwert wird zuerst übertragen (aufsteigend) hoher Pegel entspricht einer logischen 1, niedriger Pegel einer 0 gleiche Geschwindigkeit, bei uns 1200 Bd (1 Baud entspricht ein Symbol pro Sekunde) 15

Beispiel high low t 16

Beispiel high low t 16

Beispiel 1 0 1 1 1 0 1 0 0 0 0 1 1 high low t 16

Beispiel 1 0 1 1 1 0 1 0 0 0 0 1 1 high low Start Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Parität Stop t 16

Beispiel 1 0 1 1 1 0 1 0 0 0 0 1 1 high low Start Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Parität Stop t Datenbits 16

Beispiel 1 0 1 1 1 0 1 0 0 0 0 1 1 high low Start Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Parität Stop t Datenbits Empfangenes Byte (rückwärts gelesen): 00010111 2 = 0x17 = 23 16

Beispiel 1 0 1 1 1 0 1 0 0 0 0 1 1 high low Start Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Parität Stop t Datenbits Empfangenes Byte (rückwärts gelesen): 00010111 2 = 0x17 = 23 Parität 0 (da Datenbits vier 1er gerade Anzahl) 16

Beispiel 1 0 1 1 1 0 1 0 0 0 0 1 1 high low Start Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Parität Stop t Datenbits Empfangenes Byte (rückwärts gelesen): 00010111 2 = 0x17 = 23 Parität 0 (da Datenbits vier 1er gerade Anzahl) Startbit immer 0 und Stopbit immer 1 16

Abtastung high low Start Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Parität Stop t Die Fenstergröße T ist uns bekannt 17

Abtastung high low Start Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Parität Stop t Die Fenstergröße T ist uns bekannt 17

Abtastung high T low Start Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Parität Stop t Die Fenstergröße T ist uns bekannt Anfang ist einen Pegelwechsel von hoch auf niedrig 17

Abtastung high 1.5 T low Start Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Parität Stop t Die Fenstergröße T ist uns bekannt Anfang ist einen Pegelwechsel von hoch auf niedrig 17

Abtastung high 1.5 T T low Start Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Parität Stop t Die Fenstergröße T ist uns bekannt Anfang ist einen Pegelwechsel von hoch auf niedrig warte danach 1.5 T für ein eindeutiges Symbol 17

Abtastung high 1.5 T T low Start Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7 Parität Stop t Die Fenstergröße T ist uns bekannt Anfang ist einen Pegelwechsel von hoch auf niedrig warte danach 1.5 T für ein eindeutiges Symbol für jedes weitere Symbol wieder alle T abtasten 17

Aufgabe: Eigenes Kommunikationsmodule

COM-Modul Aufgabe COM-Modul der SPiCboard-Bibliothek selbst implementieren Gleiches Verhalten wie das Original Beschreibung in der Doku auf der Webseite: http://www4.cs.fau.de/lehre/ws17/v_spic/uebung/doc 01 void sb_com_sendbyte(uint8_t data); 02 void sb_com_senddoublebyte(uint16_t data); 03 void sb_com_sendarray(uint8_t *data, size_t len); 04 05 uint8_t sb_com_receivebyte(uint8_t data); 06 uint8_t sb_com_receivedoublebyte(uint16_t data); 07 uint8_t sb_com_receivearray(uint8_t *data, size_t len); 08 09 uint8_t sb_com_bytereadyforreceive(); 18

COM-Modul Aufgabe Hilfsfunktionen zum Setzen/Auslesen der Register gegeben Setzen des Pegels für das Senderegister TX Auslesen des Pegels für das Empfangsregister RX Hilfsfunktionen gehören nicht zur Schnittstelle Sichtbarkeit mit static einschränken 01 static inline void sb_com_settx(uint8_t bit) { 02 if (bit) 03 PORTD = (1 << PD1); 04 else 05 PORTD &= ~(1 << PD1); 06 } 07 08 static inline uint8_t sb_com_getrx() { 09 return (PIND & (1 << PD0))!= 0; 10 } 19

COM-Modul Aufgabe Funktionen der Schnittstelle müssen überall sichtbar sein Sichtbarkeit nicht einschränken Kompatibilität von Schnittstelle und Implementierung durch Inkludieren des Headers gewährleistet 01 uint8_t sb_com_bytereadyforreceive(){ 02 sb_com_init(); 03 return sb_com_getrx()!= 0; 04 } 20

COM-Modul Aufgabe Implementierung nur einmal machen Funktionen auf allgemeinste Funktion abbilden sb_com_sendbyte() auf Feld der Größe 1 abbilden sb_com_senddoublebyte() auf Feld der Größe 2 abbilden 01 void sb_com_sendbyte(uint8_t data) { 02 sb_com_sendarray(&data, 1); 03 } 04 05 void sb_com_senddoublebyte(uint16_t data) { 06 sb_com_sendarray((uint8_t *)(&data), 2); 07 } 08 09 void sb_com_sendarray(uint8_t * data, size_t len){ 10 // Implement 11 } 21

COM-Modul Aufgabe Analog für Empfangsfunktionen Funktionen auf allgemeinste Funktion abbilden sb_com_receivebyte() auf Feld der Größe 1 abbilden sb_com_receivedoublebyte() auf Feld der Größe 2 abbilden 01 uint8_t sb_com_receivebyte(uint8_t *data) { 02 return sb_com_receivearray(data, 1); 03 } 04 05 uint8_t sb_com_receivedoublebyte(uint16_t *data) { 06 return sb_com_receivearray((uint8_t *) data, 2); 07 } 08 09 uint8_t sb_com_receivearray(uint8_t *data, size_t len) { 10 // Implement 11 } 22

COM-Modul Aufgabe Aufgabe ist in drei Teile unterteilt Teilaufgabe a: Initialisierung Einmaliges Initialisieren der Empfangs- und Senderegister Implementieren der Hilfsfunktion sb_com_init() Wird bei jedem Sende- oder Empfangsvorgang aufgerufen 23

COM-Modul Aufgabe Aufgabe ist in drei Teile unterteilt Teilaufgabe b: Sendefunktionalität Unabhängig vom Empfangen implementieren Implementieren der Funktion sb_com_sendarray() Ablauf für jedes zu sendende Byte: Senden des Startbits Senden der Nutzdaten (LSB zuerst) Senden des Paritätsbits Senden des Stoppbits Verwendung von sb_com_wait(1.0) um ein Symbol zu warten Testen der Sendefunktionalität mit dem vorgebenen Programm test_receiver.elf 23

COM-Modul Aufgabe Aufgabe ist in drei Teile unterteilt Teilaufgabe c: Empfangsfunktionalität Unabhängig vom Senden implementieren Implementieren der Funktion sb_com_receivearray() Ablauf für jedes zu empfangende Byte: Warten auf fallende Flanke an RX Empfangen des Startbits Empfangen der Nutzdaten Empfangen des Paritätsbits Empfangen des Stoppbits Treten Fehler während der Übertragung auf, wird der Empfangsvorgang bis zum Ende ausgeführt und der entsprechende Fehlercode zurückgegeben Testen der Empfangsfunktionalität mit dem vorgebenen Programm test_sender.elf 23

COM-Modul Aufgabe Testen der finalen Implementierung mit einer Anwendung Beispielanwendung auf100 2-Personen-Spiel zum Testen des Kommunikationsmoduls Spielprinzip: Es wird mit einer zufälligen Zahl begonnen, die auf der 7-Segmentanzeige dargestellt wird. Jeder Spieler kann diese Zahl nun abwechselnd durch drehen des Potentiometers um 1 bis 8 erhöhen. Der Spieler, der die 100 erreicht hat gewonnen. 24