I2CPICMasterSlave - Homepage von Stefan Buchgeher
Transcription
I2CPICMasterSlave - Homepage von Stefan Buchgeher
Datenaustausch zwischen zwei (oder mehreren) PIC16Fxx-Mikrocontrollern via I2CTMin C (oder: Wie realisiere ich einen I2CTM-Slave mit einem PIC16Fxx-Mikrocontroller) Stefan Buchgeher 4. August 2014 www.stefan-buchgeher.info B [email protected] B Großambergstraße 106/3, A-4040 Linz (Österreich) H ++43/699/11 29 63 38 1 INHALTSVERZEICHNIS Inhaltsverzeichnis 1 Einleitung 2 2 I2 C-Protokoll 3 3 PIC16Fxx als I2 C-Slave 3.1 Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4 6 4 PIC16Fxx als I2 C-Master 9 4.1 Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 4.2 Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 5 Demonstrationsbeispiele 5.1 Schaltung (Hardware) . . . . . . . . . . . . . . . 5.2 Software für 1. Demo (Slave) . . . . . . . . . . . . 5.3 Anmerkungen zur Software für 1. Demo (Slave) . 5.4 Software für 1. Demo (Master) . . . . . . . . . . . 5.5 Anmerkungen zur Software für 1. Demo (Master) 5.6 Software für 2. Demo (Slave) . . . . . . . . . . . . 5.7 Anmerkungen zur Software für 2. Demo (Slave) . 5.8 Software für 2. Demo (Master) . . . . . . . . . . . 5.9 Anmerkungen zur Software für 2. Demo (Master) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 11 13 20 23 28 31 39 41 45 Literatur [1] Microchip. Datenblatt des PIC16F887. http://ww1.microchip.com/downloads/en/ DeviceDoc/41291G.pdf, 2012. [2] Microchip. Application Note: AN734 - Using the Mid-Range Enhanced Core PIC16 Devices’ MSSP Moduls for slave I2C Communication. http://ww1.microchip.com/ downloads/en/AppNotes/00000734C.pdf, 2013. [3] mikroElekronika. mikroElektronika - Tools, Compilers, Books, Magazine. http:// www.mikroe.com/, 2009. [4] mikroElekronika. mikroc user’s manual. http://www.mikroe.com/, 2009. 1 EINLEITUNG 1 2 Einleitung Der I2 C-Bus1 wurde ursprünglich von der Firma Philips für die Kommunikation verschiedener Baugruppen in einem Gerät entwickelt. Der I2 C-Bus ist eine so genannte synchrone serielle Zwei-Drahtverbindung zwischen einem Master und einem oder mehreren Slaves. In den meisten Fällen ist der Master ein Mikrocontroller (z.B. ein PIC), während es sich beim Slave z.B. um einen Speicherbaustein handelt, oder um Porterweiterungsbausteine, Temperatursensor, Uhrenbausteine, AnalogDigital-Wandler oder um Spezialbausteine aus dem Bereich der Audio- und Videotechnik. Oder, und darum geht es hier, kann der Slave auch ein PIC-Mikrocontroller sein. Der I2 C-Bus benötigt neben einer Masseleitung nur zwei Leitungen: • Eine Taktleitung (diese wird meist mit SCL bezeichnet) und dient zur Erzeugung des Taktes. Der Takt wird dabei immer vom Master erzeugt. Die Taktgeschwindigkeit ist von den verwendeten Slave-Bausteinen abhängig. Sie kann maximal 100 kHz, 400 kHz oder 1 MHz betragen. • Eine Datenleitung (diese wird meist mit SDA bezeichnet) und dient zur Übertragung der Daten. Die Daten können sowohl vom Master zum Slave (hier spricht man von Daten schreiben) als auch vom Slave zum Master (hier spricht man von Daten lesen) übertragen werden. In den meisten Fällen wird die Datenübertragung von einem Master ausgelöst. Es ist aber auch möglich, dass zwei oder mehr Master in einen Bus vorkommen. In diesem Fall spricht man vom Multi-Master-Mode. Hier ist durch ein bestimmtes Protokoll gesichert, dass immer nur ein Master den Bus übernehmen kann, wenn der Bus frei ist. Der MultiMaster-Mode soll hier nicht näher betrachtet werden. Diese Dokumentation bezieht sich ausschließlich auf die Konfiguration ein Master mit einem oder mehreren Slaves. Einige Bausteine der PIC16-Familie beinhalten ein (oder zwei) Hardwaremodul(e) für die Ansteuerung von I2 C-Slave-Bausteinen (z.B. PIC16F88x). Beinhaltet der für ein Projekt ausgewählte PIC kein I2 C-Hardwaremodul, so ist man gezwungen diese per Software zu realisieren, wenn man mit I2 C-Bausteinen kommunizieren muss. Diese Dokumentation beschreibt die Software für die Implementierung des I2 C-Protokolls für einen Slave mit einem PIC-Mikrocontroller mit I2 C-Hardwaremodul. Wichtig: Damit ein Mikrocontroller vom Typ PIC16Fxx als Slave für den I2 C-Bus verwendet werden kann muss dieser über das MSSP-Modul verfügen, und dieser muss den Slave-Mode beinhalten. MSSP steht für Master Synchronous Serial Port. Als Informationsquellen für diese Arbeit dienen das Datenblatt des verwendeten PICMikrocontroller (hier PIC16F887 [1])und die Application-Note AN734 mit dem Titel: 1 Das Kürzel I2 C bedeutet Inter-Integrated-Circuit und wird daher auch oft mit IIC abgekürzt 2 I2 C-PROTOKOLL 3 Using the Mid-Range Enhanced Core PIC16 Devices’ MSSP Modules for Slave I2 CTM Communication [2]. Als Programmiersprache für die PIC-Mikrocontroller-Software wurde C mit dem mikroCCompiler2 verwendet. Für die Demonstrationsbeispiele (ab Seite 10) ist die kostenlose Demoversion3 ausreichend. I2C-Protokoll 2 Jede Aktion auf dem I2 C-Bus geht vom Master aus. Als Master dient hier ein PIC (z.B. PIC16F887). Die erste Aufgabe des Masters einer jeden Datenübertragung ist das Erzeugen der Startbedingung. Die Startbedingung ist wie folgt definiert: Auf der Datenleitung (SDA) erfolgt eine High-Low-Flanke, während die Taktleitung (SCL) High ist. Damit wird gekennzeichnet, dass auf dem I2 C-Bus ein Datenverkehr stattfindet. Würden sich auf dem Bus weitere Master befinden (Multi-Master-Mode) so dürfen diese jetzt keine Datenübertragung zu einem Slave beginnen, da der Bus jetzt belegt ist. Nun muss der Master die Adresse des Slaves mit welchem er kommunizieren möchte bekannt geben. Zu diesem Zweck besitzt jeder Slave eine Adresse. Diese Adresse besteht in den meisten Fällen aus einem vom Hersteller festgelegtem Bauteilkode und einer Bausteinadresse, welche durch Beschaltung dafür reservierter Anschlüsse wählbar ist. So ist es möglich mehrere gleichartiger Bausteine an einem Bus anzuschließen. (Z.B. mehrere Speicherbausteine oder mehrere Porterweiterungsbausteine.) Nach der Bauteiladresse (diese besteht in den meisten Fällen aus 7 Bit oder aus 10 Bit) erfolgt als nächstes die Bekanntgabe der Übertragungsrichtung. Möchte der Master (also der PIC) von einem Slave Daten lesen, so erfolgt als Übertragungsrichtung ein Low (0). Möchte der Master (PIC) zu einem Slave Daten (oder Befehle) übertragen, so erfolgt als Übertragungsrichtung ein High (1). Die Adresse und das Bit welches die Übertragungsrichtung festlegt werden auch als Kontrollbyte bezeichnet. Nach dem Kontrollbyte muss der Master auf ein Bestätigungsbit vom adressierten Slave warten. Je nach Slave kann nun entweder ein Datenbyte oder mehrere Datenbytes vom Master zum Slave oder vom Slave zum Master übertragen werden. Werden Daten vom Master zum Slave übertragen (Schreibvorgang), so muss der Master nach jedem übertragenen Byte auf eine Bestätigung vom Slave warten. Erfolgt der Datenverkehr in die andere Richtung (vom Slave zum Master, man spricht hier auch von einem Lesevorgang) so muss der Master jedes empfange Byte bestätigen. Sind alle Daten übertragen, muss der I2 C-Bus wieder freigegeben werden. Diese Freigabe erfolgt mit einer Stoppbedingung. Die Stoppbedingung ist wie folgt definiert: Auf der 2 Der mikroC-Compiler wurde von der Firma mikroElektronika [3] entwickelt und dient zum Programmieren der PIC16Fxx-Familie in der Hochsprache C 3 Die freie Demoversion ist nur auf eine Programmspeichergröße von 2k begrenzt, ansonst voll kompatibel zur Vollversion. Die Demoversion ist auf der Firmen-Webseite [3] downloadbar 3 PIC16FXX ALS I2 C-SLAVE 4 Datenleitung (SDA) erfolgt eine Low-High-Flanke, während die Taktleitung (SCL) High ist. Der I2 C-Bus ist nun frei und kann von einem anderen Master zur Datenübertragung benutzt werden. Das folgende Bild zeigt zur besseren Verdeutlichung nochmals den gesamten Vorgang. Abbildung 1: I2 C-Protokoll Achtung: Das hier beschriebene Protokoll zum I2 C-Bus - also das Setzen und das Löschen der Leitungen SDA und SCL muss in der Software nicht nachgebildet werden. Diese Aufgabe übernimmt das Hardwaremodul MSSP des PIC16Fxx-Mikrocontroller. In der Software müssen nur die Steuerbits gesetzt (oder gelöscht) werden und die zu übermittelten Daten bereitgestellt oder abgeholt werden. Mehr dazu in den folgenden Abschnitten. PIC16Fxx als I2C-Slave 3 Dieser Abschnitt beschreibt nun wie ein PIC16Fxx-Mikrocontroller als Slave für den I2 C zu konfigurieren ist und welche Software-Routinen notwendig sind. Wichtig: Damit ein Mikrocontroller vom Typ PIC16Fxx als Slave für den I2 C-Bus verwendet werden kann muss dieser über das MSSP-Modul verfügen, und dieser muss den Slave-Mode beinhalten. MSSP steht für Master Synchronous Serial Port. 3.1 Hardware Zunächst die Hardwarebeschaltung. Abbildung 2 zeigt die Beschaltung des PIC16FxxMikrocontrollers, wobei auch die Beschaltung des Oszillators X1 entfallen kann, wenn der verwendete PIC16Fxx-Mikrocontroller über einen internen Oszillator verfügt. Der I2 C-Bus mit seinen Leitungen (SDA, SCL, Masse, Betriebsspannung und dem optionalen Interrupt) ist im Bild unten zu sehen. Wesentlich ist hier eigentlich nur, dass 3 PIC16FXX ALS I2 C-SLAVE 5 Abbildung 2: PIC16Fxx als I2 C-Slave, Schaltung die beiden PIC-I/O-Pins SDA und SCL über Schutzwiderstände (R3 bis R5) mit dem I2 C-Bus verbunden werden. Die übrigen Schaltungsteile entsprechen den üblichen PIC16Fxx-Applikationen. Die Schaltung rund um den Quarz X1 erzeugt einen stabilen Systemtakt. Dieser Schaltungsteil kann entweder komplett entfallen falls der verwendete PIC16F-Mikrocontroller einen internen Oszillator besitzt und dieser verwendet wird, oder umschaltbar mit Steckbrücken. Die PIC16Fxx-Familie lässt sich sehr gut in der Schaltung programmieren. Diese Methode wird ICSP4 genannt. Der Reset wird hier mit einem RC-Glied bestehend aus R1 und C1 erzeugt. Zusätzlich kann ein Reset jederzeit mit dem Taster S1 ausgelöst werden. Da der Reseteingang des Mikrocontrollers (MCLR, Pin 1) auch gleichzeitig die Programmierspannung (ca. 13V) bei der ICSP-Proghrammierung ist, darf während einer Programmierung kein Reset ausgelöst werden. Durch die Diode D1 ist ein Reset durch das RC-Glied (R1 4 ICSP steht für In-Circuit-Serial-Programming 3 PIC16FXX ALS I2 C-SLAVE 6 und C1) während einer Programmierung via ICSP nicht möglich. Die Spannungsversorgung für den Mikrocontroller erfolgt über den I2 C-Bus, so dass hier kein extra Schaltungsteil notwendig ist. Ein Koppelkondensator (C4) ist aber empfehlenswert. Die I2 C-Busadresse kann entweder in der Software fix vergeben werden oder über Steckbrücken (Jumper, JP1 bis JP6). Hier wird fast der gesamte Port B dafür verwendet. Alle übrigen Portpins sind frei verfügbar. 3.2 Software Damit ein PIC16Fxx-Mikrocontroller als Slave für den I2 C-Bus verwendet werden kann muss dieser (wie in diesem Dokument schon öfter erwähnt) über ein so genanntes MSSPModul verfügen. Dieses Modul ist im Mikrocontroller als Hardware integriert und unterstützt neben dem I2 C-Bus einen weiteren seriellen Bus, der hier nicht weiter behandelt wird. Dieses Hardware-Modul muss zunächst für den I2 C-Slave-Mode konfigueriert werden. Dazu dienen die folgenden Register: • SSPCON • SSPCON2 • SSPSTAT • SSPADD Wie diese konfiguriert werden müssen zeigen die beiden Demonstrationsbeispiel in Abschnitt 5 ab Seite 10. Wichtig ist auch, dass die Portpins (SDA und SCL) als Eingang konfiguriert werden. Da der Mikrocontroller über ein geeignetes Hardwaremodul verfügt erfolgt die Umsetzung des I2 C-Protokolls automatisch, und der Anwender muss sich darum nicht kümmern. Er hat nur“ die Aufgabe die empfangenen Daten rechtzeitig zu lesen und die zu sendenden ” Daten rechtzeitig zur Verfügung zu stellen. Dieses rechtzeitig“ lässt sich sehr elegant ” mit einem Interrupt erkennen, die der Mikrocontroller erzeugt. Wichtig ist, dass dieser Interrupt (SSP-Interrupt) freigegeben werden muss! Die Abbildungen 3 und 4 zeigen die Statusbits bei einem Lesebefehl bzw. bei einem Schreibbefehl. 3 PIC16FXX ALS I2 C-SLAVE 7 Abbildung 3: PIC16Fxx als I2 C-Slave, Statusbits bei einem Lesebefehl (Auszug aus dem Datenblatt zum PIC16F887) Abbildung 4: PIC16Fxx als I2 C-Slave, Statusbits bei einem Schreibebefehl (Auszug aus dem Datenblatt zum PIC16F887) Für den Anwender (Softwarenetwickler) besteht nur“ die Aufgabe zum richtigen Zeit” punkt die zu lesenden Daten abzuholen bzw. die zu schreibenden Daten zur Verfügung zu stellen. Dazu dienen die zwei Flags R W und D A im Register SSPSTAT. Diese beiden Flags werden automatisch gesetzt oder gelöscht nachdem ein Datenbyte via I2 C-Bus empfangen oder gesendet wurde. Gleichzeitig wird auch das Interrupt-Flag für das SSP-Modul (SSPIF) gesetzt und ein Interrupt ausgelöst, falls dieser Interrupt freigegeben wurde. Mit anderen Worten ausgedrückt: Nach jedem empfangene oder gesendeten Byte via I2 CBus wird der SSP-Interrupt ausgelöst. Dabei gibt das Flag R W an, ob die Daten am Bus vom Slave gelesen werden sollen R W = 0 oder ob der Slave Daten auf den Bus Schreiben muss R W = 1. Das Flag D A gibt an, ob das zuletzt empfangene Byte das Adressbyte war D A = 0 oder ob es sich um ein Datenbyte handelt D A = 1. 3 PIC16FXX ALS I2 C-SLAVE 8 Somit ergeben sich die vier Fälle: RW 0 0 1 1 DA 0 1 0 1 Bedeutung Daten vom Bus lesen, zuletzt empfangenes Byte war die Slaveadresse Daten vom Bus lesen, zuletzt empfangenes Byte war ein Datenbyte Daten auf den Bus schreiben, zuletzt empfangenes Byte war die Slaveadresse Daten auf den Bus schreiben, zuletzt gesendetes Byte war ein Datenbyte Das Flussdiagramm in Abbildung 5 zeigt was in diesen vier Fällen zu tun ist. Abbildung 5: PIC16Fxx als I2 C-Slave, Flussdiagramm (Interrupt-Service-Routine) Anmerkungen: • Die beiden Demonstrationsbeispiel in Abschnitt 5 ab Seite 10 zeigen diese InterruptService-Routine an einem einfachen konkreten Beispiel • Die Slave-Adresse wird in das Register SSPADD geschrieben und muss in der InterruptService-Routine (ISR) nicht beachtet werden • Das Interrupt-Flag SSPIF wird nur dann gesetzt, wenn die empfange Adresse mit dem Wert im Register SSPADD übereinstimmt • Wichtig: Das Interrupt-Flag SSPIF muss in der ISR wieder gelöscht werden! 4 PIC16FXX ALS I2 C-MASTER 9 Noch ein Hinweise: Leider hat sich herausgestellt, dass meine Software nicht bei jedem PIC16Fxx funktioniert obwohl dieser gemäß dem Datenblatt als I2 C-Slave geeignet ist. Den Grund dafür habe ich leider nicht gefunden bzw. ich hatte noch nicht das Bedürfnis diesen Fehler zu suchen. Die nachfolgende Tabelle zeigt mit welche PIC16Fxx-Typen meine“ Software funktioniert und mit welchen nicht. Typen die in dieser Tabelle nicht ” aufscheinen habe ich (noch) nicht als I2 C-Slave getestet. Typ PIC16F887 PIC16F877 Anz.Pins 40 40 funktioniert oder funktioniert nicht funktioniert :-) funktioniert (leider nicht) :-( PIC16Fxx als I2C-Master 4 Dieser Abschnitt beschreibt nun wie ein PIC16Fxx-Mikrocontroller als Master für den I2 C zu konfigurieren ist und welche Software-Routinen notwendig sind. Wichtig: Damit ein Mikrocontroller vom Typ PIC16Fxx als Master für den I2 C-Bus verwendet werden kann muss dieser über das MSSP-Modul verfügen. MSSP steht für Master Synchronous Serial Port. 4.1 Hardware Zunächst die Hardwarebeschaltung. Abbildung 6 zeigt die minimal notwendige Beschaltung des PIC16Fxx-Mikrocontrollers. Auffällig ist, dass hier kein Oszillator vorhanden ist. Dies ist auch nicht notwendig, da die Kommunikation via I2 C-Bus nicht zeitkritisch ist, und daher ein interner Oszillator verwendet werden kann. Wichtig sind hier nur die Pull-Up-Widerstände R2 bis R4 für die beiden I2 C-Leitungen (SDA und SCL) sowie für die Interrupt-Leitung (INT)5 . An die Buchse K3 bzw. an den Stecker K4 kann ein beliebiges (5-poliges) Kabel angeschlossen werden. Buchsentyp sowie Steckertyp und Pinbelegung sind frei wählbar. Hier wird auch die Betriebsspannung sowie die Masse über das Kabel übertragen, so dass die I2 C-Slaves mit dieser Betriebsspannung versorgt werden können. Wie schon bei der Beschaltung für den PIC16Fxx als Slave wird auch der Master mittels ICSP6 programmiert. Schaltungsteil um Buchse K5. 5 Achtung: Dies ist kein Interrupt des Mikrocontroller PIC16Fxx. Es gibt I2 C-Bausteine (Slaves) die neben den Leitungen SDA und SCL einen so genannten INT-Ausgang besitzen um den I2 C-Master mitzuteilen, dass Daten zum Abholen bereit sind. z.B. siehe PCF8574. 6 ICSP steht für In-Circuit-Serial-Programming 5 DEMONSTRATIONSBEISPIELE 10 Abbildung 6: PIC16Fxx als I2 C-Master, Schaltung 4.2 Software Der hier verwendete C-Compiler verfügt bereits über Unterprogramme zur Kommunikation via I2 C für den Master [4]. Wichtig ist dass zu Beginn die Taktfrequenz für den I2 C-Bus definiert werden muss. Diese Aufgabe übernimmt das Unterprogramm I2C Init(). Für die Erzeugung der Startund Stopp-Bedingung stehen die Unterprogramme I2C Start() und I2C Stop() zur Verfügung. Das Schreiben von 8-Bit-Daten erfolgt mit dem Unterpogramm I2C Wr() und das Lesen von 8-Bit-Daten erfolgt mit dem Unterprogramm I2C Rd(). Wichtig ist dass die Pins SDA und SCL (beim Master) als Ausgang definiert werden müssen. (Vgl.: Bei der Verwendung eines PIC16Fxx als I2 C-Slave müssen die Pins SDA und SCL als Eingang definiert werden). 5 Demonstrationsbeispiele Das folgende Beispiel dient nur zur Demonstration. Es zeigt eine mögliche Einbindung der zuvor beschriebenen ISR (Interrupt-Service-Routine) für den I2 C-Slave. Neben einem PIC16Fxx als I2 C-Slave dient ein weiterer Mikrocontroller vom Typ PIC16Fxx als I2 C- 5 DEMONSTRATIONSBEISPIELE 11 Master. Weitere I2 C-Slaves sind ein I/O-Expander vom Typ PCF8574 zur 8-Bit-Eingabe mittels Jumper und ein zweiter I/O-Expander vom gleichen Typ PCF8574 zur 8-BitAusgabe mittels Leuchtdioden (LEDs). Die Aufgabe des I2 C-Masters ist es nun: 1. 8-Bit-Wert vom I2 C-Eingabemodul (mit PCF8574) lesen und am PIC-I2 C-Slave am Port D mittels 8 Leuchtdioden (LEDs) ausgeben. 2. 8-Bit-Wert vom PIC-I2 C-Slave vom Port A einlesen und am I2 C-Ausgabemodul (mit PCF8574) anzeigen (mittels 8 Leuchtdioden). 5.1 Schaltung (Hardware) Die Abbildung 7 zeigt die gesamte Schaltung für dieses Demonstrationsbeispiel. Der schwarz gezeichnete Schaltungsteil kennzeichnet den PIC-I2 C-Slave. Dieser Schaltungsteil entspricht der Schaltung aus Abbildung 2 (Seite 5). Zusätzlich sind hier die Jumper und Pull-Up-Widerstände am Port A, sowie die Leuchtdioden und die dazugehörigen Vorwiderstände am Port D (grau dargestellt). Der externe Oszillator X1 mit den Kondensatoren C2 und C3 sowie dem Widerstand R2 werden hier nicht benötigt, da der interne Oszillator verwendet wird. Diese sind daher ebenfalls grau gekennzeichnet. Weiters sind die Jumper JP1 bis JP10 so wie in Abbildung 7 zu setzen. JP1 bis JP6 definieren die I2 C-Slave-Adresse. Hier 0011000 R/W. Als Mikrocontroller für den I2 C-Slave wurde hier der Typ PIC16F887 verwendet. Der zweite Mikrocontroller (IC2) ist ebenfalls vom gleichen Typ (PIC16F887) und dient hier als I2 C-Master. Dieser Schaltungsteil ist genau wie in Abschnitt 4.1 (Seite 9) beschrieben. (Wichtig sind hier die Pull-Up-Widerstände an den I/O-Pins SCL, SDA und INT). An den I2 C-Bus sind neben dem PIC-I2 C-Slave (rund um IC1) auch die beiden I/OExpander vom Typ PCF8574 angeschlossen (IC3 und IC4). Wichtig sind die I2 C-SlaveAdressen die hier ebenfalls mit Jumpern ausgewählt werden können. Bei IC3 sind die Jumper für A1 und A2 gesteckt, während bei IC4 nur der Jumper für A2 gesteckt ist. Es versteht sich von selbst, dass beide I/O-Expander unterschiedliche Slaveadressen besitzen müssen, und dass die Slaveadresse des PIC-I2 C-Slave sich von denen der I/O-Expander unterscheiden muss! Die Spannungsversorgung besteht hier aus einem Labornetzgerät und beträgt 5V. 5 DEMONSTRATIONSBEISPIELE Abbildung 7: Demonstrationsbeispiel (Schaltung) 12 5 DEMONSTRATIONSBEISPIELE 5.2 13 Software für 1. Demo (Slave) Beim ersten Demonstrationsbeispiel sendet der I2 C-Master nur ein Datenbyte zum PICI2 C-Slave, bzw. liest anschließend auch nur ein Datenbyte vom PIC-I2 C-Slave. Beachte: Da bei diesem ersten Demonstrationsbeispiel nur ein Datenbyte gesendet bzw. nur ein Datenbyte gelesen wird, vereinfacht sich das Flussdiagramm (aus Abbildung 5, Seite 8). Es sind nämlich kein Lesezeiger und kein Schreibzeiger notwendig. Siehe auch Abschnitt 5.3, ab Seite 20. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Demo z u r Ansteuerung d e s PIC16Fxx a l s I2C−S l a v e gemaess A p p l i c a t i o n Note AN734 ∗/ /∗ ∗/ /∗ S l a v e ∗/ /∗ ∗/ /∗ Demo 1 : j e w e i l s nur e i n Byte vom Port A l e s e n und an den Master s e n d e n bzw . e i n ∗/ /∗ Byte vom Master l e s e n und am Port D a u s g e b e n ∗/ /∗ ∗/ /∗ M i k r o c o n t r o l l e r : PIC16F887 ∗/ /∗ Takt : i n t e r n e r Takt ( 4 . 0 MHz) ∗/ /∗ ∗/ /∗ Compiler : mikroC V8 . 2 ∗/ /∗ ∗/ /∗ E n t w i c k l e r : S t e f a n Buchgeher ∗/ /∗ E n t w i c k l u n g s b e g i n n d e r S o f t w a r e : 1 9 . Februar 2014 ∗/ /∗ F u n k t i o n s f a e h i g s e i t : 2 . Maerz 2014 ∗/ /∗ L e t z t e B e a r b e i t u n g : 4 . J u l i 2014 ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ I n c l u d e −D a te i e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e I n c l u d e −D a te i e n ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ S t r u k t u r e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e S t r u k t u r e n v e r w e n d e t ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ E x te r n e R e g i s t e r ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e e x t e r n e n R e g i s t e r ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ B i t s i n den e x t e r n e n R e g i s t e r n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e e x t e r n e n R e g i s t e r ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ G l o b a l e R e g i s t e r ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ char cDummy ; /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ B i t s i n den g l o b a l e n R e g i s t e r n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e g l o b a l e n R e g i s t e r ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ P o r t b e l e g u n g ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ \INT−Ausgang d e s PCF8574 ∗/ //#d e f i n e nINTPCF8574 PORTC. F5 /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ Konstanten ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n Konstanten ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ T a b e l l e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ 5 DEMONSTRATIONSBEISPIELE 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 14 /∗ k e i n e T a b e l l e n ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ F u n k t i o n s p r o t o t y p e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Unterprogramm z u r I n i t i a l i s i e r u n g d e s M i k r o c c n t r o l l e r s ∗/ void I n i t ( void ) ; /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ I n t e r r u p t −S e r v i c e −R o u ti n e ( ISR ) ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ I n t e r r u p t S e r v i c e R o u ti n e : ∗/ /∗ ∗/ /∗ A u f r u f : ∗/ /∗ SSP I n t e r r u p t F l a g ( SSPIF ) , nach jedem I2C−Event ( wenn d e r Master e i n e A d r e s s e ∗/ /∗ a u f den I2C−Bus s c h r e i b t o d e r wenn s i c h Daten am I2C−Bus b e f i n d e n ∗/ /∗ ∗/ /∗ Aufgaben : ∗/ /∗ + Je nach S t a t u s s i n d u n t e r s c h i e d l i c h e Aktionen a u s z u f u e h r e n : s i e h e Kommentare im ∗/ /∗ Quellcode ∗/ /∗ + Nach j e d e r Aktion muss das SSP−I n t e r r u p t −F l a g SSPIF w i e d e r g e l o e s c h e n werden ∗/ /∗ ∗/ /∗ Achtung : ∗/ /∗ Der S t a t u s Lesen bzw . S c h r e i b e n e r f o l g t immer aus S i c h t d e s Master ! ! ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ void i n t e r r u p t ( void ) // I n t e r r u p t r o u t i n e { i f (SSPSTAT .R W == 0 ) { // S c h r e i b z u g r i f f e ( aus S i c h t d e s Masters , d . h . S l a v e muss Daten aus dem Sende− // und E m p f a n g s b u f f e r (SSPBUF) l e s e n ) i f (SSPSTAT . D A == 0 ) { // S t a t e 1 : I2C w r i t e o p e r a t i o n , l a s t b y te was an a d d r e s s b y te // SSPSTAT b i t s : S=1 , D/A=0 , R/W=0 , BF=1 cDummy = SSPBUF ; SSPSTAT . BF = 0 ; // F l a g B u f f e r −F u l l l o e s c h e n SSPCON.CKP = 1 ; // C l o c k s t r e t c h i n g e r l a u b e n PIR1 . SSPIF = 0 ; // SSP−I n t e r r u p t −F l a g w i e d e r l o e s c h e n return ; } else { // S t a t e 2 : I2C w r i t e o p e r a t i o n , l a s t b y te was a data b y te // SSPSTAT b i t s : S=1 , D/A=1 , R/W=1 , BF=1 PORTD = SSPBUF ; // Datenbyte von SSPBUF l e s e n und am // Port D a u s g e b e n SSPCON.CKP = 1 ; // C l o c k s t r e t c h i n g e r l a u b e n PIR1 . SSPIF = 0 ; // SSP−I n t e r r u p t −F l a g w i e d e r l o e s c h e n return ; } } else { // L e s e z u g r i f f ( aus S i c h t d e s Masters , d .H. S l a v e muss Daten i n Sende− und // E m p f a n g s b u f f e r (SSPBUF) s c h r e i b e n ) i f (SSPSTAT . D A == 0 ) { // S t a t e 3 : I2C r e a d o p e r a t i o n , l a s t b y te was an a d d r e s s b y te // SSPSTAT b i t s : S=1 , D/A=0 , R/W=1 , BF=0 SSPBUF = PORTA; // Datenbyte von PortA l e s e n und i n // SSPBUF s c h r e i b e n SSPCON.CKP = 1 ; // C l o c k s t r e t c h i n g e r l a u b e n PIR1 . SSPIF = 0 ; // SSP−I n t e r r u p t −F l a g w i e d e r l o e s c h e n return ; } else { // S t a t e 4 : I2C r e a d o p e r a t i o n , l a s t b y te was a data b y te // SSPSTAT b i t s : S=1 , D/A=1 , R/W=0 , BF=0 SSPBUF = cDummy ; 15 5 DEMONSTRATIONSBEISPIELE 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 SSPCON.CKP = 1 ; PIR1 . SSPIF = 0 ; return ; // C l o c k s t r e t c h i n g e r l a u b e n // SSP−I n t e r r u p t −F l a g w i e d e r l o e s c h e n } } } /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ Unterprogramme und Funktionen ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ I n i t : ∗/ /∗ ∗/ /∗ Aufgabe : ∗/ /∗ I n i t i a l i s i e r u n g des P r o z e s s o r : ∗/ /∗ + internen Os z i l l a to r konfigurieren ∗/ /∗ + P o r t s a u f D i g i t a l I /O u m s c h a l te n und a l s Ein− o d e r Ausgang k o n f i g u r i e r e n ∗/ /∗ + I2C−Hardware−Modul a l s S l a v e k o n f i g u r i e r e n ∗/ /∗ + I2C S l a v e A d r e s s e von Port B l e s e n und i n SSPADD s c h r e i b e n ∗/ /∗ + Interrupt freigeben ∗/ /∗ ∗/ /∗ U e b e r g a b e p a r a m e te r : ∗/ /∗ keiner ∗/ /∗ ∗/ /∗ Rueckgabeparameter : ∗/ /∗ keiner ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ void I n i t ( void ) { char c I2 C A d r e s s e ; // I2C−S l a v e −A d r e s s e /∗ // ( i n t e r n e n ) O s z i l l a t o r k o n f i g u r i e r e n OSCCON = 0 b01100001 ; // Sync O s c i l l a t o r C o n t r o l R e g i s t e r +−−−−−−−−−−−−−−−−−−−− B i t 7 R e s e r v e +++−−−−−−−−−−−−−−−−− B i t 6−4 ( IRCF2 : IRCF0 ) : I n t e r n a l O s c i l l a t o r Frequency |||| Select bits |||| 000 : 31 kHz (LFINTOSC) |||| 001 : 125 kHz |||| 010 : 250 kHz |||| 011 : 500 kHz |||| 100 : 1 MHz |||| 101 : 2 MHz |||| −> 110 : 4 MHz ( d e f a u l t ) |||| 111 : 8 MHz +−−−−−−−−−−−−−−−− B i t 3 (OSTS) : O s c i l l a t o r S t a r t −up Time−out S t a t u s ||| ( Read Only ) ||| 0 : D e v i c e i s r u n n i n g from th e c l o c k d e f i n e d ||| by FOSC2 : FOSC0 o f th e CONFIG1 r e g i s t e r ||| 1 : D e v i c e i s r u n n i n g from th e i n t e r n a l ||| oscillator (HFINTOSC o r LFINTOSC) +−−−−−−−−−−−−−−− B i t 2 (HTS) : HFINTOSC S t a t u s b i r || ( High Frequency − 125 kHz to 8MHz) || ( Read Only ) || 0 : HFINTOSC i s not s t a b l e || 1 : HFINTOSC i s s t a b l e +−−−−−−−−−−−−−− B i t 1 (LTS) : LFINTOSC S t a t u s b i t | (Low Frequency − 31kHz ) | ( Read Only ) | 0 : LFINTOSC i s not s t a b l e | 1 : LFINTOSC i s s t a b l e +−−−−−−−−−−−−− B i t 0 (SCS ) : System Clock S e l e c t b i t 0 : Clock s o u r c e d e f i n e d by FOSC2 : FOSC0 o f th e CONFIG1 r e g i s t e r −> 1 : I n t e r n a l o s c i l l a t o r i s used f o r system clock ∗/ // A l l e P o r t s a u f d i g i t a l I /O k o n f i g u r i e r e n ANSEL = 0 b00000000 ; // Analog S e l e c t R e g i s t e r |||||||| // ( 0 : D i g i t a l I /O, 1 : A n a l o g e i n g a n g ) 16 5 DEMONSTRATIONSBEISPIELE 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 /∗ +−−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−− +−−−−−−−−−−−−−− Bit Bit Bit Bit Bit Bit Bit Bit 7: 6: 5: 4: 3: 2: 1: 0: Port Port Port Port Port Port Port Port RE2/AN7 RE1/AN6 RE0/AN5 RA5/AN4 RA3/AN3 RA2/AN2 RA1/AN1 RA0/AN0 ist ist ist ist ist ist ist ist hier hier hier hier hier hier hier hier Digital Digital Digital Digital Digital Digital Digital Digital I /O I /O I /O I /O I /O I /O I /O I /O ∗/ /∗ ANSELH = 0 b00000000 ; |||||||| ++−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−− +−−−−−−−−−−−−−− +−−−−−−−−−−−−− // Analog S e l e c t R e g i s t e r // ( 0 : D i g i t a l I /O, 1 : A n a l o g e i n g a n g ) Bit 6 ,7 Reserve B i t 5 : Port RB5/AN13 i s t h i e r D i g i t a l I /O B i t 4 : Port RB0/AN12 i s t h i e r D i g i t a l I /O B i t 3 : Port RB4/AN11 i s t h i e r D i g i t a l I /O B i t 2 : Port RB1/AN10 i s t h i e r D i g i t a l I /O B i t 1 : Port RB9/AN9 i s t h i e r D i g i t a l I /O B i t 0 : Port RB2/AN8 i s t h i e r D i g i t a l I /O // P o r t s k o n f i g u r i e r e n TRISA = 0 b11111111 ; +−−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−− +−−−−−−−−−−−−−− // R i c h t u n g s r e g i s t e r B i t 7 Port RA7 : h i e r B i t 6 Port RA6 : h i e r B i t 5 Port RA5 : h i e r B i t 4 Port RA4 : h i e r B i t 3 Port RA3 : h i e r B i t 2 Port RA2 : h i e r B i t 1 Port RA1 : h i e r B i t 0 Port RA0 : h i e r Port A ( 0 : Ausgang , Eingang ( Jumper Pin Eingang ( Jumper Pin Eingang ( Jumper Pin Eingang ( Jumper Pin Eingang ( Jumper Pin Eingang ( Jumper Pin Eingang ( Jumper Pin Eingang ( Jumper Pin TRISB = 0 b00111111 ; +−−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−− +−−−−−−−−−−−−−− // R i c h t u n g s r e g i s t e r B i t 7 Port RB7 : h i e r B i t 6 Port RB6 : h i e r B i t 5 Port RB5 : h i e r B i t 4 Port RB4 : h i e r B i t 3 Port RB3 : h i e r B i t 2 Port RB2 : h i e r B i t 1 Port RB1 : h i e r B i t 0 Port RB0 : h i e r Port B ( 0 : Ausgang , 1 : Eingang ) u n b e n u tz t u n b e n u tz t Eingang ( I2C−S l a v e −A d r e s s e A5) Eingang ( I2C−S l a v e −A d r e s s e A4) Eingang ( I2C−S l a v e −A d r e s s e A3) Eingang ( I2C−S l a v e −A d r e s s e A2) Eingang ( I2C−S l a v e −A d r e s s e A1) Eingang ( I2C−S l a v e −A d r e s s e A0) TRISC = 0 b00011000 ; +−−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−− +−−−−−−−−−−−−−− // R i c h t u n g s r e g i s t e r B i t 7 Port RC7 : h i e r B i t 6 Port RC6 : h i e r B i t 5 Port RC5 : h i e r B i t 4 Port RC4 : h i e r B i t 3 Port RC3 : h i e r B i t 2 Port RC2 : h i e r B i t 1 Port RC1 : h i e r B i t 0 Port RC0 : h i e r Port C ( 0 : Ausgang , 1 : Eingang ) u n b e n u tz t u n b e n u tz t u n b e n u tz t Eingang (SDA) Eingang (SCL) u n b e n u tz t u n b e n u tz t u n b e n u tz t TRISD = 0 b00000000 ; +−−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−− +−−−−−−−−−−−−−− // R i c h t u n g s r e g i s t e r B i t 7 Port RD7 : h i e r B i t 6 Port RD6 : h i e r B i t 5 Port RD5 : h i e r B i t 4 Port RD4 : h i e r B i t 3 Port RD3 : h i e r B i t 2 Port RD2 : h i e r B i t 1 Port RD1 : h i e r B i t 0 Port RD0 : h i e r Port D ( 0 : Ausgang , 1 : Eingang ) Ausgang (LED D7) Ausgang (LED D6) Ausgang (LED D5) Ausgang (LED D4) Ausgang (LED D3) Ausgang (LED D2) Ausgang (LED D1) Ausgang (LED D0) ∗/ /∗ 1 : Eingang ) 7) 6) 5) 4) 3) 2) 1) 0) ∗/ /∗ ∗/ /∗ ∗/ /∗ ∗/ /∗ TRISE = 0 b00000000 ; // R i c h t u n g s r e g i s t e r Port E ( 0 : Ausgang , 1 : Eingang ) |||||||| // und P a r a l l e l S l a v e Port S t a t u s / C o n t r o l B i t s +−−−−−−−−−−−−−−−−−−−−− B i t 7 ( IBF ) : In p u t B u f f e r F u l l S t a t u s b i t ||||||| ( Read o n l y ) ||||||| 0 : No word has been r e c e i v e d 5 DEMONSTRATIONSBEISPIELE 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 ||||||| ||||||| +−−−−−−−−−−−−−−−−−−−− |||||| |||||| |||||| |||||| +−−−−−−−−−−−−−−−−−−− ||||| ||||| ||||| ||||| ||||| +−−−−−−−−−−−−−−−−−− |||| |||| +−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−− +−−−−−−−−−−−−−− 17 1 : A word has been r e c e i v e d and i s w a i t i n g to be r e a d by th e CPU B i t 6 (OBF) : Output B u f f e r F u l l S t a t u s b i t ( Read o n l y ) 0 : The o u tp u t b u f f e r has been r e a d 1 : The o u tp u t b u f f e r s t i l l h o l d s a p r e v i o u s l y w r i t t e n word B i t 5 (IBOV) : In p u t B u f f e r O v e r f l o w D e te c t b i t ( i n M i c r o p r o c e s s o r mode ) 0 : No o v e r f l o w o c c u r r e d 1 : A w r i t e o c c u r r e d when a p r e v i o u s l y i n p u t word has not been r e a d ( must be c l e a r e d in Software ) B i t 4 (PSPMODE) : P a r a l l e l S l a v e Port Mode S e l e c t −> 0 : PORTD f u n c t i o n s i n g e n e r a l Purpose I /O mode 1 : PORTD f u n c t i o n s i n P a r a l l e l S l a v e Port mode Bit 3 Reserve B i t 2 Port RE2 : h i e r u n b e n u tz t B i t 1 Port RE1 : h i e r u n b e n u tz t B i t 0 Port RE0 : h i e r u n b e n u tz t ∗/ PORTA PORTB PORTC PORTD PORTE /∗ = = = = = 0; 0; 0; 0; 0; // I2C−Hardware−Modul a l s S l a v e k o n f i g u r i e r e n SSPCON = 0 b00100110 ; // Sync S e r i a l Port C o n t r o l R e g i s t e r 1 +−−−−−−−−−−−−−−−−−−−− B i t 7 (WCOL) : Write C o l l i s i o n D e te c t b i t ||||||| Master mode : ||||||| 0 : No c o l l i s i o n ||||||| 1 : A w r i t e to SSPBUF was attempt w h i l e th e I2C ||||||| c o n d i t i o n s were not v a l i s ||||||| S l a v e mode : ||||||| 0 : No c o l l i s i o n ||||||| 1 : SSPBUF r e g i s t e r i s w r i t t e n w h i l e s t i l l ||||||| t r a n s m i t t i n g th e p r e v i o u s word ( must be ||||||| cleared in software ) +−−−−−−−−−−−−−−−−−−− B i t 6 (SSPOV) : R e c e i v e O v e r f l o w I n d i c a t o r b i t |||||| 0 : No o v e r f l o w |||||| 1 : A new b y te i s r e c e i v e d w h i l e SSPBUF h o l d s |||||| p r e v i o u s data ( w e i t e r s i e h e D a t e n b l a t t ! ! ) |||||| ( must be c l e a r e d i n s o f t w a r e ) +−−−−−−−−−−−−−−−−−− B i t 5 (SSPEN ) : Synchronous S e r i a l Port Enable b i t ||||| 0 : D i s a b l e s s e r i a l p o r t and c o n f i g u r e s t h e s e ||||| P i n s a s I /O p o r t p i n s ||||| −> 1 : E n a b l e s th e s e r i a l p o r t an c o n f i g u r e s ||||| SCK, SDO, SDI , SS / SDA, SCL p i n s a s th e ||||| s o u r c e o f th e s e r i a l p o r t p i n s +−−−−−−−−−−−−−−−−− B i t 4 (CKP) : Clock P o l a r i t y S e l e c t b i t |||| In SPI mode : |||| 0 : I d l e s t a t e f o r c l o c k i s a low l e v e l |||| 1 : I d l e s t a t e f o r cl ock i s a high l e v e l |||| In I2C S l a v e mode : SCK r e l e a s e c o n t r o l |||| −> 0 : Holds c l o c k low ( c l o c k s t r e t c h ) . ( Used to |||| e n s u r e data s e t u p time . ) |||| 1 : Enable c l o c k |||| In I2C Master mode : Unused i n t h i s mode ++++−−−−−−−−−−−−− B i t 3−0 (SSPM3 : SSPM0) : SSP Mode S e l e c t b i t s 0000 : SPI Master mode , c l o c k = Fosc /4 0001 : SPI Master mode , c l o c k = Fosc /16 0010 : SPI Master mode , c l o c k = Fosc /64 0011 : SPI Master mode , c l o c k = TMR2 o u tp u t /2 0100 : SPI S l a v e mode , c l o c k = SCK pin , nSS p i n contr ol enabled 0101 : SPI S l a v e mode , c l o c k = SCK pin , nSS p i n c o n t r o l d i s a b l e d . nSS can be used a s I /O −> 0110 : I2C S l a v e mode , 7− b i t a d d r e s s 18 5 DEMONSTRATIONSBEISPIELE 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 0111 : I2C S l a v e mode , 10− b i t a d d r e s s 1000 : I2C Master mode , c l o c k = Fosc / ( 4 ∗ ( SSPADD+1) ) 1001 : R e s e r v e d 1010 : R e s e r v e d 1011 : I2C Firmware C o n t r o l l e d Master mode ( slave idle ) 1100 : R e s e r v e d 1101 : R e s e r v e d 1110 : I2C Firmware C o n t r o l l e d Master mode , 7− b i t a d d r e s s with START and STOP b i t i n t e r r u p t s enabled 1111 : I2C Firmware C o n t r o l l e d Master mode , 10− b i t a d d r e s s with START and STOP b i t i n t e r r u p t s enabled ∗/ /∗ SSPCON2 = 0 b00110110 ; +−−−−−−−−−−−−−−−−−−− ||||||| ||||||| ||||||| ||||||| +−−−−−−−−−−−−−−−−−− |||||| |||||| |||||| +−−−−−−−−−−−−−−−−− ||||| ||||| ||||| ||||| ||||| ||||| +−−−−−−−−−−−−−−−− |||| |||| |||| |||| |||| +−−−−−−−−−−−−−−− ||| ||| ||| +−−−−−−−−−−−−−− || || || || +−−−−−−−−−−−−− | | | | | +−−−−−−−−−−−− // Sync S e r i a l Port C o n t r o l R e g i s t e r 2 B i t 7 (GCEN) : G e n e r a l C a l l Enable b i t ( In I2C S l a v e mode o n l y ) −> 0 : General C a l l a d d r e s s d i s a b l e d 1 : Enable i n t e r r u p t when a g e n e r a l c a l l a d d r e s s (0 0 0 0 h ) i s t r e c e i v e d i n th e SSPSR B i t 6 (ACKSTAT) : Acknowledge S t a t u s b i t ( In I2C Master mode o n l y ) 0 : Acknowledge was r e c e i v e d from s l a v e 1 : Acknowledge was not r e c e i v e d from s l a v e B i t 5 (ACKDT) : Acknowledge Data b i t ( In I2C Master mode o n l y ) : Value t h a t w i l l be t r a n s m i t t e d when th e u s e r i n i z i a t e s an Acknowledge s e q u e n c e a t th e end of a r ecei ve 0 : Acknowledge 1 : Not Acknowledge B i t 4 (ACKEN) : Acknowledge Sequence Enable b i t ( In I2C Master mode o n l y ) : 0 : Acknowledge s e q u e n c e i d l e 1 : I n i t i a t e Acknowledge s e q u e n c e on SDA and SCL p i n s and t r a n s m i t ACKDT data b i t . A u t o m a t i c a l l y c l e a r e d by hardware B i t 3 (RCEN) : R e c e i v e Enable b i t ( In I2C Master mode o n l y ) 0 : Receive i d l e 1 : E n a b l e s R e c e i v e mode f o r I2C B i t 2 (PEN) : STOP C o n d i t i o n Enable b i t ( In I2C Master mode o n l y ) 0 : STOP c o n d i t i o n i d l e 1 : I n i t i a t e STOP c o n d i t i o n on SDA and SCL p i n s A u t o m a t i c a l l y c l e a r e d by hardware B i t 1 (RSEN) : Repeated START C o n d i t i o n Enable b i t ( In I2C Master mode o n l y ) 0 : Repeated START c o n d i t i o n i d l e 1 : I n i t i a t e Repeated START c o n d i t i o n on SDA and SCL p i n s A u t o m a t i c a l l y c l e a r e d by hardware B i t 0 (SEN) : START C o n d i t i o n Enable b i t ( In I2C Master mode o n l y ) 0 : START c o n d i t i o n i d l e 1 : I n i t i a t e START cond . on SDA and SCL p i n s A u t o m a t i c a l l y c l e a r e d by hardware ∗/ SSPSTAT = 0 b10000000 ; // I2C S l a v e A d r e s s e von Port B l e s e n und i n SSPADD s c h r e i b e n // H i e r 0 A5 A4 A3 A2 A1 A0 R/nW c I2 C A d r e s s e = 0 b00111111 ; // Maske c I2 C A d r e s s e = c I2 C A d r e s s e & PORTB; c I2 C A d r e s s e = c I2 C A d r e s s e << 1 ; c I2 C A d r e s s e . F0 = 0 ; // S c h r e i b z u g r i f f aus S i c h t d e s Master SSPADD = c I2 C A d r e s s e ; 19 5 DEMONSTRATIONSBEISPIELE 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 /∗ 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 // I n t e r r u p t f r e i g e b e n PIE1 = 0 b00001000 ; +−−−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−−−− |||||| |||||| +−−−−−−−−−−−−−−−−−−−− ||||| ||||| +−−−−−−−−−−−−−−−−−−− |||| |||| +−−−−−−−−−−−−−−−−−− ||| ||| ||| +−−−−−−−−−−−−−−−−− || || +−−−−−−−−−−−−−−−− Enable b i t | | +−−−−−−−−−−−−−−− bit // P e r i p h e r a l I n t e r r u p t Enable R e g i s t e r 1 ( Bank 1 ) Bit 7 Reserve B i t 6 (ADIE) : A/D C o n v e r te r I n t e r r u p t Enable b i t −> 0 : D i s a b l e s th e ADC i n t e r r u p t 1 : E n a b l e s th e ADC i n t e r r u p t B i t 5 (RCIE) : EUSART R e c e i v e I n t e r r u p t Enable b i t −> 0 : D i s a b l e s th e EUSART R e c e i v e I n t e r r u p t 1 : E n a b l e s th e EUSART R e c e i v e I n t e r r u p t B i t 4 (TXIE ) : EUSART Transmit I n t e r r u p t Enable b i t −> 0 : D i s a b l e s th e Transmit I n t e r r u p t Enable b i t 1 : E n a b l e s th e Transmit I n t e r r u p t Enable b i t B i t 3 ( SSPIE ) : Master Synchronous S e r i a l Port (MSSP) I n t e r r u p t Enable b i t 0 : D i s a b l e s th e MSSP i n t e r r u p t −> 1 : E n a b l e s th e MSSP i n t e r r u p t B i t 2 ( CCP1IF) : CCP1 I n t e r r u p t Enable b i t −> 0 : D i s a b l e s th e CCP1 i n t e r r u p t 1 : E n a b l e s th e CCP1 i n t e r r u p t B i t 1 (TMR2IE) : Timer 2 to PR2 Match I n t e r r u p t −> 0 : D i s a b l e s th e Timer 2 to PR2 Match I n t e r r u p t 1 : E n a b l e s th e Timer 2 to PR2 Match I n t e r r u p t B i t 0 (TMR1IE) : Timer 1 O v e r f l o w I n t e r r u p t Enable −> 0 : D i s a b l e s Timer 1 O v e r f l o w I n t e r r u p t 1 : E n a b l e s Timer 1 O v e r f l o w I n t e r r u p t ∗/ /∗ INTCON = 0 b11000000 ; // I n t e r r u p t −C o n tr o l −R e g i s t e r ( Bank 1 ) +−−−−−−−−−−−−−−−−−−−− B i t 7 ( GIE) : G l o b a l I n t e r r u p t Enable b i t ||||||| 0 : Disables a l l i nter r upts ||||||| −> 1 : E n a b l e s a l l unmasked i n t e r r u p t s +−−−−−−−−−−−−−−−−−−− B i t 6 ( PEIE ) : P e r i p h e r a l I n t e r r u p t Enable b i t |||||| 0 : Disables a l l peripheral i nter r upts |||||| −> 1 : E n a b l e s a l l unmasked p e r i p h e r a l i n t e r r u p t s +−−−−−−−−−−−−−−−−−− B i t 5 ( T0IE ) : Timer 0 O v e r f l o w I n t e r r u p t Enable B i t ||||| −> 0 : Disabled ||||| 1 : Enabled +−−−−−−−−−−−−−−−−− B i t 4 (INTE ) : RB0/INT E x t e r n a l I n t e r r u p t Enable B i t |||| −> 0 : Disabled |||| 1 : Enabled +−−−−−−−−−−−−−−−− B i t 3 (RPIE ) : RB Port Change I n t e r r u p t Enable B i t ||| −> 0 : Disabled ||| 1 : Enabled +−−−−−−−−−−−−−−− B i t 2 ( T0IF ) : Timer 0 O v e r f l o w I n t e r r u p t F l a g b i t || −> 0 : TMR0 r e g i s t e r d i d not o v e r f l o w || 1 : TMR0 r e g i s t e r has o v e r f l o w e d +−−−−−−−−−−−−−− B i t 1 (INTF) : RB0/INT E x t e r n a l I n t e r r u p t F l a g b i t | −> 0 : RB0/INT e x t e r n a l i n t e r r u p t d i d not o c c u r | 1 : RB0/INT e x t e r n a l i n t e r r u p t o c c u r r e d +−−−−−−−−−−−−− B i t 0 (RBIF ) : RB Port Change I n t e r r u p t F l a g b i t −> 0 : None o f RB7 : RB4 p i n s have changed s t a t e 1 : One o f th e RB7 : RB4 p i n s changed s t a t e ∗/ } /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ Hauptprogramm ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Aufgaben d e s Hauptprogramms : ∗/ /∗ + C o n t r o l l e r i n i t i a l i s i e r e n ( Unterprogramm I n i t ) ∗/ /∗ + A l l e s a n d e r e e r f o l g t i n d e r ISR ! ! ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ void main ( void ) { // C o n t r o l l e r i n i t i a l i s i e r e n Init () ; 5 DEMONSTRATIONSBEISPIELE 477 478 479 480 481 20 // E n d l o s s c h l e i f e while ( 1 ) ; } Listing 1: I2C Demo PIC Slave.c (Demo 1) 5.3 Anmerkungen zur Software für 1. Demo (Slave) Der Quellcode für dieses Demonstrationsbeispiel wurde in C mit der freien Demoversion des mikroC-Compilers erstellt7 . Die Software (für den PIC-I2 C-Slave) besteht im Wesentlichen aus den folgenden Programmteilen: • kurzes Hauptprogramm am Ende des Quellcodes, Zeilen 473 bis 481. • 1 Unterprogramm zur Initialisierung des PIC16F887 (Unterprogramm Init, Zeilen 152 bis 463). • kurze Interrupt-Service-Routine (kurz: ISR), Zeilen 79 bis 130. Hauptprogramm: Die Aufgabe des Hauptprogramms (Zeilen 473 bis 481) ist hier nur“ das Initialisieren ” des Mikrocontrollers. Dies erfolgt mit dem Unterprogramm Init (Zeile 476). Alles andere erfolgt in der Interrupt-Service-Routine (ISR). Unterprogramm Init: Das Unterprogramm Init (Zeilen 152 bis 463) dient zur Initialisierung des Mikrocontrollers. Hier werden die benötigten Hardwaremodule konfiguriert. Für den PIC-I2 C-Slave sind das zunächst der interne Oszillator (Zeile 158), sämtliche Ports als Ein- oder Ausgang kunfigurieren und als digitale Ein-/Ausgabepins konfigurieren (Zeilen 193 bis 292). Wichtig ist dass die Portpins (SDA und SCL) als Eingang konfiguriert werden. Ganz wichtig ist hier natürlich das SSP-Modul, denn dieses ist für die Kommunikation via I2 C zuständig. Im Register SSPCON wird u.a. ausgewählt dass der Mikrocontroller im I2 C-Slave-Mode betrieben wird (Zeile 296). Wichtig ist auch dass der I2 C-Slave über eine Slave-Adresse verfügt. Dafür ist das Register SSPADD zuständig. Da bei diesem Demonstrationsbeispiel die Slave-Adresse am Port B des Mikrocontrollers ausgewählt werden kann muss diese vom Port B gelesen werden und die entsprechenden Bits müssen in das Register SSPADD geschrieben werden. Beachte: Bit 0 gibt die Datenflussrichtung aus Sicht des Masters an (also Master schreibt Daten oder liest Daten, Zeilen 403 bis 407). Als letzter Schritt muss noch der SSP-Interrupt freigegeben werden. Bit SSPIE im Register PIE1 (Zeile 411). Weiters die Globale Interruptfreigabe (Bit GIE im Register INTCON), sowie das Bit PEIE ebenfalls im Register INTCON (Zeile 437). 7 Die freie Demoversion ist nur auf eine Programmspeichergröße von 2k begrenzt, ansonst voll kompatibel zur Vollversion. Die Demoversion ist auf der Firmen-Webseite [3] downloadbar 5 DEMONSTRATIONSBEISPIELE 21 Interrupt-Service-Routine (kurz: ISR): Die SSP-ISR (Zeilen 79 bis 130) wird jedesmal aufgerufen wenn ein gesamtes Datenbyte vom SSP-Hardware-Modul empfangen wurde und dieses für den PIC-Slave mit der Adresse im Register SSPADD bestimmt ist. Jedesmal wenn diese SSP-ISR aufgerufen wird muss eine der folgenden vier Fälle ausgeführt werden (vgl. Flussdiagramm in Abbildung 5, Seite 8 jedoch hier ohne Lese- und Schreibezeiger, da nur ein Datenbyte gelesen bzw. geschrieben (gesendet) wird.). Fall 1: Schreibzugriff aus Sicht des Masters, zuletzt wurde die Slave-Adresse empfangen (Bits: SSPSTAT.R W = 0, SSPSTAT.D A = 0): In diesem Fall muss der Mikrocontroller (Slave) die empfangenen Daten aus dem SSPBuffer (Register SSPBUF) lesen, kann den Inhalt von SSPBUF aber verwerfen, da es nur die Adresse und keine Daten enthält (Zeile 89). Hier wird der Inhalt von SSPBUF in ein Dummy-Register geschrieben. Wichtig ist das dass Register SSPBUF gelesen wird, weil dadurch Steuerbits für das Hardwaremodul verändert werden. Wichtig sind auch die folgenden Codezeilen 90 bis 93. Das SSP-Interrupt-Flag (SSPIF) muss ebenfalls gelöscht werden, da sonst dieser Interrupt sofort wieder ausgelöst wird! Fall 2: Schreibzugriff aus Sicht des Masters, zuletzt wurde ein Datenbyte empfangen (Bits: SSPSTAT.R W = 0, SSPSTAT.D A = 1): Jetzt handelt es sich tatsächlich um die Nutzdaten. Bei diesem Demonstrationsbeispiel wird nur ein 1 Datenbyte übertragen. Daher sind dies die einzigen Nutzdaten und können vom Register SSPBUF gelesen und in ein eigenes Register gespeichert werden, oder so wie hier direkt am Port D ausgegeben werden (Zeile 99). Auch hier sind die folgenden Codezeilen 101 bis 103 wichtig und dürfen nicht weggelassen werden! Fall 3: Lesezugriff aus Sicht des Masters, zuletzt wurde die Slave-Adresse empfangen (Bits: SSPSTAT.R W = 1, SSPSTAT.D A = 0): In diesem Fall müssen die zu sendenden Nutzdaten in das Register SSPBUF geschrieben werden. Hier, bei diesem Demonstrationsbeispiel ist dies der Inhalt von Port A (Zeile 114). Auch hier sind die folgenden Codezeilen 116 bis 118 wichtig und dürfen nicht weggelassen werden! Fall 4: Lesezugriff aus Sicht des Masters, zuletzt wurde ein Datenbyte gesendet (Bits: SSPSTAT.R W = 1, SSPSTAT.D A = 1): Meiner Ansicht nach dürfte bei diesem Demonstrationsbeispiel dieser Fall gar nicht auftreten, da vom Master nur ein Datenbyte gelesen werden darf. Daher wird in diesem Fall nur der Inhalt einer Dummy-Variable (cDummy) in das Register SSPBUF geschrieben (Zeile 124). Auch hier sind die folgenden Codezeilen 125 bis 127 wichtig und dürfen nicht weggelassen werden! Mehr als das Lesen des SSPBUF-Registers oder das Schreiben in das SSPBUF-Register ist in der Interrupt-Service-Routine (ISR) nicht zu tun. Alles andere übernimmt das HardwareModul SSP des Mikrocontrollers. 5 DEMONSTRATIONSBEISPIELE 22 Sonstiges: Am Beginn des Quellcodes befinden sich die folgenden Definitionen und Einstellungen: • Definition der globalen Register (hier nur cDummy, Zeile 37) • Die Funktionsprototypen für die hier verwendeten Unterprogramme (hier nur für das Unterprogramm Init, Zeile 59) • Ab Zeile 62 beginnt der Quellcode der ausreichend mit Kommentaren versehen ist Ein kleiner Nachteil beim mikroC-Compiler ist, dass die Konfigurationsbits für den PICMikrocontroller in der IDE gesetzt werden müssen. Ich persönlich würde diese lieber im Quellcode mit einer geeigneten Anweisung setzen. Hier sind die notwendigen Einstellungen für den PIC16F887 für dieses Demonstrationsbeispiel (für Slave und Master): ! ! ! ! ! ! ! ! ! ! ! ! ! INTOSCIO WDT OFF PWRTE OFF MCLRE ON CP OFF CPD OFF BOR OFF IESO OFF FCMEN OFF LVP OFF DEBUG OFF WRT OFF WRT 1FOURTH 5 DEMONSTRATIONSBEISPIELE 5.4 23 Software für 1. Demo (Master) Für den I2 C-Bus-Master wurde hier ebenfalls ein Mikrocontroller vom Typ PIC16F887 verwendet. Dieser hat hier folgende Aufgabe: Jedes mal wenn sich bei IC3 (PCF8574) zumindest ein Port-Pin (P0 bis P7) ändert erzeugt dieser Chip einen Interrupt, indem der Ausgang INT (Pin 13) den Pegel von High auf Low ändert. Daraufhin soll der Master diesen (geänderten) Eingang lesen und am PIC-I2 C-Slave (am Port D) ausgeben. Danach soll der Master die Daten vom PIC-I2 C-Slave (vom Port A) lesen und am IC4 (PCF8574) ausgeben. Der Quellcode für den I2 C-Bus-Master (mit dem PIC16F887, IC2) ist zur besseren Übersicht in mehrere Dateien aufgeteilt: • I2C Demo PIC Master.c beinhaltet das Hauptprogramm und das Unterprogramm zur Initialisierung des Mikrocontrollers (PIC16F887). • PCF8574.C beinhaltet die Unterprogramme zur Datenübertragung mit dem PCF8574. • PCF8574.H ist die Headerdatei zu PCF8574.C Zuerst die Datei I2C Demo PIC Master.c: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Demo z u r Ansteuerung d e s PIC16Fxx a l s I2C−S l a v e gemaess A p p l i c a t i o n Note AN734 ∗/ /∗ ∗/ /∗ Master ∗/ /∗ ∗/ /∗ Demo 1 : j e w e i l s nur e i n Byte vom Port B l e s e n und an den Master s e n d e n bzw . e i n ∗/ /∗ Byte vom Master l e s e n und am Port D a u s g e b e n ∗/ /∗ ∗/ /∗ M i k r o c o n t r o l l e r : PIC16F887 ∗/ /∗ Takt : i n t e r n e r Takt ( 4 , 0 MHz) ∗/ /∗ ∗/ /∗ Compiler : mikroC V8 . 2 ∗/ /∗ ∗/ /∗ E n t w i c k l e r : S t e f a n Buchgeher ∗/ /∗ E n t w i c k l u n g s b e g i n n d e r S o f t w a r e : 1 9 . Februar 2014 ∗/ /∗ F u n k t i o n s f a e h i g s e i t : 2 . Maerz 2014 ∗/ /∗ L e t z t e B e a r b e i t u n g : 4 . J u l i 2014 ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ I n c l u d e −D a te i e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ #include ”PCF8574.H” #include ”PCF8574A.H” /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ S t r u k t u r e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e S t r u k t u r e n v e r w e n d e t ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ E x te r n e R e g i s t e r ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e e x t e r n e n R e g i s t e r ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ B i t s i n den e x t e r n e n R e g i s t e r n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e e x t e r n e n R e g i s t e r ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ G l o b a l e R e g i s t e r ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e g l o b a l e n R e g i s t e r ∗/ 5 DEMONSTRATIONSBEISPIELE 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 24 /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ B i t s i n den g l o b a l e n R e g i s t e r n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e g l o b a l e n R e g i s t e r ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ P o r t b e l e g u n g ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ \INT−Ausgang d e s PCF8574 ∗/ #define nINTPCF8574 PORTC. F5 /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ Konstanten ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Konstanten f u e r I2C ∗/ #define noACK 0 #define ACK 1 /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ T a b e l l e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e T a b e l l e n ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ F u n k t i o n s p r o t o t y p e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Unterprogramm z u r I n i t i a l i s i e r u n g d e s M i k r o c c n t r o l l e r s ∗/ void I n i t ( void ) ; /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ Unterprogramme und Funktionen ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ I n i t : ∗/ /∗ ∗/ /∗ Aufgabe : ∗/ /∗ I n i t i a l i s i e r u n g des P r o z e s s o r : ∗/ /∗ + internen Os z i l l a to r konfigurieren ∗/ /∗ + Ports konf i gur i er en ∗/ /∗ ∗/ /∗ U e b e r g a b e p a r a m e te r : ∗/ /∗ keiner ∗/ /∗ ∗/ /∗ Rueckgabeparameter : ∗/ /∗ keiner ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ void I n i t ( void ) { // ( i n t e r n e n ) O s z i l l a t o r k o n f i g u r i e r e n OSCCON = 0 b01100001 ; // Sync O s c i l l a t o r C o n t r o l R e g i s t e r /∗ +−−−−−−−−−−−−−−−−−−−− B i t 7 R e s e r v e +++−−−−−−−−−−−−−−−−− B i t 6−4 ( IRCF2 : IRCF0 ) : I n t e r n a l O s c i l l a t o r Frequency |||| Select bits |||| 000 : 31 kHz (LFINTOSC) |||| 001 : 125 kHz |||| 010 : 250 kHz |||| 011 : 500 kHz |||| 100 : 1 MHz |||| 101 : 2 MHz |||| −> 110 : 4 MHz ( d e f a u l t ) |||| 111 : 8 MHz +−−−−−−−−−−−−−−−− B i t 3 (OSTS) : O s c i l l a t o r S t a r t −up Time−out S t a t u s ||| ( Read Only ) ||| 0 : D e v i c e i s r u n n i n g from th e c l o c k d e f i n e d ||| by FOSC2 : FOSC0 o f th e CONFIG1 r e g i s t e r ||| 1 : D e v i c e i s r u n n i n g from th e i n t e r n a l ||| oscillator (HFINTOSC o r LFINTOSC) +−−−−−−−−−−−−−−− B i t 2 (HTS) : HFINTOSC S t a t u s b i r || ( High Frequency − 125 kHz to 8MHz) || ( Read Only ) || 0 : HFINTOSC i s not s t a b l e || 1 : HFINTOSC i s s t a b l e +−−−−−−−−−−−−−− B i t 1 (LTS) : LFINTOSC S t a t u s b i t | (Low Frequency − 31kHz ) | ( Read Only ) 25 5 DEMONSTRATIONSBEISPIELE 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | 0 : LFINTOSC i s not s t a b l e | 1 : LFINTOSC i s s t a b l e +−−−−−−−−−−−−− B i t 0 (SCS ) : System Clock S e l e c t b i t 0 : Clock s o u r c e d e f i n e d by FOSC2 : FOSC0 o f th e CONFIG1 r e g i s t e r −> 1 : I n t e r n a l o s c i l l a t o r i s used f o r system clock ∗/ /∗ // P o r t s k o n f i g u r i e r e n TRISC = 0 b00100000 ; +−−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−− +−−−−−−−−−−−−−− // R i c h t u n g s r e g i s t e r B i t 7 Port RC7 : h i e r B i t 6 Port RC6 : h i e r B i t 5 Port RC5 : h i e r B i t 4 Port RC4 : h i e r B i t 3 Port RC3 : h i e r B i t 2 Port RC2 : h i e r B i t 1 Port RC1 : h i e r B i t 0 Port RC0 : h i e r Port C ( 0 : Ausgang , 1 : Eingang ) u n b e n u tz t u n b e n u tz t Eingang (/ INT ) Ausgang (SDA) Ausgang (SCL) u n b e n u tz t u n b e n u tz t u n b e n u tz t ∗/ } /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ Hauptprogramm ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Aufgaben d e s Hauptprogramms : ∗/ /∗ + C o n t r o l l e r i n i t i a l i s i e r e n ( Unterprogramm I n i t ) ∗/ /∗ + Takt f u e r I2C−Bus f e s t l e g e n ( h i e r 100 kHz mit dem Unterprogramm I 2 C I n i t ) ∗/ /∗ + 8−Bit−Wert vom Eingabemodul ( mit dem PCF8574 ) l e s e n und am I2C−PIC−S l a v e ∗/ /∗ ausgeben ∗/ /∗ + Daten vom I2C−PIC−S l a v e l e s e n und am I2C−LED−Modul ( mit einem w e i t e r e n PCF8574 ) ∗/ /∗ ausgeben ∗/ /∗ + T a e t i g k e i t e n / Unterprogramme , d i e a l l e z y k l i s c h d u r c h g e f u e h r t werden muessen : ∗/ /∗ + b e i jedem I n t e r r u p t d e s PCF8574 (A) d i e Daten vom Eingabemodul ( mit dem ∗/ /∗ PCF8574 ) l e s e n und am I2C−PIC−S l a v e a u s g e b e n . A n s c h l i e s s e n d Daten vom I2C− ∗/ /∗ PIC−S l a v e l e s e n und am LED−Ausgabemodul a u s g e b e n . ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ void main ( void ) { char cTemp ; // C o n t r o l l e r Init () ; initialisieren // I2C i n i t i a l i s i e r e n I2C Ini t (100000) ; // I2C−T a k t f r e q u e n z : 100 kHz // Demo 1 : 8−Bit−Wert vom I2C−Eingabemodul l e s e n . . . cTemp = I2C PCF8574 ReadData ( 1 ) ; // M o d u l a d r e s s e : h i e r 1 // . . . und am I2C−PIC−S l a v e a u s g e b e n I2C Start () ; // S t a r t b e d i n g u n g I2C Wr (0 b00110000 ) ; // B a u s t e i n a d r e s s e + S c h r e i b z u g r i f f I2C Wr ( cTemp ) ; // Daten an den PIC−S l a v e s c h r e i b e n I2 C S to p ( ) ; // S to p b e d i n g u n g // Demo 2 : Daten vom I2C−PIC−S l a v e l e s e n I2C Start () ; I2C Wr (0 b00110001 ) ; cTemp = I2C Rd (noACK) ; I2 C S to p ( ) ; // . . . und am I2C−LED−Modul a u s g e b e n cTemp = ˜cTemp ; I2C PCF8574 WriteData ( 3 , cTemp ) ; // E n d l o s s c h l e i f e while ( 1 ) { ... // // // // Startbedingung Bausteinadresse + L es e zu gr i f f Daten vom PIC−S l a v e l e s e n S to p b e d i n g u n g // M o d u l a d r e s s e : h i e r 3 5 DEMONSTRATIONSBEISPIELE 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 26 // b e i jedem I n t e r r u p t d e s PCF8574 (A) i f ( nINTPCF8574 == 0 ) { // Demo 1 : 8−Bit−Wert vom I2C−Eingabemodul l e s e n . . . cTemp = I2C PCF8574 ReadData ( 1 ) ; // M o d u l a d r e s s e : h i e r 1 // . . . und am I2C−PIC−S l a v e a u s g e b e n I2C Start () ; // S t a r t b e d i n g u n g I2C Wr (0 b00110000 ) ; // B a u s t e i n a d r e s s e + S c h r e i b z u g r i f f I2C Wr ( cTemp ) ; // Daten an den PIC−S l a v e s c h r e i b e n I2 C S to p ( ) ; // S to p b e d i n g u n g // Demo 2 : Daten vom I2C−PIC−S l a v e l e s e n . . . I2C Start () ; // S t a r t b e d i n g u n g I2C Wr (0 b00110001 ) ; // B a u s t e i n a d r e s s e + L e s e z u g r i f f cTemp = I2C Rd (noACK) ; // Daten vom PIC−S l a v e l e s e n I2 C S to p ( ) ; // S to p b e d i n g u n g // . . . und am I2C−LED−Modul a u s g e b e n cTemp = ˜cTemp ; I2C PCF8574 WriteData ( 3 , cTemp ) ; // M o d u l a d r e s s e : h i e r 3 } } } Listing 2: I2C Demo PIC Master.c (Demo 1) Datei PCF8574.H: 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Header f u e r d i e Unterprogramme z u r Ansteuerung d e s I /O−Port−Expander PCF8574 ∗/ /∗ ∗/ /∗ Compiler : mikroC V8 . 2 ∗/ /∗ ∗/ /∗ E n t w i c k l e r : S t e f a n Buchgeher ∗/ /∗ E n t w i c k l u n g s b e g i n n d e r S o f t w a r e : 1 7 . Februar 2013 ∗/ /∗ F u n k t i o n s f a e h i g s e i t : 1 7 . Februar 2013 ∗/ /∗ L e t z t e B e a r b e i t u n g : 1 7 . Februar 2013 ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ G l o b a l e R e g i s t e r ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e g l o b a l e n R e g i s t e r ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ P o r t b e l e g u n g ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e P o r t d e f i n i t i o n e n ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ Konstanten ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e Konstanten ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ F u n k t i o n s p r o t o t y p e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Daten zum I /O−Port−Expander PCF8574 s c h r e i b e n ∗/ void I2C PCF8574 WriteData ( char c D e v i c e A d r e s s e , char cWriteData ) ; /∗ Daten vom I /O−Port−Expander PCF8574 l e s e n ∗/ unsigned char I2C PCF8574 ReadData ( char c D e v i c e A d r e s s e ) ; Listing 3: PCF8574.H Datei PCF8574.C: 234 235 236 237 /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Unterprogramme z u r Ansteuerung d e s I /O−Port−Expander PCF8574 ∗/ /∗ ∗/ /∗ Compiler : mikroC V8 . 2 ∗/ 27 5 DEMONSTRATIONSBEISPIELE 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 /∗ ∗/ /∗ E n t w i c k l e r : S t e f a n Buchgeher ∗/ /∗ E n t w i c k l u n g s b e g i n n d e r S o f t w a r e : 1 7 . Februar 2013 ∗/ /∗ F u n k t i o n s f a e h i g s e i t : 1 7 . Februar 2013 ∗/ /∗ L e t z t e B e a r b e i t u n g : 1 7 . Februar 2013 ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ I n c l u d e −D a te i e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ #include ”PCF8574.H” #include ”PCF8574A.H” /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ S t r u k t u r e n /∗ k e i n e S t r u k t u r e n ∗/ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ G l o b a l e R e g i s t e r ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e g l o b a l e n R e g i s t e r ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ B i t s i n den g l o b a l e R e g i s t e r ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e g l o b a l e n R e g i s t e r ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ Konstanten ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ #define noACK 0 #define ACK 1 /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ T a b e l l e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e T a b e l l e n ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ F u n k t i o n s p r o t o t y p e n ( f u e r i n t e r n e H i l f s u n te r p r o g r a m m e ) ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e i n t e r n e n H i l f s u n te r p r o g r a m m e ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ Unterprogramme ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ I2C PCF8574 WriteData : ∗/ /∗ ∗/ /∗ Aufgabe : ∗/ /∗ Daten (8− Bit−Wert ) an den PCF8574 s c h r e i b e n ∗/ /∗ ∗/ /∗ U e b e r g a b e p a r a m e te r : ∗/ /∗ cDeviceAdresse B a u s t e i n a d r e s s e gemaess den g e s e t z t e n Jumper A0 b i s A2 ∗/ /∗ cWriteData Daten (8− Bit−Wert ) , w e l c h e an den PCF8574 g e s c h r i e b e n werden ∗/ /∗ ∗/ /∗ Rueckgabeparameter : ∗/ /∗ keiner ∗/ /∗ ∗/ /∗ V o r g e h e n s w e i s e : ∗/ /∗ S c h r i t t 1 : Die Device −A d r e s s s e e r m i t t e l n ∗/ /∗ S c h r i t t 2 : Daten (8− Bit−Wert ) an den PCF8574 s c h r e i b e n ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ void I2C PCF8574 WriteData ( char c D e v i c e A d r e s s e , char cWriteData ) { char c H e l p A d r e s s e = c D e v i c e A d r e s s e ; // S c h r i t t 1 : Device −A d r e s s e zusammensetzen c H e l p A d r e s s e = 0 b00000111 & c H e l p A d r e s s e ; c H e l p A d r e s s e = c H e l p A d r e s s e << 1 ; c H e l p A d r e s s e = 0 b01000000 | c H e l p A d r e s s e ; // B a u s t e i n a d r e s s e + S c h r e i b z u g r i f f // S c h r i t t 2 : Daten (8− Bit−Wert ) an den PCF8574 s c h r e i b e n I2C Start () ; // S t a r t b e d i n g u n g I2C Wr ( c H e l p A d r e s s e ) ; // B a u s t e i n a d r e s s e + S c h r e i b z u g r i f f I2C Wr ( cWriteData ) ; // Daten an den PCF8574 s c h r e i b e n I2 C S to p ( ) ; // S to p b e d i n g u n g } 28 5 DEMONSTRATIONSBEISPIELE 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ I2C PCF8574 ReadData : ∗/ /∗ ∗/ /∗ Aufgabe : ∗/ /∗ Daten (8− Bit−Wert ) vom PCF8574 l e s e n ∗/ /∗ ∗/ /∗ U e b e r g a b e p a r a m e te r : ∗/ /∗ cDeviceAdresse B a u s t e i n a d r e s s e gemaess den g e s e t z t e n Jumper A0 b i s A2 ∗/ /∗ ∗/ /∗ Rueckgabeparameter : ∗/ /∗ cReadData Daten (8− Bit−Wert ) , w e l c h e vom PCF8574 empfangen wurden ∗/ /∗ ∗/ /∗ V o r g e h e n s w e i s e : ∗/ /∗ S c h r i t t 1 : Die Device −A d r e s s s e e r m i t t e l n ∗/ /∗ S c h r i t t 2 : Daten (8− Bit−Wert ) vom PCF8574 l e s e n ∗/ /∗ S c h r i t t 3 : Empfangenen Wert an das a u f r u f e n d e Programm u e b e r g e b e n ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ unsigned char I2C PCF8574 ReadData ( char c D e v i c e A d r e s s e ) { char c H e l p A d r e s s e = c D e v i c e A d r e s s e ; char cReadData ; // S c h r i t t 1 : Device −A d r e s s e zusammensetzen c H e l p A d r e s s e = 0 b00000111 & c H e l p A d r e s s e ; c H e l p A d r e s s e = c H e l p A d r e s s e << 1 ; c H e l p A d r e s s e = 0 b01000001 | c H e l p A d r e s s e ; // B a u s t e i n a d r e s s e + L e s e z u g r i f f // S c h r i t t 2 : Daten (8− Bit−Wert ) vom PCF8574 l e s e n I2C Start () ; // S t a r t b e d i n g u n g I2C Wr ( c H e l p A d r e s s e ) ; // B a u s t e i n a d r e s s e + L e s e z u g r i f f cReadData = I2C Rd (noACK) ; I2 C S to p ( ) ; // S to p b e d i n g u n g // S c h r i t t 3 : Empfangenen Wert an das a u f r u f e n d e Programm u e b e r g e b e n return ( cReadData ) ; } Listing 4: PCF8574.C 5.5 Anmerkungen zur Software für 1. Demo (Master) Auch dieser Quellcode wurde in C mit der freien Demoversion des mikroC-Compilers erstellt. Die Software (für den PIC-I2 C-Master) besteht im Wesentlichen aus den folgenden Programmteilen: • Hauptprogramm am Ende des Quellcodes von I2C Demo PIC Master.c, Zeilen 148 bis 203. • 1 Unterprogramm zur Initialisierung des PIC16F887 (Unterprogramm Init in der Datei I2C Demo PIC Master.c, Zeilen 81 bis 130). • 2 Unterprogramme zur Kommunikation mit dem PCF8574 (I2C PCF8574 WriteData, Zeilen 293 bis 308 und I2C PCF8574 ReadData, Zeilen 330 bis 347 in der Datei PCF8574.C. 5 DEMONSTRATIONSBEISPIELE 29 Hauptprogramm: Zuerst muss der Mikrocontroller initialisiert werden. Diese Aufgabe übernehmen die Unterprogramme Init(), Zeile 153 und I2C Init(), Zeile 156. Danach werden zum ersten Mal die Portpins vom I2 C-Eingabemodul mit dem PCF8574 (IC3) gelesen und am I2 C-PIC-Slave ausgegeben. Das Lesen vom I2 C-Eingabemodul geschieht mit dem Unterprogramm I2C PCF8574 ReadData (Zeile 159). Übergabeparameter ist hier die Moduladresse (3-Bit entsprechend den Pins A2 bis A0). Hier der Wert 1, da A0 offen ist - also den Pegel High besitzt, während A1 und A2 via Jumper auf low-Pegel liegen (vgl. Schaltung in Abbildung 7, Seite 12). Für das Ausgeben der Daten am I2 C-PIC-Slave muss zunächst die I2 C-Startbedingung erzeugt werden (Zeile 161) anschließend die Adresse des I2 C-PIC-Slave inkl. Schreibzugriff (Zeile 162, hier 0b00110000 da die Jumper JP1, JP2, JP3 und JP6 gesetzt sind, siehe Abbildung 7 Seite 12. Das letzte niederwertigste Bit gibt die Zugriffsrichtung an. Hier 0 da es sich um einen Schreibzugriff aus Sicht des Masters handelt.) Anschließend werden die Daten an den I2 C-PIC-Slave geschrieben (Zeile 163) und zum Schluss die Stopbedingung (Zeile 164). Der umgekehrte Weg, also das Lesen von Daten vom I2 C-PIC-Slave und Ausgeben am I2 C-Ausgabemodul mit dem PCF8574 (IC4) ist ähnlich: Für das Lesen vom I2 C-PIC-Slave muss zunächst (wieder) die I2 C-Startbedingung erzeugt werden (Zeile 168) anschließend die Adresse des I2 C-PIC-Slave hier inkl. Lesezugriff (Zeile 169). Das letzte niederwertigste Bit ist hier 1 da es sich um einen Lesezugriff aus Sicht des Masters handelt. Gefolgt vom Lesen der Daten vom I2 C-PIC-Slave (Zeile 170) und zum Schluss wieder die Stopbedingung (Zeile 171). Der Übergabeparameter noACK bedeutet, dass keine weiteren Daten gelesen werden. Das Schreiben der gelesenen Daten (diese befinden sich im Register cTemp) am I2 CAusgabemodul erfolgt mit dem Unterprogramm I2C PCF8574 WriteData (Zeile 174). Übergabeparameter sind hier die Moduladresse (auch hier 3-Bit, entsprechend den Pins A2 bis A0. Hier der Wert 3, da A0 und A1 offen sind - also den Pegel High besitzen, während A2 via Jumper auf low-Pegel liegen) und die zu schreibenden Daten. Beachte. Die Leuchtdioden beim Ausgabemodul sind gegen +5V geschaltet. D.h. damit eine Leuchtdiode leuchtet muss am Portpin Px low anliegen. Daher muss das Register cTemp invertiert werden bevor es am I2 C-Ausgabemodul ausgegeben werden kann (Zeile 199). Nun befindet sich das Hauptprogramm in einer Endlosschleife. Jedesmal wenn am I2 CEingabemodul ein Portpin verändert wird erzeugt der PCF8574 einen so genannten Interrupt, indem der Pin 13 (INT) von High nach Low übergeht. Dieser Interrupt-Pin ist sozusagen die fünfte Leitung des I2 C-Buses und kann mit einem beliebigen I/O-Pin des Mikrocontrollers verbunden werden. Hier ist es der Portpin RC5 (vgl. Schaltbild nach Abbildung 7, Seite 12). In meiner Software erhält dieser Portpin die Bezeichnung nINTPCF8574 (Zeile 47). Immer wenn dieser Portpin low ist, also wenn am I2 C-Eingabemodul zumindest ein Portpin verändert wurde soll der geänderten Eingang gelesen und am PIC-I2 C-Slave ausgeben werden (Zeilen 184 bis 189). Danach sollen die Daten vom PIC-I2 C-Slave gelesen und am I2 C-Ausgabemodul ausgeben werden (Zeilen 193 bis 200). 5 DEMONSTRATIONSBEISPIELE 30 Hinweise: • Der Interrupt-Pin (INT, Pin 13) des PCF8574 geht in seinen Ruhepegel (High) über, nachdem sein Portzustand gelesen wurde. • Die Zeilen 184 bis 189 sind die gleichen wie 161 bis 164, und die Zeilen 193 bis 200 sind gleich mit den Zeilen 168 bis 174. Beachte: Die Unterprogramme und Funktionen I2c Init(), I2c Start(), I2c Stop(), I2c Wr() und I2c Rd() stellt der mikroC-Compiler zur Verfügung. Diese müssen hier nicht mittels include-Anweisung eingebunden werden. Diese Unterprogramme und Funktionen steuern dass SSP-Hardware-Modul im I2 C-Master-Mode. Unterprogramm Init: Das Unterprogramm Init (Datei: I2C Demo PIC Master.c, Zeilen 81 bis 130) dient zur Initialisierung des Mikrocontrollers. Hier wird der interne Oszillator konfiguriert (also auf 4MHz eingestellt, Zeile 84) und die Pins des Port C für den I2 C-Bus als Ein- oder Ausgang definiert (Zeile 120). Die anderen Ports (A, B, D und E) werden hier nicht benötigt, und müssen daher auch nicht konfiguriert werden. Im Gegensatz zum Slave muss hier das SSP-Hardware-Module für den Mastermode nicht initialisiert werden. Diese Aufgabe übernimmt das Unterprogramm I2c Init(), welches vom microC-Compiler zur Verfügung gestellt wird. Unterprogramme I2C PCF8574 WriteData und I2C PCF8574 ReadData: Das Unterprogramm I2C PCF8574 WriteData (Datei: PCF8574.C, Zeilen 293 bis 308) dient zum Schreiben eines 8-Bit-Wertes (Adresse oder Daten) zum PCF8574, während das Unterprogramm I2C PCF8574 ReadData (Datei: PCF8574.C, Zeilen 228 bis 347) einen 8-Bit-Wert vom PCF8574 liest. Aufgrund der Einfachheit und der ausführlichen Kommentare ist hier eine weitere Erklärung glaube ich nicht notwendig. Sonstiges: Am Beginn des Quellcodes (in der Datei I2C Demo PIC Master.c) befinden sich die folgenden Definitionen und Einstellungen: • Einbinden externer Codeteile (hier die Unterprogramme für den PCF8574, Zeile 21, oder alternativ die Unterprogramme für den PCF8574A, Zeile 22) • Portdefinition (hier für den INT-Ausgang des PCF8574, Zeilen 47) • Konstanten für I2 C (Zeilen 52 und 53) • Funktionsprototyp für das hier verwendete Unterprogramm (Zeile 62) • Ab Zeile 81 beginnt der Quellcode der ausreichend mit Kommentaren versehen ist 5 DEMONSTRATIONSBEISPIELE 31 Ein kleiner Nachteil beim mikroC-Compiler ist, dass die Konfigurationsbits für den PICMikrocontroller in der IDE gesetzt werden müssen. Ich persönlich würde diese lieber im Quellcode mit einer geeigneten Anweisung setzen. Hier sind die notwendigen Einstellungen für den PIC16F887 für dieses Demonstrationsbeispiel (für Master und Slave): ! ! ! ! ! ! ! ! ! ! ! ! ! 5.6 INTOSCIO WDT OFF PWRTE OFF MCLRE ON CP OFF CPD OFF BOR OFF IESO OFF FCMEN OFF LVP OFF DEBUG OFF WRT OFF WRT 1FOURTH Software für 2. Demo (Slave) Beim zweiten Demonstrationsbeispiel sendet der I2 C-Master mehrere Datenbytes (hier vier) zum PIC-I2 C-Slave, bzw. liest anschließend auch mehrere Datenbytes (auch vier) vom PIC-I2 C-Slave. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Demo z u r Ansteuerung d e s PIC16Fxx a l s I2C−S l a v e gemaess A p p l i c a t i o n Note AN734 ∗/ /∗ ∗/ /∗ S l a v e ∗/ /∗ ∗/ /∗ Demo 2 : e i n Byte vom Port A l e s e n und i n einem Array s p e i c h e r n . D i e s e s Array mit ∗/ /∗ w e i t e r e n b e l i e b i g e n Werten a u f f u e l l e n , und das gesamte Array v i a I2C an den ∗/ /∗ S l a v e s e n d e n . Ebenso e i n Array v i a I2C empfangen und das z u l e t z t empfangene ∗/ /∗ Byte am Port D a u s g e b e n . ∗/ /∗ ∗/ /∗ M i k r o c o n t r o l l e r : PIC16F887 ∗/ /∗ Takt : i n t e r n e r Takt ( 4 . 0 MHz) ∗/ /∗ ∗/ /∗ Compiler : mikroC V8 . 2 ∗/ /∗ ∗/ /∗ E n t w i c k l e r : S t e f a n Buchgeher ∗/ /∗ E n t w i c k l u n g s b e g i n n d e r S o f t w a r e : 2 . Maerz 2014 ∗/ /∗ F u n k t i o n s f a e h i g s e i t : 2 . Maerz 2014 ∗/ 5 DEMONSTRATIONSBEISPIELE 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 32 /∗ L e t z t e B e a r b e i t u n g : 4 . J u l i 2014 ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ I n c l u d e −D a te i e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e I n c l u d e −D a te i e n ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ S t r u k t u r e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e S t r u k t u r e n v e r w e n d e t ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ E x te r n e R e g i s t e r ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e e x t e r n e n R e g i s t e r ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ B i t s i n den e x t e r n e n R e g i s t e r n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e e x t e r n e n R e g i s t e r ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ G l o b a l e R e g i s t e r ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ char cDummy ; char char char char c I2 C R e a d B u f f e r [ ] = { 0 , 0 , 0 , 0 } ; cI2CWriteBuffer [ ] = {0 , 0 , 0 , 0}; c I2 C R e a d B u f f e r In d e x = 0 ; cI2CWriteBufferIndex = 0; /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ B i t s i n den g l o b a l e n R e g i s t e r n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e g l o b a l e n R e g i s t e r ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ P o r t b e l e g u n g ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ \INT−Ausgang d e s PCF8574 ∗/ //#d e f i n e nINTPCF8574 PORTC. F5 /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ Konstanten ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Konstanten I2C−S c h r e i b und L e s e b u f f e r ∗/ //#d e f i n e READBUFFERMAX 4 //#d e f i n e WRITEBUFFERMAX 4 /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ T a b e l l e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e T a b e l l e n ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ F u n k t i o n s p r o t o t y p e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Unterprogramm z u r I n i t i a l i s i e r u n g d e s M i k r o c c n t r o l l e r s ∗/ void I n i t ( void ) ; /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ I n t e r r u p t −S e r v i c e −R o u ti n e ( ISR ) ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ I n t e r r u p t S e r v i c e R o u ti n e : ∗/ /∗ ∗/ /∗ A u f r u f : ∗/ /∗ SSP I n t e r r u p t F l a g ( SSPIF ) , nach jedem I2C−Event ( wenn d e r Master e i n e A d r e s s e ∗/ /∗ a u f den I2C−Bus s c h r e i b t o d e r wenn s i c h Daten am I2C−Bus b e f i n d e n ∗/ /∗ ∗/ /∗ Aufgaben : ∗/ /∗ + Je nach S t a t u s s i n d u n t e r s c h i e d l i c h e Aktionen a u s z u f u e h r e n : s i e h e Kommentare im ∗/ /∗ Quellcode ∗/ /∗ + Nach j e d e r Aktion muss das SSP−I n t e r r u p t −F l a g SSPIF w i e d e r g e l o e s c h e n werden ∗/ /∗ ∗/ /∗ Achtung : ∗/ /∗ Der S t a t u s Lesen bzw . S c h r e i b e n e r f o l g t immer aus S i c h t d e s Master ! ! ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ void i n t e r r u p t ( void ) // I n t e r r u p t r o u t i n e { 5 DEMONSTRATIONSBEISPIELE 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 33 i f (SSPSTAT .R W == 0 ) { // S c h r e i b z u g r i f f e ( aus S i c h t d e s Masters , d . h . S l a v e muss Daten aus dem Sende− // und E m p f a n g s b u f f e r (SSPBUF) l e s e n ) i f (SSPSTAT . D A == 0 ) { // S t a t e 1 : I2C w r i t e o p e r a t i o n , l a s t b y te was an a d d r e s s b y te // SSPSTAT b i t s : S=1 , D/A=0 , R/W=0 , BF=1 cDummy = SSPBUF ; SSPSTAT . BF = 0 ; SSPCON.CKP = 1 ; // C l o c k s t r e t c h i n g e r l a u b e n cI2CWriteBufferIndex = 0; PIR1 . SSPIF = 0 ; // SSP−I n t e r r u p t −F l a g w i e d e r l o e s c h e n return ; } else { // S t a t e 2 : I2C w r i t e o p e r a t i o n , l a s t b y te was a data b y te // SSPSTAT b i t s : S=1 , D/A=1 , R/W=1 , BF=1 c I 2 C W r i t e B u f f e r [ c I 2 C W r i t e B u f f e r I n d e x ] = SSPBUF ; // Datenbyte von SSPBUF // l e s e n und i n s Array s c h r e i b e n cI2CWriteBufferIndex = cI2CWriteBufferIndex + 1; SSPCON.CKP = 1 ; // C l o c k s t r e t c h i n g e r l a u b e n PIR1 . SSPIF = 0 ; // SSP−I n t e r r u p t −F l a g w i e d e r l o e s c h e n return ; } } else { // L e s e z u g r i f f ( aus S i c h t d e s Masters , d . h . S l a v e muss Daten i n Sende− und // E m p f a n g s b u f f e r (SSPBUF) s c h r e i b e n ) i f (SSPSTAT . D A == 0 ) { // S t a t e 3 : I2C r e a d o p e r a t i o n , l a s t b y te was an a d d r e s s b y te // SSPSTAT b i t s : S=1 , D/A=0 , R/W=1 , BF=0 SSPBUF = c I2 C R e a d B u f f e r [ 0 ] ; // Datenbyte von Array l e s e n und i n SSPBUF c I2 C R e a d B u f f e r In d e x = 0 ; SSPCON.CKP = 1 ; // C l o c k s t r e t c h i n g e r l a u b e n PIR1 . SSPIF = 0 ; // SSP−I n t e r r u p t −F l a g w i e d e r l o e s c h e n return ; } else { // S t a t e 4 : I2C r e a d o p e r a t i o n , l a s t b y te was a data b y te // SSPSTAT b i t s : S=1 , D/A=1 , R/W=0 , BF=0 c I2 C R e a d B u f f e r In d e x = c I2 C R e a d B u f f e r In d e x + 1 ; SSPBUF = c I2 C R e a d B u f f e r [ c I2 C R e a d B u f f e r In d e x ] ; // Datenbyte von Array // l e s e n und i n SSPBUF SSPCON.CKP = 1 ; // C l o c k s t r e t c h i n g e r l a u b e n PIR1 . SSPIF = 0 ; // SSP−I n t e r r u p t −F l a g w i e d e r l o e s c h e n return ; } } } /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ Unterprogramme und Funktionen ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ I n i t : ∗/ /∗ ∗/ /∗ Aufgabe : ∗/ /∗ I n i t i a l i s i e r u n g des P r o z e s s o r : ∗/ /∗ + internen Os z i l l a to r konfigurieren ∗/ /∗ + P o r t s a u f D i g i t a l I /O u m s c h a l te n und a l s Ein− o d e r Ausgang k o n f i g u r i e r e n ∗/ /∗ + I2C−Hardware−Modul a l s S l a v e k o n f i g u r i e r e n ∗/ /∗ + I2C S l a v e A d r e s s e von Port B l e s e n und i n SSPADD s c h r e i b e n ∗/ /∗ + Interrupt freigeben ∗/ /∗ ∗/ /∗ U e b e r g a b e p a r a m e te r : ∗/ /∗ keiner ∗/ 5 DEMONSTRATIONSBEISPIELE 34 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 /∗ ∗/ /∗ Rueckgabeparameter : ∗/ /∗ keiner ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ void I n i t ( void ) { char c I2 C A d r e s s e ; // I2C−S l a v e −A d r e s s e 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 ∗/ /∗ /∗ // ( i n t e r n e n ) O s z i l l a t o r k o n f i g u r i e r e n OSCCON = 0 b01100001 ; // Sync O s c i l l a t o r C o n t r o l R e g i s t e r +−−−−−−−−−−−−−−−−−−−− B i t 7 R e s e r v e +++−−−−−−−−−−−−−−−−− B i t 6−4 ( IRCF2 : IRCF0 ) : I n t e r n a l O s c i l l a t o r Frequency |||| Select bits |||| 000 : 31 kHz (LFINTOSC) |||| 001 : 125 kHz |||| 010 : 250 kHz |||| 011 : 500 kHz |||| 100 : 1 MHz |||| 101 : 2 MHz |||| −> 110 : 4 MHz ( d e f a u l t ) |||| 111 : 8 MHz +−−−−−−−−−−−−−−−− B i t 3 (OSTS) : O s c i l l a t o r S t a r t −up Time−out S t a t u s ||| ( Read Only ) ||| 0 : D e v i c e i s r u n n i n g from th e c l o c k d e f i n e d ||| by FOSC2 : FOSC0 o f th e CONFIG1 r e g i s t e r ||| 1 : D e v i c e i s r u n n i n g from th e i n t e r n a l ||| oscillator (HFINTOSC o r LFINTOSC) +−−−−−−−−−−−−−−− B i t 2 (HTS) : HFINTOSC S t a t u s b i r || ( High Frequency − 125 kHz to 8MHz) || ( Read Only ) || 0 : HFINTOSC i s not s t a b l e || 1 : HFINTOSC i s s t a b l e +−−−−−−−−−−−−−− B i t 1 (LTS) : LFINTOSC S t a t u s b i t | (Low Frequency − 31kHz ) | ( Read Only ) | 0 : LFINTOSC i s not s t a b l e | 1 : LFINTOSC i s s t a b l e +−−−−−−−−−−−−− B i t 0 (SCS ) : System Clock S e l e c t b i t 0 : Clock s o u r c e d e f i n e d by FOSC2 : FOSC0 o f th e CONFIG1 r e g i s t e r −> 1 : I n t e r n a l o s c i l l a t o r i s used f o r system clock // A l l e P o r t s a u f d i g i t a l I /O k o n f i g u r i e r e n ANSEL = 0 b00000000 ; // Analog S e l e c t R e g i s t e r |||||||| // ( 0 : D i g i t a l I /O, 1 : A n a l o g e i n g a n g ) +−−−−−−−−−−−−−−−−−−−−− B i t 7 : Port RE2/AN7 i s t h i e r D i g i t a l I /O +−−−−−−−−−−−−−−−−−−−− B i t 6 : Port RE1/AN6 i s t h i e r D i g i t a l I /O +−−−−−−−−−−−−−−−−−−− B i t 5 : Port RE0/AN5 i s t h i e r D i g i t a l I /O +−−−−−−−−−−−−−−−−−− B i t 4 : Port RA5/AN4 i s t h i e r D i g i t a l I /O +−−−−−−−−−−−−−−−−− B i t 3 : Port RA3/AN3 i s t h i e r D i g i t a l I /O +−−−−−−−−−−−−−−−− B i t 2 : Port RA2/AN2 i s t h i e r D i g i t a l I /O +−−−−−−−−−−−−−−− B i t 1 : Port RA1/AN1 i s t h i e r D i g i t a l I /O +−−−−−−−−−−−−−− B i t 0 : Port RA0/AN0 i s t h i e r D i g i t a l I /O ∗/ /∗ ANSELH = 0 b00000000 ; |||||||| ++−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−− +−−−−−−−−−−−−−− +−−−−−−−−−−−−− // Analog S e l e c t R e g i s t e r // ( 0 : D i g i t a l I /O, 1 : A n a l o g e i n g a n g ) Bit 6 ,7 Reserve B i t 5 : Port RB5/AN13 i s t h i e r D i g i t a l I /O B i t 4 : Port RB0/AN12 i s t h i e r D i g i t a l I /O B i t 3 : Port RB4/AN11 i s t h i e r D i g i t a l I /O B i t 2 : Port RB1/AN10 i s t h i e r D i g i t a l I /O B i t 1 : Port RB9/AN9 i s t h i e r D i g i t a l I /O B i t 0 : Port RB2/AN8 i s t h i e r D i g i t a l I /O // P o r t s k o n f i g u r i e r e n TRISA = 0 b11111111 ; // R i c h t u n g s r e g i s t e r Port A ( 0 : Ausgang , 1 : Eingang ) ∗/ 35 5 DEMONSTRATIONSBEISPIELE 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 /∗ +−−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−− +−−−−−−−−−−−−−− Bit Bit Bit Bit Bit Bit Bit Bit 7 6 5 4 3 2 1 0 Port Port Port Port Port Port Port Port RA7 : RA6 : RA5 : RA4 : RA3 : RA2 : RA1 : RA0 : hier hier hier hier hier hier hier hier Eingang Eingang Eingang Eingang Eingang Eingang Eingang Eingang ( Jumper ( Jumper ( Jumper ( Jumper ( Jumper ( Jumper ( Jumper ( Jumper Pin Pin Pin Pin Pin Pin Pin Pin 7) 6) 5) 4) 3) 2) 1) 0) ∗/ /∗ TRISB = 0 b00111111 ; +−−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−− +−−−−−−−−−−−−−− // R i c h t u n g s r e g i s t e r B i t 7 Port RB7 : h i e r B i t 6 Port RB6 : h i e r B i t 5 Port RB5 : h i e r B i t 4 Port RB4 : h i e r B i t 3 Port RB3 : h i e r B i t 2 Port RB2 : h i e r B i t 1 Port RB1 : h i e r B i t 0 Port RB0 : h i e r Port B ( 0 : Ausgang , 1 : Eingang ) u n b e n u tz t u n b e n u tz t Eingang ( I2C−S l a v e −A d r e s s e A5) Eingang ( I2C−S l a v e −A d r e s s e A4) Eingang ( I2C−S l a v e −A d r e s s e A3) Eingang ( I2C−S l a v e −A d r e s s e A2) Eingang ( I2C−S l a v e −A d r e s s e A1) Eingang ( I2C−S l a v e −A d r e s s e A0) TRISC = 0 b00011000 ; +−−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−− +−−−−−−−−−−−−−− // R i c h t u n g s r e g i s t e r B i t 7 Port RC7 : h i e r B i t 6 Port RC6 : h i e r B i t 5 Port RC5 : h i e r B i t 4 Port RC4 : h i e r B i t 3 Port RC3 : h i e r B i t 2 Port RC2 : h i e r B i t 1 Port RC1 : h i e r B i t 0 Port RC0 : h i e r Port C ( 0 : Ausgang , 1 : Eingang ) u n b e n u tz t u n b e n u tz t u n b e n u tz t Eingang (SDA) Eingang (SCL) u n b e n u tz t u n b e n u tz t u n b e n u tz t TRISD = 0 b00000000 ; +−−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−− +−−−−−−−−−−−−−− // R i c h t u n g s r e g i s t e r B i t 7 Port RD7 : h i e r B i t 6 Port RD6 : h i e r B i t 5 Port RD5 : h i e r B i t 4 Port RD4 : h i e r B i t 3 Port RD3 : h i e r B i t 2 Port RD2 : h i e r B i t 1 Port RD1 : h i e r B i t 0 Port RD0 : h i e r Port D ( 0 : Ausgang , 1 : Eingang ) Ausgang (LED D7) Ausgang (LED D6) Ausgang (LED D5) Ausgang (LED D4) Ausgang (LED D3) Ausgang (LED D2) Ausgang (LED D1) Ausgang (LED D0) TRISE = 0 b00000000 ; |||||||| +−−−−−−−−−−−−−−−−−−−−− ||||||| ||||||| ||||||| ||||||| +−−−−−−−−−−−−−−−−−−−− |||||| |||||| |||||| |||||| +−−−−−−−−−−−−−−−−−−− ||||| ||||| ||||| ||||| ||||| +−−−−−−−−−−−−−−−−−− |||| |||| +−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−− +−−−−−−−−−−−−−− // R i c h t u n g s r e g i s t e r Port E ( 0 : Ausgang , 1 : Eingang ) // und P a r a l l e l S l a v e Port S t a t u s / C o n t r o l B i t s B i t 7 ( IBF ) : In p u t B u f f e r F u l l S t a t u s b i t ( Read o n l y ) 0 : No word has been r e c e i v e d 1 : A word has been r e c e i v e d and i s w a i t i n g to be r e a d by th e CPU B i t 6 (OBF) : Output B u f f e r F u l l S t a t u s b i t ( Read o n l y ) 0 : The o u tp u t b u f f e r has been r e a d 1 : The o u tp u t b u f f e r s t i l l h o l d s a p r e v i o u s l y w r i t t e n word B i t 5 (IBOV) : In p u t B u f f e r O v e r f l o w D e te c t b i t ( i n M i c r o p r o c e s s o r mode ) 0 : No o v e r f l o w o c c u r r e d 1 : A w r i t e o c c u r r e d when a p r e v i o u s l y i n p u t word has not been r e a d ( must be c l e a r e d in Software ) B i t 4 (PSPMODE) : P a r a l l e l S l a v e Port Mode S e l e c t −> 0 : PORTD f u n c t i o n s i n g e n e r a l Purpose I /O mode 1 : PORTD f u n c t i o n s i n P a r a l l e l S l a v e Port mode Bit 3 Reserve B i t 2 Port RE2 : h i e r u n b e n u tz t B i t 1 Port RE1 : h i e r u n b e n u tz t B i t 0 Port RE0 : h i e r u n b e n u tz t ∗/ /∗ ∗/ /∗ ∗/ /∗ ∗/ PORTA = 0 ; 5 DEMONSTRATIONSBEISPIELE 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 PORTB PORTC PORTD PORTE /∗ = = = = 36 0; 0; 0; 0; // I2C−Hardware−Modul a l s S l a v e k o n f i g u r i e r e n SSPCON = 0 b00100110 ; // Sync S e r i a l Port C o n t r o l R e g i s t e r 1 +−−−−−−−−−−−−−−−−−−−− B i t 7 (WCOL) : Write C o l l i s i o n D e te c t b i t ||||||| Master mode : ||||||| 0 : No c o l l i s i o n ||||||| 1 : A w r i t e to SSPBUF was attempt w h i l e th e I2C ||||||| c o n d i t i o n s were not v a l i s ||||||| S l a v e mode : ||||||| 0 : No c o l l i s i o n ||||||| 1 : SSPBUF r e g i s t e r i s w r i t t e n w h i l e s t i l l ||||||| t r a n s m i t t i n g th e p r e v i o u s word ( must be ||||||| cleared in software ) +−−−−−−−−−−−−−−−−−−− B i t 6 (SSPOV) : R e c e i v e O v e r f l o w I n d i c a t o r b i t |||||| 0 : No o v e r f l o w |||||| 1 : A new b y te i s r e c e i v e d w h i l e SSPBUF h o l d s |||||| p r e v i o u s data ( w e i t e r s i e h e D a t e n b l a t t ! ! ) |||||| ( must be c l e a r e d i n s o f t w a r e ) +−−−−−−−−−−−−−−−−−− B i t 5 (SSPEN ) : Synchronous S e r i a l Port Enable b i t ||||| 0 : D i s a b l e s s e r i a l p o r t and c o n f i g u r e s t h e s e ||||| P i n s a s I /O p o r t p i n s ||||| −> 1 : E n a b l e s th e s e r i a l p o r t an c o n f i g u r e s ||||| SCK, SDO, SDI , SS / SDA, SCL p i n s a s th e ||||| s o u r c e o f th e s e r i a l p o r t p i n s +−−−−−−−−−−−−−−−−− B i t 4 (CKP) : Clock P o l a r i t y S e l e c t b i t |||| In SPI mode : |||| 0 : I d l e s t a t e f o r c l o c k i s a low l e v e l |||| 1 : I d l e s t a t e f o r cl ock i s a high l e v e l |||| In I2C S l a v e mode : SCK r e l e a s e c o n t r o l |||| −> 0 : Holds c l o c k low ( c l o c k s t r e t c h ) . ( Used to |||| e n s u r e data s e t u p time . ) |||| 1 : Enable c l o c k |||| In I2C Master mode : Unused i n t h i s mode ++++−−−−−−−−−−−−− B i t 3−0 (SSPM3 : SSPM0) : SSP Mode S e l e c t b i t s 0000 : SPI Master mode , c l o c k = Fosc /4 0001 : SPI Master mode , c l o c k = Fosc /16 0010 : SPI Master mode , c l o c k = Fosc /64 0011 : SPI Master mode , c l o c k = TMR2 o u tp u t /2 0100 : SPI S l a v e mode , c l o c k = SCK pin , nSS p i n contr ol enabled 0101 : SPI S l a v e mode , c l o c k = SCK pin , nSS p i n c o n t r o l d i s a b l e d . nSS can be used a s I /O −> 0110 : I2C S l a v e mode , 7− b i t a d d r e s s 0111 : I2C S l a v e mode , 10− b i t a d d r e s s 1000 : I2C Master mode , c l o c k = Fosc / ( 4 ∗ ( SSPADD+1) ) 1001 : R e s e r v e d 1010 : R e s e r v e d 1011 : I2C Firmware C o n t r o l l e d Master mode ( slave idle ) 1100 : R e s e r v e d 1101 : R e s e r v e d 1110 : I2C Firmware C o n t r o l l e d Master mode , 7− b i t a d d r e s s with START and STOP b i t i n t e r r u p t s enabled 1111 : I2C Firmware C o n t r o l l e d Master mode , 10− b i t a d d r e s s with START and STOP b i t i n t e r r u p t s enabled ∗/ /∗ SSPCON2 = 0 b00110110 ; // Sync S e r i a l Port C o n t r o l R e g i s t e r 2 +−−−−−−−−−−−−−−−−−−− B i t 7 (GCEN) : G e n e r a l C a l l Enable b i t ( In I2C S l a v e ||||||| mode o n l y ) ||||||| −> 0 : General C a l l a d d r e s s d i s a b l e d ||||||| 1 : Enable i n t e r r u p t when a g e n e r a l c a l l ||||||| a d d r e s s (0 0 0 0 h ) i s t r e c e i v e d i n th e SSPSR 5 DEMONSTRATIONSBEISPIELE 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 +−−−−−−−−−−−−−−−−−− |||||| |||||| |||||| +−−−−−−−−−−−−−−−−− ||||| ||||| ||||| ||||| ||||| ||||| +−−−−−−−−−−−−−−−− |||| |||| |||| |||| |||| +−−−−−−−−−−−−−−− ||| ||| ||| +−−−−−−−−−−−−−− || || || || +−−−−−−−−−−−−− | | | | | +−−−−−−−−−−−− 37 B i t 6 (ACKSTAT) : Acknowledge S t a t u s b i t ( In I2C Master mode o n l y ) 0 : Acknowledge was r e c e i v e d from s l a v e 1 : Acknowledge was not r e c e i v e d from s l a v e B i t 5 (ACKDT) : Acknowledge Data b i t ( In I2C Master mode o n l y ) : Value t h a t w i l l be t r a n s m i t t e d when th e u s e r i n i z i a t e s an Acknowledge s e q u e n c e a t th e end of a r ecei ve 0 : Acknowledge 1 : Not Acknowledge B i t 4 (ACKEN) : Acknowledge Sequence Enable b i t ( In I2C Master mode o n l y ) : 0 : Acknowledge s e q u e n c e i d l e 1 : I n i t i a t e Acknowledge s e q u e n c e on SDA and SCL p i n s and t r a n s m i t ACKDT data b i t . A u t o m a t i c a l l y c l e a r e d by hardware B i t 3 (RCEN) : R e c e i v e Enable b i t ( In I2C Master mode o n l y ) 0 : Receive i d l e 1 : E n a b l e s R e c e i v e mode f o r I2C B i t 2 (PEN) : STOP C o n d i t i o n Enable b i t ( In I2C Master mode o n l y ) 0 : STOP c o n d i t i o n i d l e 1 : I n i t i a t e STOP c o n d i t i o n on SDA and SCL p i n s A u t o m a t i c a l l y c l e a r e d by hardware B i t 1 (RSEN) : Repeated START C o n d i t i o n Enable b i t ( In I2C Master mode o n l y ) 0 : Repeated START c o n d i t i o n i d l e 1 : I n i t i a t e Repeated START c o n d i t i o n on SDA and SCL p i n s A u t o m a t i c a l l y c l e a r e d by hardware B i t 0 (SEN) : START C o n d i t i o n Enable b i t ( In I2C Master mode o n l y ) 0 : START c o n d i t i o n i d l e 1 : I n i t i a t e START cond . on SDA and SCL p i n s A u t o m a t i c a l l y c l e a r e d by hardware ∗/ SSPSTAT = 0 b10000000 ; // I2C S l a v e A d r e s s e von Port B l e s e n und i n SSPADD s c h r e i b e n // H i e r 0 A5 A4 A3 A2 A1 A0 R/nW c I2 C A d r e s s e = 0 b00111111 ; // Maske c I2 C A d r e s s e = c I2 C A d r e s s e & PORTB; c I2 C A d r e s s e = c I2 C A d r e s s e << 1 ; c I2 C A d r e s s e . F0 = 0 ; // S c h r e i b z u g r i f f aus S i c h t d e s Master SSPADD = c I2 C A d r e s s e ; // D i v e r s e R e g i s t e r i n i t i a l i s i e r e n /∗ // I n t e r r u p t f r e i g e b e n PIE1 = 0 b00001000 ; +−−−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−−−− |||||| |||||| +−−−−−−−−−−−−−−−−−−−− ||||| ||||| +−−−−−−−−−−−−−−−−−−− |||| |||| +−−−−−−−−−−−−−−−−−− ||| ||| ||| +−−−−−−−−−−−−−−−−− || // P e r i p h e r a l I n t e r r u p t Enable R e g i s t e r 1 ( Bank 1 ) Bit 7 Reserve B i t 6 (ADIE) : A/D C o n v e r te r I n t e r r u p t Enable b i t −> 0 : D i s a b l e s th e ADC i n t e r r u p t 1 : E n a b l e s th e ADC i n t e r r u p t B i t 5 (RCIE) : EUSART R e c e i v e I n t e r r u p t Enable b i t −> 0 : D i s a b l e s th e EUSART R e c e i v e I n t e r r u p t 1 : E n a b l e s th e EUSART R e c e i v e I n t e r r u p t B i t 4 (TXIE ) : EUSART Transmit I n t e r r u p t Enable b i t −> 0 : D i s a b l e s th e Transmit I n t e r r u p t Enable b i t 1 : E n a b l e s th e Transmit I n t e r r u p t Enable b i t B i t 3 ( SSPIE ) : Master Synchronous S e r i a l Port (MSSP) I n t e r r u p t Enable b i t 0 : D i s a b l e s th e MSSP i n t e r r u p t −> 1 : E n a b l e s th e MSSP i n t e r r u p t B i t 2 ( CCP1IF) : CCP1 I n t e r r u p t Enable b i t −> 0 : D i s a b l e s th e CCP1 i n t e r r u p t 5 DEMONSTRATIONSBEISPIELE 444 445 || 1 : E n a b l e s th e CCP1 i n t e r r u p t +−−−−−−−−−−−−−−−− B i t 1 (TMR2IE) : Timer 2 to PR2 Match I n t e r r u p t Enable b i t | −> 0 : D i s a b l e s th e Timer 2 to PR2 Match I n t e r r u p t | 1 : E n a b l e s th e Timer 2 to PR2 Match I n t e r r u p t +−−−−−−−−−−−−−−− B i t 0 (TMR1IE) : Timer 1 O v e r f l o w I n t e r r u p t Enable bit −> 0 : D i s a b l e s Timer 1 O v e r f l o w I n t e r r u p t 1 : E n a b l e s Timer 1 O v e r f l o w I n t e r r u p t 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 38 ∗/ /∗ INTCON = 0 b11000000 ; // I n t e r r u p t −C o n tr o l −R e g i s t e r ( Bank 1 ) +−−−−−−−−−−−−−−−−−−−− B i t 7 ( GIE) : G l o b a l I n t e r r u p t Enable b i t ||||||| 0 : Disables a l l i nter r upts ||||||| −> 1 : E n a b l e s a l l unmasked i n t e r r u p t s +−−−−−−−−−−−−−−−−−−− B i t 6 ( PEIE ) : P e r i p h e r a l I n t e r r u p t Enable b i t |||||| 0 : Disables a l l peripheral i nter r upts |||||| −> 1 : E n a b l e s a l l unmasked p e r i p h e r a l i n t e r r u p t s +−−−−−−−−−−−−−−−−−− B i t 5 ( T0IE ) : Timer 0 O v e r f l o w I n t e r r u p t Enable B i t ||||| −> 0 : Disabled ||||| 1 : Enabled +−−−−−−−−−−−−−−−−− B i t 4 (INTE ) : RB0/INT E x t e r n a l I n t e r r u p t Enable B i t |||| −> 0 : Disabled |||| 1 : Enabled +−−−−−−−−−−−−−−−− B i t 3 (RPIE ) : RB Port Change I n t e r r u p t Enable B i t ||| −> 0 : Disabled ||| 1 : Enabled +−−−−−−−−−−−−−−− B i t 2 ( T0IF ) : Timer 0 O v e r f l o w I n t e r r u p t F l a g b i t || −> 0 : TMR0 r e g i s t e r d i d not o v e r f l o w || 1 : TMR0 r e g i s t e r has o v e r f l o w e d +−−−−−−−−−−−−−− B i t 1 (INTF) : RB0/INT E x t e r n a l I n t e r r u p t F l a g b i t | −> 0 : RB0/INT e x t e r n a l i n t e r r u p t d i d not o c c u r | 1 : RB0/INT e x t e r n a l i n t e r r u p t o c c u r r e d +−−−−−−−−−−−−− B i t 0 (RBIF ) : RB Port Change I n t e r r u p t F l a g b i t −> 0 : None o f RB7 : RB4 p i n s have changed s t a t e 1 : One o f th e RB7 : RB4 p i n s changed s t a t e ∗/ } /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ Hauptprogramm ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Aufgaben d e s Hauptprogramms : ∗/ /∗ + C o n t r o l l e r i n i t i a l i s i e r e n ( Unterprogramm I n i t ) ∗/ /∗ + Aufgaben i n d e r E n d l o s s c h l e i f e : ∗/ /∗ + Daten vom emfangenen Array am Port D a u s g g e b e n ( h i e r nur das l e t z t e Daten− ∗/ /∗ b y te ∗/ /∗ + Daten vom Port A e i n l e s e n und i n einem Demo−Array s p e i c h e r n ( d i e n t h i e r ∗/ /∗ nur z u r D e m o n s tr a ti o n ! ) ∗/ /∗ + A l l e s a n d e r e e r f o l g t i n d e r ISR ! ! ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ void main ( void ) { // C o n t r o l l e r i n i t i a l i s i e r e n Init () ; // E n d l o s s c h l e i f e while ( 1 ) { PORTD = c I 2 C W r i t e B u f f e r [ 3 ] ; c I2 C R e a d B u f f e r [ 0 ] c I2 C R e a d B u f f e r [ 1 ] c I2 C R e a d B u f f e r [ 2 ] c I2 C R e a d B u f f e r [ 3 ] = = = = PORTA; 0 b00111100 ; 0 b01010011 ; PORTA; } } Listing 5: I2C Demo PIC Slave.c (Demo 2) 5 DEMONSTRATIONSBEISPIELE 5.7 39 Anmerkungen zur Software für 2. Demo (Slave) Auch bei diesem zweiten Demonstrationsbeispiel wurde der Quellcode in C mit der freien Demoversion des mikroC-Compilers erstellt, und die Software für den PIC-I2 C-Slave besteht aus den gleichen, aber angepassten, Programmteilen wie beim ersten Demonstrationsbeispiel. Nämlich aus: • kurzes Hauptprogramm am Ende des Quellcodes, Zeilen 494 bis 510. • 1 Unterprogramm zur Initialisierung des PIC16F887 (Unterprogramm Init, Zeilen 165 bis 479). • kurze Interrupt-Service-Routine (kurz: ISR), Zeilen 88 bis 143. Wichtig zu erwähnen ist, dass es bei diesem zweiten Demonstrationsbeispiel zweckmäßig ist die empfangenen Daten und die zu sendenden Daten in je einem Array zu speichern (hier: cI2CReadBuffer[] und cI2CWriteBuffer[]). Hauptprogramm: Die Aufgabe des Hauptprogramms (Zeilen 494 bis 510) ist hier zunächst das Initialisieren des Mikrocontrollers. Dies erfolgt mit dem Unterprogramm Init (Zeile 497). Das Bereitstellen der zu übertragenden Daten und die Weiterverarbeitung der empfangenen Daten erfolgt in der Endlosschleife. Bei diesem Demonstrationsbeispiel soll nur das vierte empfange Byte am Port D ausgegeben werden (Zeile 503), während der Zustand von Port A zweimal zum I2 C-Master übertragen werden soll. Das zweite und dritte Datenbyte sind hier beliebige konstante Werte (Zeilen 505 bis 508). Alles andere erfolgt in der Interrupt-Service-Routine (ISR). Beachte: Die Bezeichnungen der Variablen cI2CReadBuffer[] und cI2CWriteBuffer[]) erfolgen aus Sicht des Masters! Unterprogramm Init: Das Unterprogramm Init (Zeilen 165 bis 479) dient auch hier zur Initialisierung des Mikrocontrollers. Es ist gleich wie beim ersten Demonstrationsbeispiel (siehe Abschnitt 5.3 ab Seite 20). Interrupt-Service-Routine (kurz: ISR): Die SSP-ISR (Zeilen 88 bis 143) wird auch hier jedesmal aufgerufen wenn ein gesamtes Datenbyte vom SSP-Hardware-Modul empfangen wurde und dieses für den PIC-Slave mit der Adresse im Register SSPADD bestimmt ist. Jedes mal wenn diese SSP-ISR aufgerufen wird muss eine der folgenden vier Fälle ausgeführt werden (vgl. Flussdiagramm in Abbildung 5, Seite 8). Im Gegensatz zum ersten Demonstrationsbeispiel müssen hier auch die Lese- und Schreibezeiger richtig behandelt werden, da hier mehr als ein Datenbyte gelesen bzw. geschrieben (gesendet) werden). 5 DEMONSTRATIONSBEISPIELE 40 Fall 1: Schreibzugriff aus Sicht des Masters, zuletzt wurde die Slave-Adresse empfangen (Bits: SSPSTAT.R W = 0, SSPSTAT.D A = 0): In diesem Fall muss der Mikrocontroller (Slave) die empfangenen Daten aus dem SSPBuffer (Register SSPBUF) lesen kann den Inhalt von SSPBUF aber verwerfen, da es nur die Adresse und keine Daten enthält (Zeile 98). Hier wird der Inhalt von SSPBUF in ein Dummy-Register geschrieben. Wichtig ist das dass Register SSPBUF gelesen wird, weil dadurch Steuerbits für das Hardwaremodul verändert werden. Neu ist bei diesem Demonstrationsbeispiel das Initialisieren des Schreib-Zeiger cI2CWriteBufferIndex (aus Sicht des Masters, Zeile 101). Wichtig sind auch hier die folgenden Codezeilen 99 und 100. Das SSP-Interrupt-Flag SSPIF muss ebenfalls gelöscht werden, da sonst dieser Interrupt sofort wieder ausgelöst wird (Zeile 102)! Fall 2: Schreibzugriff aus Sicht des Masters, zuletzt wurde ein Datenbyte empfangen (Bits: SSPSTAT.R W = 0, SSPSTAT.D A = 1): Jetzt handelt es sich tatsächlich um Nutzdaten. Diese befinden sich im SSP-BufferRegister SSPBUF. Daher den Inhalt dieses Registers in das eigene Array cI2CWriteBuffer[] an der Stelle auf den der Index-Zeiger cI2CWriteBufferIndex zeigt schreiben (Zeile 109). Diesen Index-Zeiger anschließend um eins erhöhen (Zeile 111), damit beim nächsten Aufruf dieser ISR der nächste empfangene Wert an die nächste Stelle im Array cI2CWriteBuffer[] geschrieben wird. Auch hier sind die folgenden Codezeilen 112 bis 114 wichtig und dürfen nicht weggelassen werden! Fall 3: Lesezugriff aus Sicht des Masters, zuletzt wurde die Slave-Adresse empfangen (Bits: SSPSTAT.R W = 1, SSPSTAT.D A = 0): In diesem Fall muss das erste zu sendende Datenbyte in das Register SSPBUF geschrieben werden. Daher das erste Datenbyte (mit dem Index 0) vom eigene Array cI2CReadBuffer[] lesen und in das Register SSPBUF schreiben (Zeile 125). Als nächstes den Lese-Zeiger (aus Sicht des Masters) cI2CReadBufferIndex initialisieren (Zeile 126). Auch hier sind die folgenden Codezeilen 127 bis 129 wichtig und dürfen nicht weggelassen werden! Fall 4: Lesezugriff aus Sicht des Masters, zuletzt wurde ein Datenbyte gesendet (Bits: SSPSTAT.R W = 1, SSPSTAT.D A = 1): Im Gegensatz zum ersten Demonstrationsbeispiel tritt hier auch dieser Fall auf. Hier muss zunächst der Lese-Index-Zeiger cI2CReadBufferIndex um eins erhöht werden (Zeile 135). Anschließend den Inhalt des Lesearray, auf den der Lesezeiger zeigt lesen und in das Register SSPBUF schreiben (Zeile 136). Auch hier sind die folgenden Codezeilen 138 bis 140 wichtig und dürfen nicht weggelassen werden! Mehr als das Lesen des SSPBUF-Registers oder das Schreiben in das SSPBUF-Register ist auch bei diesem zweiten Demonstrationsbeispiel in der Interrupt-Service-Routine (ISR) nicht zu tun. Alles andere übernimmt auch hier das Hardware-Modul SSP des Mikrocontrollers. 5 DEMONSTRATIONSBEISPIELE 41 Sonstiges: Am Beginn des Quellcodes befinden sich die folgenden Definitionen und Einstellungen: • Definition der globalen Register (hier cDummy, Zeile 37, sowie die Arrays zum speichern der gesendeten und empfangenen Daten (Zeilen 41 und 42) und die IndexZeiger (Zeilen 43 und 44) • Funktionsprototyp für das hier verwendete Unterprogramm (Init, Zeile 68) • Ab Zeile 88 beginnt der Quellcode der ausreichend mit Kommentaren versehen ist Die Konfigurationsbits für den PIC16F887-Mikrocontroller sind hier gleich wie beim ersten Demonstrationsbeispiel. 5.8 Software für 2. Demo (Master) Natürlich müssen auch beim Master Änderungen vorgenommen werden. Auch bei diesem zweiten Demonstrationsbeispiel ist der Quellcode für den I2 C-Bus-Master (mit dem PIC16F887, IC2) zur besseren Übersicht in mehrere Dateien aufgeteilt: • I2C Demo PIC Master.c beinhaltet das Hauptprogramm und das Unterprogramm zur Initialisierung des Mikrocontrollers (PIC16F887). • PCF8574.C beinhaltet die Unterprogramme zur Datenübertragung mit dem PCF8574. • PCF8574.H ist die Headerdatei zu PCF8574.C Die Dateien PCF8574.C und PCF8574.H unterscheiden sich nicht zum ersten Demonstrationsbeispiel und werden hier daher auch nicht mehr behandelt. Hier die Datei I2C Demo PIC Master.c (für das zweite Demonstrationsbeispiel): 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Demo z u r Ansteuerung d e s PIC16Fxx a l s I2C−S l a v e gemaess A p p l i c a t i o n Note AN734 ∗/ /∗ ∗/ /∗ Master ∗/ /∗ ∗/ /∗ Demo 2 : e i n Byte vom Port B l e s e n und i n einem Array s p e i c h e r n . D i e s e Array mit ∗/ /∗ w e i t e r e n b e l i e b i g e n Werten a u f f u e l l e n , und da gesamte Array v i a I2C an den ∗/ /∗ S l a v e s e n d e n . Ebenso e i n Array v i a I2C empfangen und das z u l e t z t empfangene ∗/ /∗ Byte am Port D a u s g e b e n . ∗/ /∗ ∗/ /∗ M i k r o c o n t r o l l e r : PIC16F887 ∗/ /∗ Takt : i n t e r n e r Takt ( 4 . 0 MHz) ∗/ /∗ ∗/ /∗ Compiler : mikroC V8 . 2 ∗/ /∗ ∗/ /∗ E n t w i c k l e r : S t e f a n Buchgeher ∗/ /∗ E n t w i c k l u n g s b e g i n n d e r S o f t w a r e : 2 . Maerz 2014 ∗/ /∗ F u n k t i o n s f a e h i g s e i t : 2 . Maerz 2014 ∗/ /∗ L e t z t e B e a r b e i t u n g : 4 . J u l i 2014 ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ I n c l u d e −D a te i e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ 5 DEMONSTRATIONSBEISPIELE 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 42 #include ”PCF8574.H” #include ”PCF8574A.H” /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ S t r u k t u r e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e S t r u k t u r e n v e r w e n d e t ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ E x te r n e R e g i s t e r ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e e x t e r n e n R e g i s t e r ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ B i t s i n den e x t e r n e n R e g i s t e r n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e e x t e r n e n R e g i s t e r ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ G l o b a l e R e g i s t e r ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e g l o b a l e n R e g i s t e r ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ B i t s i n den g l o b a l e n R e g i s t e r n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e g l o b a l e n R e g i s t e r ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ P o r t b e l e g u n g ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ \INT−Ausgang d e s PCF8574 ∗/ #define nINTPCF8574 PORTC. F5 /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ Konstanten ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Konstanten f u e r I2C ∗/ #define noACK 0 #define ACK 1 /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ T a b e l l e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ k e i n e T a b e l l e n ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ F u n k t i o n s p r o t o t y p e n ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Unterprogramm z u r I n i t i a l i s i e r u n g d e s M i k r o c c n t r o l l e r s ∗/ void I n i t ( void ) ; /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ Unterprogramme und Funktionen ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ I n i t : ∗/ /∗ ∗/ /∗ Aufgabe : ∗/ /∗ I n i t i a l i s i e r u n g des P r o z e s s o r : ∗/ /∗ + internen Os z i l l a to r konfigurieren ∗/ /∗ + Ports konf i gur i er en ∗/ /∗ ∗/ /∗ U e b e r g a b e p a r a m e te r : ∗/ /∗ keiner ∗/ /∗ ∗/ /∗ Rueckgabeparameter : ∗/ /∗ keiner ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ void I n i t ( void ) { // ( i n t e r n e n ) O s z i l l a t o r k o n f i g u r i e r e n OSCCON = 0 b01100001 ; // Sync O s c i l l a t o r C o n t r o l R e g i s t e r /∗ +−−−−−−−−−−−−−−−−−−−− B i t 7 R e s e r v e +++−−−−−−−−−−−−−−−−− B i t 6−4 ( IRCF2 : IRCF0 ) : I n t e r n a l O s c i l l a t o r Frequency |||| Select bits |||| 000 : 31 kHz (LFINTOSC) |||| 001 : 125 kHz |||| 010 : 250 kHz |||| 011 : 500 kHz 43 5 DEMONSTRATIONSBEISPIELE 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |||| |||| |||| |||| +−−−−−−−−−−−−−−−− ||| ||| ||| ||| ||| +−−−−−−−−−−−−−−− || || || || +−−−−−−−−−−−−−− | | | | +−−−−−−−−−−−−− 100 : 1 MHz 101 : 2 MHz −> 110 : 4 MHz ( d e f a u l t ) 111 : 8 MHz B i t 3 (OSTS) : O s c i l l a t o r S t a r t −up Time−out S t a t u s ( Read Only ) 0 : D e v i c e i s r u n n i n g from th e c l o c k d e f i n e d by FOSC2 : FOSC0 o f th e CONFIG1 r e g i s t e r 1 : D e v i c e i s r u n n i n g from th e i n t e r n a l oscillator (HFINTOSC o r LFINTOSC) B i t 2 (HTS) : HFINTOSC S t a t u s b i r ( High Frequency − 125 kHz to 8MHz) ( Read Only ) 0 : HFINTOSC i s not s t a b l e 1 : HFINTOSC i s s t a b l e B i t 1 (LTS) : LFINTOSC S t a t u s b i t (Low Frequency − 31kHz ) ( Read Only ) 0 : LFINTOSC i s not s t a b l e 1 : LFINTOSC i s s t a b l e B i t 0 (SCS ) : System Clock S e l e c t b i t 0 : Clock s o u r c e d e f i n e d by FOSC2 : FOSC0 o f th e CONFIG1 r e g i s t e r −> 1 : I n t e r n a l o s c i l l a t o r i s used f o r system clock ∗/ /∗ // P o r t s k o n f i g u r i e r e n TRISC = 0 b00100000 ; +−−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−−− +−−−−−−−−−−−−−−− +−−−−−−−−−−−−−− // R i c h t u n g s r e g i s t e r B i t 7 Port RC7 : h i e r B i t 6 Port RC6 : h i e r B i t 5 Port RC5 : h i e r B i t 4 Port RC4 : h i e r B i t 3 Port RC3 : h i e r B i t 2 Port RC2 : h i e r B i t 1 Port RC1 : h i e r B i t 0 Port RC0 : h i e r Port C ( 0 : Ausgang , 1 : Eingang ) u n b e n u tz t u n b e n u tz t Eingang (/ INT ) Ausgang (SDA) Ausgang (SCL) u n b e n u tz t u n b e n u tz t u n b e n u tz t ∗/ } /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ Hauptprogramm ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ /∗ Aufgaben d e s Hauptprogramms : ∗/ /∗ + C o n t r o l l e r i n i t i a l i s i e r e n ( Unterprogramm I n i t ) ∗/ /∗ + Takt f u e r I2C−Bus f e s t l e g e n ( h i e r 100 kHz mit dem Unterprogramm I 2 C I n i t ) ∗/ /∗ + 8−Bit−Wert vom Eingabemodul ( mit dem PCF8574 ) l e s e n und insgesammt v i e r Byte an ∗/ /∗ den I2C−PIC−S l a v e s e n d e n ∗/ /∗ + Daten (4 Byte ) vom I2C−PIC−S l a v e l e s e n und das v i e r t e Byte am I2C−LED−Modul ∗/ /∗ ( mit einem w e i t e r e n PCF8574 ) a u s g e b e n ∗/ /∗ + T a e t i g k e i t e n / Unterprogramme , d i e a l l e z y k l i s c h d u r c h g e f u e h r t werden muessen : ∗/ /∗ + b e i jedem I n t e r r u p t d e s PCF8574 (A) d i e Daten vom Eingabemodul ( mit dem ∗/ /∗ PCF8574 ) l e s e n und ( w i e d e r ) v i e r Byte am I2C−PIC−S l a v e a u s g e b e n . A n s c h l i e s − ∗/ /∗ send Daten (4 Byte ) vom I2C−PIC−S l a v e l e s e n und das v i e r t e Byte am I2C−LED− ∗/ /∗ Modul a u s g e b e n . ∗/ /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ void main ( void ) { char cTemp ; char cTemp1 ; char cTemp2 ; char cTemp3 ; char cTemp4 ; // C o n t r o l l e r Init () ; initialisieren // I2C i n i t i a l i s i e r e n I2C Ini t (100000) ; // I2C−T a k t f r e q u e n z : 100 kHz 44 5 DEMONSTRATIONSBEISPIELE 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 // Demo 1 : 8−Bit−Wert vom I2C−Eingabemodul l e s e n . . . cTemp = I2C PCF8574 ReadData ( 1 ) ; // M o d u l a d r e s s e : h i e r 1 // . . . und am I2C−PIC−S l a v e a u s g e b e n I2C Start () ; // S t a r t b e d i n g u n g I2C Wr (0 b00110000 ) ; // B a u s t e i n a d r e s s e + S c h r e i b z u g r i f f I2C Wr ( cTemp ) ; // 4 Datenbyte I2C Wr (0 b00001111 ) ; // an den I2C Wr (0 b11001100 ) ; // PIC−S l a v e I2C Wr ( cTemp ) ; // schreiben I2 C S to p ( ) ; // S to p b e d i n g u n g // Demo 2 : Daten vom I2C−PIC−S l a v e l e s e n I2C Start () ; I2C Wr (0 b00110001 ) ; cTemp1 = I2C Rd (ACK) ; cTemp2 = I2C Rd (ACK) ; cTemp3 = I2C Rd (ACK) ; cTemp4 = I2C Rd (noACK) ; I2 C S to p ( ) ; // . . . und am I2C−LED−Modul a u s g e b e n cTemp4 = ˜cTemp4 ; I2C PCF8574 WriteData ( 3 , cTemp4 ) ; ... // // // // // // // Startbedingung Bausteinadresse + L es e zu gr i f f Daten vom PIC−S l a v e lesen S to p b e d i n g u n g // M o d u l a d r e s s e : h i e r 3 // E n d l o s s c h l e i f e while ( 1 ) { // b e i jedem I n t e r r u p t d e s PCF8574 (A) i f ( nINTPCF8574 == 0 ) { // Demo 1 : 8−Bit−Wert vom I2C−Eingabemodul l e s e n . . . cTemp = I2C PCF8574 ReadData ( 1 ) ; // M o d u l a d r e s s e : h i e r 1 // . . . und am I2C−PIC−S l a v e a u s g e b e n I2C Start () ; // S t a r t b e d i n g u n g I2C Wr (0 b00110000 ) ; // B a u s t e i n a d r e s s e + S c h r e i b z u g r i f f I2C Wr ( cTemp ) ; // 4 Datenbyte I2C Wr (0 b00001111 ) ; // an den I2C Wr (0 b11001100 ) ; // PIC−S l a v e I2C Wr ( cTemp ) ; // schreiben I2 C S to p ( ) ; // S to p b e d i n g u n g // Demo 2 : Daten vom I2C−PIC−S l a v e l e s e n . . . I2C Start () ; // S t a r t b e d i n g u n g I2C Wr (0 b00110001 ) ; // B a u s t e i n a d r e s s e + L e s e z u g r i f f cTemp1 = I2C Rd (ACK) ; // Daten cTemp2 = I2C Rd (ACK) ; // vom cTemp3 = I2C Rd (ACK) ; // PIC−S l a v e cTemp4 = I2C Rd (noACK) ; // lesen I2 C S to p ( ) ; // S to p b e d i n g u n g // . . . und am I2C−LED−Modul a u s g e b e n cTemp4 = ˜cTemp4 ; I2C PCF8574 WriteData ( 3 , cTemp4 ) ; // M o d u l a d r e s s e : h i e r 3 } } } Listing 6: I2C Demo PIC Master.c (Demo 2) 5 DEMONSTRATIONSBEISPIELE 5.9 45 Anmerkungen zur Software für 2. Demo (Master) Auch dieser Quellcode wurde in C mit der freien Demoversion des mikroC-Compilers erstellt. Die Software (für den PIC-I2 C-Master) besteht auch hier im Wesentlichen aus den folgenden Programmteilen: • Hauptprogramm am Ende des Quellcodes von I2C Demo PIC Master.c, Zeilen 150 bis 222. • 1 Unterprogramm zur Initialisierung des PIC16F887 (Unterprogramm Init in der Datei I2C Demo PIC Master.c, Zeilen 83 bis 131). • 2 Unterprogramme zur Kommunikation mit dem PCF8574 (I2C PCF8574 WriteData und I2C PCF8574 ReadData in der Datei PCF8574.C, siehe erstes Demonstrationsbeispiel. Hier nur kurz die Änderungen im Hauptprogramm. Das Unterprogramm Init bleibt hier unverändert: Das Hauptprogramm ist - verglichen mit dem ersten Demonstrationsbeispiel, Master etwas länger. Grund dafür ist nur dass jetzt jeweils vier Datenbytes (anstelle von einer, beim ersten Demonstrationsbeispiel) gesendet bzw. gelesen werden müssen. Dies ist, glaube ich, im Quellcode sehr gut erkennbar. Dies ist auch der einzige Unterschied. Anstelle der temporären Register cTemp1 bis cTemp4 könnte auch ein Array verwendet werden, doch dies ist hier nicht unbedingt notwendig. Zum Abschluss noch ein Wort zu den Konfigurationsbits. Auch diese sind hier gleich wie beim ersten Demonstrationsbeispiel.