CAN Projektpraktikum Praktikumsanleitung Studiengang FZT Technische Universität Ilmenau - Fachgebiet Rechnerarchitektur Stand: 14. Mai 2012 Dr.-Ing. Alexander Fleischer [email protected] Inhaltsverzeichnis 1 Über diese Anleitung 2 2 Hardware des Praktikumssystems und Funktionen zur Ansteuerung 2.1 Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Adreßraum Ein- und Ausgabeeinheiten . . . . . . . . . . . . . . . 2.3 Ausgabeeinheiten . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4 Eingabeeinheiten . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5 CAN-Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 3 4 5 5 3 Beschreibung der Software 3.1 PC Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Entwicklungsumgebung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3 Programmierung des Praktikumssystems . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 6 7 8 4 Aufgabenstellung 4.1 Vorbreitung . . . . . . . . . . . . . 4.2 Aufgabe 1 – CAN-Empfang . . . . 4.3 Aufgabe 2 – CAN-Kommunikation 4.4 Belegung der Schalter und Tasten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 8 9 9 10 5 Vorgehen bei Problemen 10 6 Anhang: Übersicht der vordefinierten Funktionen 11 7 Anhang: Prgrammiersprache C 7.1 Programmieren in C – Verweis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.2 Beispielcode mit Erläuterungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 12 12 8 Vorbereitung zum Praktikum 14 1 Über diese Anleitung Diese Anleitung beinhaltet die allgemeine Beschreibung der Praktikumshardware, Praktikumssoftware und die Aufgabenstellungen für das CAN Projektpraktikum. Zusätzlich zu dieser Anleitung benötigen Sie die Dokumentation des CAN-Controllers, welches in der Datei “Beschreibung des CAN - Interfaces des C164” enthalten ist. Eine ausführlichere Beschreibung der Hardware des Praktikumssystems finden Sie in der Datei “Hardwarebeschreibung”, die für das Praktikum wichtigen Teile sind auch in dieser Anleitung enthalten. Diese Dateien erhalten Sie im entsprechenden Bereich im E-Learning System des Fachgebietes Rechnerarchitektur, welches über die Fachgebietsseite http://www.tu-ilmenau.de/ra erreichbar ist. Dort finden Sie auch noch weitere Dateien, beispielsweise die komplette Beschreibung des verwendeten C164, welche optionale Zusatzinformationen enthalten, aber für das Praktikum nicht benötigt werden. Die Beispiele sowie die kursiv gesetzten Erläuterungen zu den Aufgaben beziehen sich auf die Vorgabedateien. Dieser vorgegebene Rahmen dient der Strukturierung und Vereinfachung der einzelnen Aufgaben. Eigene Lösungen, unabhängig von diesen Vorlagen, sind selbstverständlich auch möglich. 2 2 Hardware des Praktikumssystems und Funktionen zur Ansteuerung Die ausführliche Dokumentation zur Hardware des Praktikumssystems finden Sie im Dokument “Hardwarebeschreibung“. In den folgenden Abschnitten finden Sie eine Zusammenfassung der für das Praktikum relevanten Funktionen. 2.1 Übersicht Das Praktikumssystem besteht aus folgenden Komponenten: • Prozessormodul nanoModul-164 – Prozessor Infineon C164CI ∗ 16bit CPU ∗ Full CAN 2.0B Controller ∗ 6 parallele I/O-Ports verschiedener Breite ∗ General Purpose Timer, Watchdog, Real Time Clock, A/D-Wandler ∗ asynchrone und synchrone serielle Schnittstelle – 256 kB SRAM – 256 kB Flash • Adressdekoder 74HC154 (am Port P1H ) • Eingabeeinheiten mit Bustreiber 74HCT573, Ausgänge der Bustreiber am Datenbus (Port P1L) • Ausgabeeinheiten mit Bustreiber (74HCT563, mit D-Latch), Eingänge der Bustreiber am Datenbus (Port P1L) Es ist über eine serielle Schnittstelle mit einem PC verbunden, auf welchem die Entwicklungsumgebung läuft. Alle Praktikumssysteme sind untereinander über den CAN-Bus verbunden. Zusätzlich ist am CAN-Bus noch ein Busmonitor angeschlossen, welcher es erlaubt, die Übertragungen auf dem Bus zu beobachten. 2.2 Adreßraum Ein- und Ausgabeeinheiten Zur Adressierung der Ein- und Ausgabeeinheiten werden folgende Adressen verwendet: 3 symb. Name SEG2 SEG1 SEG4 SEG3 SEG6 SEG5 SEG8 SEG7 DIL1 DIL2 DIL3 DIL4 TASTER SCHALTER1 SCHALTER2 Adresse 10H 20H 30H 40H 50H 60H 70H 80H 90H A0H B0H C0H D0H E0H F0H Peripheriebauelement A1/1 A1/2 A2/1 A2/2 A3/1 A3/2 A4/1 A4/2 DIL1 DIL2 DIL3 DIL4 Taster SW1 SW2 Erläuterung 2. Stelle von links 1. Stelle von links 4. Stelle von links 3. Stelle von links 6. Stelle von links 5. Stelle von links 8. Stelle von links 7. Stelle von links 1. DIL-Schalterblock 2. DIL-Schalterblock 3. DIL-Schalterblock 4. DIL-Schalterblock von von von von links links links links oberer Schalterblock unterer Schalterblock Die symbolischen Namen werden in dem Rahmenprogramm definiert und können statt der Adressen verwendet werden. Mit Ausgabe der jeweiligen Adresse auf dem Adressbus wird die entsprechende Baugruppe aktiviert und nimmt Daten vom Datenbus entgegen und gibt diese aus bzw. legt den Eingabewert auf den Datenbus. 2.3 Ausgabeeinheiten Jedem der Segmente der 7-Segment-Anzeige ist ein Bit in dem auszugebenden Byte zugeordnet. Durch das Ausgeben einer “1” an der jeweiligen Bitposition leuchtet das dieser Bitposition zugeordnete Segment, bei Ausgabe einer “0” bleibt es dunkel. Den Bits sind folgende Segmente zugeordnet: Bitposition 0 1 2 3 4 5 6 7 Hexadezimal 01H 02H 04H 08H 10H 20H 40H 80H Segment A B C D E F G H Für die Ansteuerung der Ausgabe sind im Rahmenprogramm folgende Funktionen vordefiniert, welche Sie direkt verwenden können: • void led ausgabe(unsigned char stelle, unsigned char ziffer) Gibt an der angegebenen Displaystelle die übergebene Ziffer aus. Der Wert für “stelle” muss zwischen 0 und 7 liegen, der Wert für “ziffer” zwischen 0 und 17. Dabei haben die Werte folgende Bedeutung: Wert 0 .. 9 10 .. 15 16 17 Bedeutung Ziffern 0 - 9 Hexadezimalziffern “A”...“F” “-” Stelle löschen Beispiel: led ausgabe(1,4) • void led hex(unsigned char stelle,unsigned char zahl) 4 Gibt die angegebene Zahl (Bereich 0 .. 255) auf der angegebenen und der folgenden Stelle hexadezimal aus. Stelle muss im Bereich von 0 .. 6 sein. 2.4 Eingabeeinheiten Bei allen Schalterblöcken ist das niederwertigste Bit (Bit 0) jeweils der Schalter ganz links, das höchstwertige Bit (Bit 7) ganz rechts. Der linke obere Taster ist Bit 0 (niederwertigstes Bit), der rechts daneben liegende Bit 1. Der linke untere Taster ist Bit 4, der rechte untere Taster Bit 7. Damit ergeben sich entsprechend der Anordnung auf der Platine folgende Werte für die einzelnen Taster: obere Reihe untere Reihe 01H 10H 02H 20H 04H 40H 08H 80H Für die Ansteuerung der Eingabe sind im Rahmenprogramm folgende Funktionen vordefiniert, welche Sie direkt verwenden können: • unsigned char schalter eingabe(unsigned char adresse) Gibt die aktuelle Belegung eines Schalterblocks zurück. Als Adresse ist der symb. Name oder die Adresse aus der Tabelle “Adressraum” anzugeben. Die zurückgegebene Belegung entspricht der binären Codierung, jedes “1” - Bit im zurückgegebenen Wert entspricht einem eingeschalteten Schalter, das niederwertigste Bit entspricht dem jeweils linken Schalter. Beispielsweise wird bei der Schalterstellung (v.l.n.r) AUS-AUS-EIN-AUS-AUS-AUS-EIN-EIN der Wert C4h (196 dezimal, 11000100 binär) zurückgegeben. Es ist auch möglich, mit dieser Funktion den aktuellen Zustand der Tasten abzufragen, dabei wird jedoch nicht auf einen Tastendruck gewartet. Beispiel: unsigned char wert = schalter eingabe(SCHALTER1); • unsigned char warte taste() Die Funktion wartet, wenn eine Taste gedrückt ist, auf das Loslassen der Taste und gibt die Belegung der Tasten als Byte (analog zu den Schaltern) oder 0, wenn keine Taste gedrückt wurde, zurück. • unsigned char bit test(unsigned int wert, unsigned char bitposition) Gibt zurück, ob das entsprechende Bit (0..7) im angegebenen Wert gesetzt ist. Beispiel: if (bit test(wert, 0)) { ... 2.5 CAN-Controller Die komplette Beschreibung des CAN-Controllers (Originaldokumentation) finden Sie im Dokument “Beschreibung des CAN - Interfaces des C164“. Der CAN-Controller ist ein “Full CAN 2.0B” Controller, d.h. er kann mehrere Nachrichtenobjekte mit unterschiedlichen Identifiern gleichzeitig verwalten. Zur Steuerung des CAN-Controllers werden verschiedene Register verwendet. Einerseits gibt es globale Register, welche sich auf alle Nachrichtenobjekte beziehen (Beispielsweise die Baudrate und die Acceptance Mask), andererseits gibt es Register, welche jeweils für ein Nachrichtenobjekt verwendet werden (z.B. Identifier, Modusregister, Datenlänge, Daten). Folgende Funktionen sind zum Umgang mit dem CAN-Controller vordefiniert: • void can init(unsigned int baudrate, unsigned int mask) Initialisiert den Controller und stellt die Baudrate und Maske auf die angegebenen Werte ein. Alle Nachrichtenobjekte werden initialisert, alle Bits im Message Control Register werden aud “0” gesetzt. • void can set mcr(unsigned char objekt, unsigned int wert) 5 Setzt oder löscht einzelne Bits im Message Control Register eines Nachrichtenobjektes. Die “objekt” ist die Nummer des zu ändernden Nachrichtenobjektes (0 .. 14). Die zu setzenden / löschenden Bits werden über folgende Konstanten festgelegt: Bit Message valid setzen SET MSGVAL löschen RES MSGVAL New Data SET NEWDAT RES NEWDAT CPU Update SET CPUUPD RES CPUUPD SET TXRQ RES TXRQ Transmit Request Beschreibung Das aktuelle Nachrichtenobjekt ist gültig und wird vom CAN-Controller verwendet Neue Daten wurden in dieses Nachrichtenobejekt geschrieben Neue Daten werden durch die CPU in dieses Objekt geschrieben (stoppt die Übertragung von Objekten, die gerade aktualisiert werden) Das Nachrichtenobjekt soll gesendet werden. Kann durch die CPU oder einen Remote Frame gesetzt werden. Sollen mehrere Bits auf einmal gesetzt werden, so müssen die Konstanten bei Übergabe an die Funktion mit bitweisem UND ( & ) verknüpft werden. Andere als die angegebenen Bits bleiben unverändert. Beispiel: can set mcr(0, SET MSGVAL & SET CPUUPD); • unsigned int can test mcr(unsigned char objekt, unsigned int wert) Prüft, ob das angegebene Bit im Message Control Register. Als “wert” muss eine der folgenden Konstanten verwendet werden: TEST MSGVAL, TEST NEWDAT, TEST CPUUPD, TEST TXRQ. Beispiel: if (can test mcr(0, TEST NEWDAT)) { ... • void can set identifier(unsigned char objekt, unsigned int identifier) Setzt den Identifier für das angegebene Nachrichtenobjekt. Es werden nur 11 bit Identifier unterstützt. • void can set mcfg(unsigned char objekt, unsigned char dlc, unsigned char direction) Setzt die Datenlänge (in Bytes, 0...8) und die Übertragungsrichtung (0: Empfang; 1:Senden) für ein Nachrichtenobjekt. • void can set data(unsigned char objekt, unsigned char b0, unsigned char b1, unsigned char b2, unsigned char b3, unsigned char b4, unsigned char b5, unsigned char b6, unsigned char b7) Setzt die zu übertragenden Daten für ein Nachrichtenobejkt. Sollten weniger als 8 Byte übertragen werden, sind die anderen Bytes auf “0” zu setzen. Beispiel: can set data(0, 123, 0,0,0,0,0,0,0); • unsigned char can get data(unsigned char objekt, unsigned char bytenum) Liefert das angegebene Byte der Daten des angegebenen Nachrichten-Objektes. “bytenum” kann ein Wert zwischen 0 und 7 sein. 3 Beschreibung der Software 3.1 PC Software Die PC Software für das Praktikum wird in einer virtuellen Maschine ausgeführt. Nach dem Login wird ein Windows 98 gestartet, welches alle zum Praktikum benötigten Programme enthält. Innerhalb dieses Windows 98 sind 2 Laufwerke definiert: Laufwerk C: enthält das Windows, die Software und die erstellten Programme. Beim Abmelden / Absturz des Windows-Systems werden alle Daten auf diesem Laufwerk wieder in Ihren Ursprungszustand 6 zurückgesetzt. Laufwerk D: bietet Ihnen die Möglichkeit, Ihre Daten und Programme zu sichern. Dazu befindet sich bereits eine Verknüpfung zu einer Batch-Datei auf dem Desktop. Die Daten auf Laufwerk D: bleiben auch bei einem Neustart des Windows erhalten, werden aber jeweils über Nacht gelöscht. 3.2 Entwicklungsumgebung Im Praktikum wird eine Demoversion der TASKING Entwicklungsumgebung EDE verwendet. Diese Demoversion hat u.A. folgende Einschränkungen: • In der Workbench können maximal 5 Dateien gleichzeitig geöffnet sein • Die Anzahl der Anweisungen pro Datei ist begrenzt (Fehlermeldung “Demo Limits exceeded“). 3.2.1 EDE Workbench In diesem Programm geben Sie den Programmcode ein und starten die Übersetzung. Im linken Bereich finden Sie eine Übersicht der im Projekt vorhandenen Dateien, welche Sie mit einem Doppelklick auf den Dateinamen öffnen können. Eine neue Datei legen Sie an, indem sie mit der rechten Maustaste auf die Bezeichnung des Projektes (“CAN“) klicken und im erscheinenden Kontextmenü “add new File...“ wählen. Nach der Eingabe des Programmcodes müssen Sie das Programm übersetzen. Benutzen Sie dazu die Schaltfläche “Make“. Beobachten Sie die Statusmeldungen im unteren Fenster (“Build“). Es können sowohl Warnungen als auch Fehler auftreten. Warnungen geben Ihnen Hinweise auf eventuell falsche Parameter, nicht verwendete Variablen, etc., führen aber nicht zum Abbruch der Übersetzung. Beim Auftreten eines Fehlers wird die weitere Übersetzung abgebrochen und keine Ausgabedatei erstellt. Sind Fehler aufgetreten, so können Sie mit einem Doppelklick auf die Fehlermeldung direkt zu der Stelle im Quelltext springen, welche den Fehler verursacht hat und diesen berichtigen. Bei fehlerfreier Beendigung des Übersetzungsvorganges wird eine Ausgabedatei “can.abs“ erstellt, welche Sie dann mit Hilfe des Debuggers auf das Zielsystem laden und dort ausführen können. Den Debugger starten Sie mit dem Lupensymbol in der Symbolleiste. 3.2.2 CrossView Pro Debugger Nach dem erstmaligen Start des Debuggers baut dieser eine Verbindung zum Zielsystem auf. Damit dies möglich ist, muß sich der Zielrechner im Bootloader-Modus befinden. Drücken Sie daher, sobald das “Connecting“-Fenster erscheint, gleichzeitig die Tasten “Reset“ (Rot) und “Boot“ (Schwarz) am Zielsystem, lassen Sie zuerst die “Reset“-Taste los, danach die “Boot“-Taste. Es wird dann ein Monitorprogramm geladen, welches im Weiteren die Kommunikation zwischen Debugger und Zielsystem ermöglicht. Im Anschluß daran wird Ihr erstelltes Programm auf das Zielsystem geladen. Beim Start des Debuggers geschieht dies automatisch. Sollten Sie den Debugger nicht beendet haben und möchten Ihr (verändertes) Programm auf das Zielsystem laden, können Sie dies auch über die “LOAD“-Schaltfläche des Debuggers tun. Über die Schaltfläche “SRC“ des Debuggers können Sie jetzt Ihren Quelltext öffnen. Vor jeder Zeile, für welche Code erzeugt wurde, wird eine Schaltfläche mit einem blauen Punkt angezeigt. Wenn Sie diese Schaltfläche anklicken (roter Punkt) wird Ihr Programm bei der Abarbeitung vor Ausführung dieser Zeile angehalten. 7 Ihr Programm können Sie mit Hilfe der folgenden Schaltflächen starten: • “START“ - Ausführen des Programms von Anfang an, auch wenn bereits ein Teil abgearbeitet wurde • “GO“ - Fortsetzung der Ausführung des Programms an der aktuellen Stelle • “STEP OVER“ - Ausführung einer Programmzeile, dabei werden evtl. vorkommende Funktionsaufrufe komplett ausgeführt • “STEP INTO“ - Ausführung einer Programmzeile, wird eine Funktion aufgerufen, wird die Abarbeitung in der ersten Programmzeile der Funktion angehalten Mit Hilfe der Schaltfläche “HALT“ können Sie Ihr Programm jederzeit anhalten. Ist Ihr Programm angehalten, können Sie sich die Werte von Variablen anzeigen lassen. Am einfachsten funktioniert dies, indem sie im Quelltext mit der Maus auf eine Variable zeigen. Es erscheint dann ein Tooltip-Fenster, in welchem der aktuelle Wert angezeigt wird. Über “Data“→“Evaluate Expression...“ (oder die “EXPR“-Schaltfläche) können Sie sich auch die Werte von Variablen in einem extra Fenster anzeigen lassen (“Add Watch“) oder diese direkt ändern. Dort können Sie auch das Anzeigeformat einstellen. “Spezielle“ Variablen, wie beispielsweise die Register des CAN-Controllers, lassen sich nicht auf diese Art und Weise anzeigen. Sollten Sie diese benötigen, können Sie sich mit “Debug“→“Memory Window Setup...“ den Speicherbereich ab der Adresse 0xEF00h anzeigen lassen. 3.3 Programmierung des Praktikumssystems Im vorgegebenen Programmrahmen sind bereits die Funktionen für den Zugriff auf die Hardware (siehe Abschnitt 2) definiert. Durch die Benutzung dieser Funktionen ist es nicht mehr nötig, direkt über die Ein- und Ausgabeports diese zu programmieren, dies wird bereits innerhalb der Funktionen realisiert. Sie müssen im Praktikum ausschließlich die Funktion main() in der Datei main.c ergänzen. Die Ergänzung eigener Funktionen ist möglich, aber nicht unbedingt erforderlich. Ergänzen Sie am Anfang der MainFunktion alles, was nur einmalig zur Initialisierung durchgeführt werden muss (vor dem while(1)). Innerhalb der Endlosschleife (while(1) { ... }) ergänzen Sie bitte die Funktionen, die zyklisch immer wieder ausgeführt werden sollen. 4 Aufgabenstellung 4.1 Vorbreitung • Lesen Sie die Dokumentation zum Experimentalsystem, insbesondere die Abschnitte zur Ansteuerung der Ein- und Ausgabeeinheiten. • Machen Sie sich mit der Dokumentation des CAN-Controllers vertraut. Hier sind vor allem die Abläufe zum Senden und Empfangen von Nachrichten und Remote - Frames zu beachten (Diagramme / Ablaufpläne in der Dokumentation). • Drucken Sie das Blatt “Vorbereitung zum Praktikum” (letzte Seite) aus und beantworten Sie die dort gestellten Fragen. Am Ende dieser Anleitung finden Sie ein Arbeitsblatt mit einigen Fragen, welches Sie zur Vorbereitung nutzen können. 8 4.2 Aufgabe 1 – CAN-Empfang Initialisieren Sie den CAN-Controller mit der Baudrate 100 kBaud (entspricht dem Wert 0x34C9 für das Baudratenregister). Setzen Sie die globale Maske so, das alle Bits des Identifiers verglichen werden. Konfigurieren Sie ein Nachrichtenobject zum Empfang der Uhrzeit vom autonomen Experimentalsystem. Den CAN - Identifier des autonomen Systems erhalten Sie zu Beginn des Praktikums. Solange der linke Schiebeschalter der unteren Reihe eingeschaltet ist, soll beim Empfang einer Uhrzeit diese auf den LED Anzeigen dargestellt werden. Die Uhrzeit wird mit 6 Datenbytes gesendet, jede Stelle der Zeit einzeln. Beispielsweise würden um 15:27:05 Uhr folgende 6 Bytes gesendet werden: 01 05 02 07 00 05. Der grundsätzliche Ablauf für das Initialisieren eines Empfangsobjektes und der Empfangsvorgang sind im CAN-Manual im Diagramm “CPU Handling of Receive Objects” beschrieben. Die Initialisierung des Message-Objektes sollte einmalig am Anfang des Programmes erfolgen, die Abfrage der empfangenen Uhrzeit dagegen in regelmäßigen Abständen. 4.3 Aufgabe 2 – CAN-Kommunikation 4.3.1 Aufgabe 2.1 – eigenen Wert speichern und ändern Definieren Sie in Ihrem Programm eine Variable zum Speichern einen eigenen Wertes. Erweitern Sie ihr Hauptprogramm so, das, wenn der linke Schiebeschalter der unteren Reihe ausgeschaltet ist, dieser Wert auf den ersten 2 Displaystellen angezeigt wird. Fragen Sie jetzt die Tasten ab, so das der Wert mit den 4 linken Tasten verändert werden kann (obere Reihe: +10H, +1, untere Reihe: -10H, -1). Der grundsätzliche Ablauf für das Initialisieren eines Sendeobjektes und der Sendevorgang sind im CANManual im Diagramm “CPU Handling of Receive Objects” beschrieben. 4.3.2 Aufgabe 2.2 – Senden des eigenen Wertes auf Anforderung Ermitteln Sie Ihre eigene Knotennummer (4 Bit) durch Auslesen des linken Blocks der DIL-Schalter (DIL1). Ändern Sie die Einstellung dieser Schalter nicht ! Bilden Sie Ihren CAN-Identifier nach folgendem Schema: Bit Wert 10 1 9 0 8 1 7 0 6 0 5 0 4 0 3 2 1 0 Knotennummer Konfigurieren Sie ein weiteres Nachrichtenobjekt zum Senden des eigenen Wertes auf Anforderung durch einen anderen Knoten (Remote Frame). Es soll auf Anforderung ein Datenbyte gesendet werden, welches als Datenwert den in Aufgabe 2.1 definierten eigenen Wert enthält. Dieses soll bei einer Änderung des eigenen Wertes mit Hilfe der Tasten auch aktualisiert werden. Der grundsätzliche Ablauf für das Initialisieren eines Sendeobjektes und der Sendevorgang sind im CANManual im Diagramm “CPU Handling of Transmit Objects” beschrieben. 4.3.3 Aufgabe 2.3 – Senden des eigenen Wertes Ergänzen Sie den Programmteil aus 2.2 um die Möglichkeit, den eigenen Wert durch einen Tastendruck auf den rechten oberen Taster auch ohne Anforderung senden zu können. 9 4.3.4 Aufgabe 2.4 – Anfordern des Wertes eines anderen Knotens Definieren Sie ein weiteres Nachrichtenobjekt zum Anfordern eines Wertes eines anderen Knoten. Der Identifier des anderen Knotens soll dabei mit den linken 4 Schiebeschaltern der oberen Reihe einstellbar sein (Bildung des Identifier wie be Aufgabe 3.2). Mit der Taste unten rechts soll das Senden des Remote Frames ausgelöst werden. Stellen Sie die Antwort auf diesen Frame auf den letzten beiden Stellen des LED dar. 4.3.5 Aufgabe 2.5 – Zykliches Anfordern des Wertes eines anderen Knotens (optional) Falls der 2. Schiebeschalter von Links des unteren Blocks eingeschaltet ist, fragen Sie den Wert des anderen Knoten zyklisch ab. Senden Sie dabei aber nicht mehr als 10 Anforderungen pro Sekunde. 4.4 Belegung der Schalter und Tasten Im folgenden sind die Belegungen aller Schalter und Tasten entsprechend der Anordnung auf dem Board nach Abschluss aller Aufgaben dargestellt. Schalter: 1. Reihe: 0 2. Reihe: 0 Uhr/Wert 1 2 3 Identifier fremdes System 1 Zyklisch 2 3 4 5 6 7 4 5 6 7 Tasten (Entsprechend der Anordnung auf dem Board): +10H +1 Senden -10H -1 Anfordern 5 Vorgehen bei Problemen 1. Der Debugger reagiert nicht • Wahrscheinlich wird gerade Ihr Programm ausgeführt. Während der Ausführung des Programms sind keine weiteren Befehle im Debugger möglich. Klicken Sie auf “HALT“, um die Ausführung Ihres Programms zu unterbrechen. 2. Nach einer Änderung des Programmes wird weiterhin das “alte“ Programm ausgeführt • Schauen Sie im Statusfenster der Workbench, ob ein Fehler bei der Übersetzung auftrat. Tritt ein Fehler auf, wird die Ausgabedatei nicht erzeugt, die “alte“ allerdings auch nicht gelöscht. Berichtigen Sie ggfs. angezeigte Fehler. • Laden Sie das Programm erneut auf das Zielsystem. • Beenden Sie den Debugger. Drücken Sie “Reset“ am Zielsystem. Starten Sie den Debugger erneut. 3. Die Anzeige im Debugger bei schrittweiser Abarbeitung stimmt nicht mit den Ausgaben auf dem Zielsystem überein • siehe Punkt 2 10 6 Anhang: Übersicht der vordefinierten Funktionen • void led ausgabe(unit8 stelle, unsigned char ziffer) Gibt an der angegebenen Displaystelle die übergebene Ziffer aus. stelle: 0..7, ziffer: 0..17 (0..9, A..F, ’-’, Leer) • void led hex(unsigned char stelle,unsigned char zahl) Gibt die angegebene Zahl auf der angegebenen und der folgenden Stelle hexadezimal aus. stelle: 0..6, zahl: 0..255 • unsigned char schalter eingabe(unsigned char adresse) Gibt die aktuelle Belegung eines Schalterblocks zurück. adresse: DILx, SCHALTERx, TASTER • unsigned char warte taste() Die Funktion wartet, wenn eine Taste gedrückt ist, auf das Loslassen der Taste und gibt die Belegung der Tasten als Byte (analog zu den Schaltern) oder 0, wenn keine Taste gedrückt wurde, zurück. • unsigned char bit test(unsigned int wert, unsigned char bitposition) Gibt zurück, ob das entsprechende Bit im angegebenen Wert gesetzt ist. wert: 0..0xFFFF, bitposition: 0..15 • void sleep(unsigned int zeit) Wartet die angegebene Zeitspanne. zeit: 330 entspricht ca. 1s • void can init(unsigned int baudrate, unsigned int mask) Initialisiert den Controller und stellt die Baudrate und Maske auf die angegebenen Werte ein. Alle Nachrichtenobjekte werden initialisert, alle Bits im Message Control Register werden aud “0” gesetzt. baudrate: 0..0xFFFF, zu setzender Wert für BTR mask: 0..0x7FF, Bitmaske für den Vergleich des CAN-Identifiers • void can set mcr(unsigned char objekt, unsigned int wert) Setzt oder löscht einzelne Bits im Message Control Register eines Nachrichtenobjektes. objekt: 0..14, wert: in MCR zu schreibender Wert, folgende Konstanten sind möglich: SET MSGVAL, RES MSGVAL, SET NEWDAT, RES NEWDAT, SET CPUUPD, RES CPUUPD, SET TXRQ, RES TXRQ Sollen mehrere Bits auf einmal gesetzt werden, so müssen die Konstanten bei Übergabe an die Funktion mit bitweisem UND ( & ) verknüpft werden. • unsigned int can test mcr(unsigned char objekt, unsigned int wert) Prüft, ob das angegebene Bit im Message Control Register. objekt: 0..14, wert: 0..0xFFFF (TEST MSGVAL, TEST NEWDAT, TEST CPUUPD, TEST TXRQ) • void can set identifier(unsigned char objekt, unsigned int identifier) Setzt den Identifier für das angegebene Nachrichtenobjekt. Es werden nur 11 bit Identifier unterstützt. objekt: 0..14, identifier: 0..0x7FF • void can set mcfg(unsigned char objekt, unsigned char dlc, unsigned char direction) Setzt die Datenlänge (in Bytes) und die Übertragungsrichtung (0: Empfang; 1:Senden) für ein Nachrichtenobjekt. objekt: 0..14, dlc: 0..8, direction: 0..1 • void can set data(unsigned char objekt, unsigned char b0, unsigned char b1, unsigned char b2, unsigned char b3, unsigned char b4, unsigned char b5, unsigned char b6, unsigned char b7) Setzt die zu übertragenden Daten für ein Nachrichtenobejkt. objekt: 0..14, b0..b7: 0..255 • unsigned char can get data(unsigned char objekt, unsigned char bytenum) Liefert das angegebene Byte der Daten des angegebenen Nachrichten-Objektes. objekt: 0..14, bytenum: 0..7 11 7 Anhang: Prgrammiersprache C 7.1 Programmieren in C – Verweis Eine allgemeine Einführung in die Programmiersprache C findet man beispielsweise unter http://de.wikibooks.org/wiki/C-Programmierung. 7.2 Beispielcode mit Erläuterungen Der folgende Beispielcode dient nur zur Erläuterung der C Syntax und hat nicht direkt etwas mit den Praktikumsaufgaben zu tun. // Das i s t e i n Kommentar , w e l c h e r b e i // s t a r t e t und b i s zum Z e i l e n e n d e g e h t /∗ s t a r t e t e i n e n m e h r z e i l i g e n Kommentar w e l c h e r wie f o l g t b e e n d e t wird : ∗/ // D e f i n i t i o n unsigned char /∗ −−−−−−−−−− Rückgabe− typ ∗/ e i n e r Funktion s w i n ( unsigned char −−−−− −−−−−−−−−−−−− Name Parameter− typ addr ) −−−− Parameter− name // { b e g i n n t e i n e n Anweisungsblock , } b e e n d e t d i e s e n { // V a r i a b l e n d e k l a r a t i o n , muss d i r e k t nach { s t e h e n unsigned char wert = 0; // −−− Typ −− −− Name −− −− I n i t i a l i s i e r u n g , kann w e g g e l a s s e n werden // Zuweisung e i n e s Wertes P1H = addr ; wert = P1L ; // R ückgabewert d e r Funktion return wert ; } void main ( void ) { // v o i d −> k e i n R ückgabewert , main −> Hauptprogramm unsigned char x , y ; // Array−D e f i n i t i o n , d . h . 5 Werte g l e i c h e n Typs werden a n g e l e g t unsigned char a r r a y [ 5 ] = { 2 , 6 , 9 , 1 , 4 } ; /∗ −−−−−−−−−− −−−−− − −−−−−−−−−−−−− Typ Name | I n i t i a l i s i e r u n g ( optional ) Anzahl d e r Elemente ∗/ // F u n k t i o n s a u f r u f , 0xE0 wird f ü r den Parameter addr e i n g e s e t z t // H e x a d e z i m a l z a h l e n werden mit dem P r ä f i x 0x angegeben x = s w i n ( 0 xE0 ) ; // // // if B e d i n g t e Anweisung z i f f o u t ( 0 , 0 ) wird nur a u s g e f ü h r t , wenn x N u l l i s t S t a t t == f ü r g l e i c h g e h t auch != ( u n g l e i c h ) , >, <, <=, >= ( x==0) z i f f o u t ( 0 , 0 ) ; 12 // Mehrere Bedingungen // && −> l o g i s c h e s UND, | | −> l o g i s c h e s ODER, ! l o g i s c h e N e g a ti o n i f ( ( x==0) && ! ( y==1)) z i f f o u t ( 0 , 0 ) ; // S t a t t e i n e r Anweisung kann d o r t auch w i e d e r e i n Block s t e h e n i f ( x==0) { ziff out (0 ,0); ziff out (0 ,1); } // S c h l e i f e n // S o l a n g e Bedingung e r f ü l l t while ( x==0) { x = s w i n ( 0 xE0 ) ; } ist . . . // Z ä h l s c h l e i f e von 0 b i s 5 , y j e w e i l s um 1 erhöhen ( y++) f o r ( y =0;y <6;y++) { z i f f o u t (x , y ) ; } // Rechnen y = ( y + x ) ∗ 2 + y / 4 ; // ”/” −> h i e r : g a n z z a h l i g e D i v i s i o n y = x % 4 ; // ”%” −> Modulo , Rest b e i D i v i s i o n // B i t o p e r a t i o n e n x = 0 x95 ; // b i n ä r 1001 0101 y = x & 0x0F ; // 1001 0101 b i n ä r UND mit v e r k n ü p f t mit 0000 1111 −> 0000 0 1 0 1 , 0 x05 y = x | 0x0F ; // 1001 0101 b i n ä r ODER mit v e r k n ü p f t mit 0000 1111 −> 1001 1 1 1 1 , 0x9F y = x >> 4 ; // 1001 0101 um 4 S t e l l e n nach r e c h t s g e s c h o b e n −> 0000 1 0 0 1 , 0 x09 y = x << 4 ; // 1001 0101 um 4 S t e l l e n nach l i n k s g e s c h o b e n −> 0101 0 0 0 0 , 0 x50 y = ˆx ; // B i t w e i s e Negation , 0110 1 0 1 0 , 0x6A // Arrays // D e f i n i t i o n s i e h e oben , Index b e g i n n t immer b e i 0 und g e h t b i s Anzahl −1 a r r a y [ 2 ] = 1 2 ; // 3 . Element a u f 12 s e t z e n f o r ( y =0;y <5;y++) { // Elemente i n e i n e r S c h l e i f e ausgeben z i f f o u t ( array [ y ] , y ) ; } } // Ende main ( ) 13 8 Vorbereitung zum Praktikum Name: Matrikelnummer: 1. Schauen Sie sich folgendes Beispielprogramm an und eränzen Sie hinter jeder Zeile, was diese Anweisung bedeutet. void main ( void ) { unsigned char s c h a l t e r ; unsigned char i ; f o r ( i =0; i <8; i ++) led ausgabe ( i , 17); while ( 1 ) { s c h a l t e r = s c h a l t e r e i n g a b e (SCHALTER1 ) ; led hex (0 , schalter ) ; i f ( b i t t e s t ( schalter , 0)) { led ausgabe (8 , 8); } else { led ausgabe (8 ,17); } } } 2. Wozu dient die globale Maske, und wie ist diese für die Anforderung im Praktikum zu setzen ? 3. Geben Sie die Befehle für die Definition eines Nachrichtenobjektes zum Senden / Empfangen eines Wertes (1 Datenbyte) an ! Benutzen Sie die Funktionen set mcr und set mcfg. Senden Empfangen 4. Geben Sie an, welche Funktionsaufrufe für das Aktualisieren des Wertes in einem Sende-Nachrichtenobjekt nötig sind ! 5. Wie kann man bei einem Empfangs-Nachrichtenobjekt abfragen, ob neue Daten eingetroffen sind ?