1 | /*
|
2 |
|
3 | Diese Include liest/schreibt Werte von Porterweiterungen,
|
4 | wie z.B. dem "PCF8574A", die am I2C-Bus hängen
|
5 | ---------------------------------------------------------------
|
6 |
|
7 | Z.B. 8 Taster am ersten "PCF8574A"
|
8 |
|
9 | #define PCF_TASTER 0x76 <-- Name des Teilnehmers
|
10 |
|
11 | Codierung laut Datenblatt:
|
12 |
|
13 | codiert -> 0 1 1
|
14 | | 1 | 1 | 1 | A2 | A1 | A0 | 0 | = 1110110 = 118 Dez = 76 h
|
15 |
|
16 | ---------------------------------------------------------------
|
17 |
|
18 | und 8 LED's am zweiten "PCF8574A"
|
19 |
|
20 | #define PCF_LAMPEN 0x78
|
21 |
|
22 | codiert -> 1 0 0
|
23 | | 1 | 1 | 1 | A2 | A1 | A0 | 0 | = 1110010 = 114 Dez = 78 h
|
24 |
|
25 | ---------------------------------------------------------------
|
26 |
|
27 |
|
28 | und noch den Bus initialiesieren.
|
29 |
|
30 | z.B. ...
|
31 |
|
32 | #asm
|
33 | .equ __i2c_port=0x15
|
34 | .equ __sda_bit=7
|
35 | .equ __scl_bit=6
|
36 | #endasm
|
37 | #include <i2c.h>
|
38 |
|
39 |
|
40 |
|
41 | Man kann dann z.B. wie folgt die I/O Ports abfragen/lesen
|
42 |
|
43 |
|
44 | Mit dem Taster 0 die 4.LED einschalten
|
45 |
|
46 | |-- Funktionsaufruf
|
47 | | |-- Bausteintyp (Adresse; siehe #define)
|
48 | | | |-- Pin-Nummer
|
49 | | | | |-- Funktionsaufruf
|
50 | | | | | |-- Bausteintyp
|
51 | | | | | | |-- Pin-Nummer
|
52 | | | | | | |
|
53 | if (pcf_write(PCF_TASTER, 0) == 1) pcf_pinset(PCF_LAMPEN, 4);
|
54 |
|
55 |
|
56 |
|
57 | Mit dem Taster 1 die 4.LED auschalten
|
58 |
|
59 | if (pcf_pinread(PCF_TASTER, 1) == 1) pcf_pinclr(PCF_LAMPEN, 4);
|
60 |
|
61 |
|
62 |
|
63 |
|
64 | Den Zustand des Tasters 2 direkt an die 5.LED anzeigen
|
65 |
|
66 | pcf_pinwert(PCF_LAMPEN, 5, pcf_pinread(PCF_TASTER, 2));
|
67 |
|
68 |
|
69 |
|
70 |
|
71 | Die 7.LED leuchtet wenn die Variable "alarm" den
|
72 | Wert "1" bekommt
|
73 |
|
74 | pcf_pinwert(PCF_LAMPEN, 7, alarm);
|
75 |
|
76 |
|
77 |
|
78 |
|
79 | Mit dem Taster 7 die LED 7 wieder auschalten
|
80 |
|
81 | if (pcf_pinread(PCF_TASTER, 7) == 1) pcf_pinclr(PCF_LAMPEN, 7);
|
82 |
|
83 | */
|
84 |
|
85 | //////////////////////////////////////////////////////////////////////
|
86 |
|
87 |
|
88 |
|
89 | #ifndef _pcf_8574_IO_INCLUDED_
|
90 | #define _pcf_8574_IO_INCLUDED_
|
91 |
|
92 | #include <i2c.h>
|
93 |
|
94 | #pragma used+
|
95 |
|
96 |
|
97 | /*********************************************************************/
|
98 | /* Anhand der übergebenen Adresse des Teilnehmers und einen Wertes */
|
99 | /* kann man den Wert der Ports initialisieren. */
|
100 |
|
101 | pcf_portwrite(unsigned char pcf_teilnehmer, unsigned char wert)
|
102 | {
|
103 | i2c_start(); // Start zur Datenübertragung
|
104 | i2c_write(pcf_teilnehmer); // Übergebene Adresse senden
|
105 | i2c_start();
|
106 | i2c_write(pcf_teilnehmer | 0);// Die "0" für lesen senden
|
107 | i2c_write(wert); // Portzustand übergeben
|
108 | i2c_stop(); // Ende der Datenübertragung
|
109 |
|
110 | }
|
111 | /*********************************************************************/
|
112 |
|
113 |
|
114 |
|
115 | /*********************************************************************/
|
116 | /* Anhand der übergebenen Adresse kann man den Zustand der I/O Ports */
|
117 | /* des gewünschten Teilnehmers auslesen lassen. Dieser Wert wird als */
|
118 | /* Funktionswert zurückgegeben. */
|
119 |
|
120 | pcf_portread(unsigned char pcf_teilnehmer)
|
121 | {
|
122 | unsigned char port_zustand; // In diese Variable wird der
|
123 | // Wert des I/O Port geschrieben
|
124 |
|
125 | i2c_start(); // Start zur Datenübertragung
|
126 | i2c_write(pcf_teilnehmer); // Übergebene Adresse senden
|
127 | i2c_start();
|
128 | i2c_write(pcf_teilnehmer | 1);// Die "1" für lesen senden
|
129 | port_zustand = i2c_read(0); // Portzustand empfangen
|
130 | i2c_stop(); // Ende der Datenübertragung
|
131 | return port_zustand; // Wert an den Funktionsaufruf
|
132 | }
|
133 | /*********************************************************************/
|
134 |
|
135 |
|
136 |
|
137 | /*********************************************************************/
|
138 | /* Mit diese Funktion kann der Zustand eines Pins abgefragt werden. */
|
139 | /* Es ist der Teilnehmer und der gewünschte Pin an die Funktion zu */
|
140 | /* übergeben. */
|
141 |
|
142 | pcf_Pinread(unsigned char pcf_teilnehmer, unsigned char pin)
|
143 | {
|
144 | unsigned char port_zustand; // aktueller Zustsand des Portes
|
145 | unsigned char signal; // Rückgabe des Signalwertes
|
146 |
|
147 | port_zustand = pcf_portread(pcf_teilnehmer); // erst mal den
|
148 | // den Zustand des Portes einlesen
|
149 |
|
150 | port_zustand >>= pin; // Um testen zu können wie der Zustand
|
151 | // des gewünschten Pins ist, schiebt
|
152 | // man das gesuchte Bit ganz nach
|
153 | // rechts (Bit 0).
|
154 |
|
155 | signal = (port_zustand & 1); // Mit der "verundung" erhält man den
|
156 | // aktuellen Zustand des Pins. Ist das
|
157 | // Bit = 1 so ist auch das Ergebnis 1,
|
158 | // sonst 0.
|
159 |
|
160 | return signal; // Wert an Funktionsaufruf
|
161 | }
|
162 | /*********************************************************************/
|
163 |
|
164 |
|
165 |
|
166 | /*********************************************************************/
|
167 | /* Mit diese Funktion kann man ein Pin direkt setzen. Dabei muss man */
|
168 | /* an die Funktion den Teilnehmer und den gewünschte Pin übergeben */
|
169 |
|
170 | pcf_pinset(unsigned char pcf_teilnehmer, unsigned char pin)
|
171 | {
|
172 | unsigned char port_zustand; // aktueller Zustsand des Portes
|
173 | unsigned char maske = 1; // Bitmaske für den Port
|
174 |
|
175 | // !!ACHTUNG!!! Bei angeschlossenen LED's leuchten sie, wenn eine "0"
|
176 | // am Port anliegt. Also muss man etwas umdenken
|
177 |
|
178 | port_zustand = pcf_portread(pcf_teilnehmer); // erst mal den
|
179 | // den Zustand des Portes einlesen
|
180 |
|
181 | maske <<= pin; // Um das gewünschte Bit zu setzen wird
|
182 | // erst mal eine "1" an die Bitposition
|
183 | // "geschoben".
|
184 |
|
185 | port_zustand = ~port_zustand; // Der Portzustand wird in der Variable
|
186 | // erst mal invertiert.
|
187 |
|
188 | maske = ~(port_zustand | maske); // der neue Wert für das Port wird
|
189 | // erzeugt in dem man jetzt den inver-
|
190 | // tierten Portzustand mit der maske
|
191 | // "verodert". Diese Ergebnis wird dann
|
192 | // invertiert in der maske gespeichert.
|
193 |
|
194 | // Genaue gesagt handelt es sich um ein "XOR" (exklusiv oder)
|
195 |
|
196 | // wahrheitstabelle:
|
197 | // a|b|y
|
198 | // 0|0|0
|
199 | // 0|1|1
|
200 | // 1|0|1
|
201 | // 0|0|0
|
202 | // mit anderen Worten, immer "eins" wenn etwas ungleich ist!
|
203 |
|
204 | // Bsp.: 11101101 ->LED 4 & 1 leuchten ->1 soll gelöscht werden
|
205 | // maske 00000010
|
206 | // Port neu 00010010 (invertiert)
|
207 | // "!(verodern)" --------
|
208 | // 00010000
|
209 | // "invertiert" 11101111 -> LED 4 leuchtet, 1 ist gelöscht
|
210 |
|
211 | i2c_start(); // Start zur Datenübertragung
|
212 | i2c_write(pcf_teilnehmer); // Übergebene Adresse senden
|
213 | i2c_start(); // Start zur Datenübertragung
|
214 | i2c_write(pcf_teilnehmer | 0);// Die "0" für schreiben senden
|
215 | i2c_write(maske); // neuen Wert schreiben
|
216 | i2c_stop(); // Ende der Datenübertragung
|
217 |
|
218 | }
|
219 | /*********************************************************************/
|
220 |
|
221 |
|
222 |
|
223 | /*********************************************************************/
|
224 | /* Mit diese Funktion kann man ein Pin direkt löschen. Dabei muss man*/
|
225 | /* an die Funktion den Teilnehmer und den gewünschte Pin übergeben */
|
226 |
|
227 | pcf_pinclr(unsigned char pcf_teilnehmer, unsigned char pin)
|
228 | {
|
229 | unsigned char port_zustand; // aktueller Zustsand des Portes
|
230 | unsigned char maske = 1; // Bitmaske für den Port
|
231 |
|
232 | // !!ACHTUNG!!! Bei angeschlossenen LED's leuchten sie, wenn eine "0"
|
233 | // am Port anliegt. Also muss man etwas umdenken
|
234 |
|
235 | port_zustand = pcf_portread(pcf_teilnehmer); // erst mal den
|
236 | // den Zustand des Portes einlesen
|
237 |
|
238 | maske <<= pin; //Um das gewünschte Bit zu löschen wird
|
239 | // erst mal eine "1" an die Bitposition
|
240 | // "geschoben".
|
241 |
|
242 | maske = (port_zustand | maske);// Portzustand wird mit der Maske
|
243 | // "verodert" und neu in maske
|
244 | // gespeichert
|
245 |
|
246 | // Bsp.: 00010010 -> LED 4 & 1 leuchten -> 6 soll gesetzt werden
|
247 | // maske 01000000
|
248 | // "verodern" --------
|
249 | // 01010010 -> LED 6, 4, und 1 leuchten
|
250 |
|
251 |
|
252 |
|
253 | i2c_start(); // Start zur Datenübertragung
|
254 | i2c_write(pcf_teilnehmer); // Übergebene Adresse senden
|
255 | i2c_start();
|
256 | i2c_write(pcf_teilnehmer | 0);// Die "0" für schreiben senden
|
257 | i2c_write(maske); // neuen Wert schreiben
|
258 | i2c_stop(); // Ende der Datenübertragung
|
259 |
|
260 | }
|
261 | /*********************************************************************/
|
262 |
|
263 |
|
264 |
|
265 |
|
266 | /*********************************************************************/
|
267 | /* Mit diese Funktion kann man eine Variablenwert direkt einem Pin */
|
268 | /* zuordnen. Dabei ist aber darauf zu achten das nur "0" und "1" */
|
269 | /* einen Sinn macht. Normalerweise würde man da eine Bit-Variable */
|
270 | /* verwenden aber das geht bei einer Funktion nicht */
|
271 | /* es handelt sich hier eigentlich nur um eine simple Funktion, kann */
|
272 | /* aber sehr hilfreich sein! */
|
273 |
|
274 | pcf_pinwert(unsigned char pcf_teilnehmer, unsigned char pin, unsigned char wert)
|
275 | {
|
276 | if (wert == 0) pcf_pinclr(pcf_teilnehmer,pin);
|
277 | else pcf_pinset(pcf_teilnehmer,pin);
|
278 |
|
279 | }
|
280 | /*********************************************************************/
|
281 |
|
282 |
|
283 | #pragma used-
|
284 |
|
285 |
|
286 | #endif
|