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 | = 1111000 = 120 Dez = 78 h
|
24 |
|
25 | ---------------------------------------------------------------
|
26 |
|
27 |
|
28 | und noch den Bus initialiesieren.
|
29 |
|
30 | z.B. am Port C (Mega 16) ...
|
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 | 0);// Die "0" für schreiben senden
|
105 | i2c_write(wert); // Portzustand übergeben
|
106 | i2c_stop(); // Ende der Datenübertragung
|
107 |
|
108 | }
|
109 | /*********************************************************************/
|
110 |
|
111 |
|
112 |
|
113 | /*********************************************************************/
|
114 | /* Anhand der übergebenen Adresse kann man den Zustand der I/O Ports */
|
115 | /* des gewünschten Teilnehmers auslesen lassen. Dieser Wert wird als */
|
116 | /* Funktionswert zurückgegeben. */
|
117 |
|
118 | pcf_portread(unsigned char pcf_teilnehmer)
|
119 | {
|
120 | unsigned char port_zustand; // In diese Variable wird der
|
121 | // Wert des I/O Port geschrieben
|
122 |
|
123 | i2c_start(); // Start zur Datenübertragung
|
124 | i2c_write(pcf_teilnehmer | 1);// Die "1" für lesen senden
|
125 | port_zustand = i2c_read(0); // Portzustand empfangen
|
126 | i2c_stop(); // Ende der Datenübertragung
|
127 | return port_zustand; // Wert an den Funktionsaufruf
|
128 | }
|
129 | /*********************************************************************/
|
130 |
|
131 |
|
132 |
|
133 | /*********************************************************************/
|
134 | /* Mit diese Funktion kann der Zustand eines Pins abgefragt werden. */
|
135 | /* Es ist der Teilnehmer und der gewünschte Pin an die Funktion zu */
|
136 | /* übergeben. */
|
137 |
|
138 | pcf_pinread(unsigned char pcf_teilnehmer, unsigned char pin)
|
139 | {
|
140 | unsigned char port_zustand; // aktueller Zustsand des Portes
|
141 | unsigned char signal; // Rückgabe des Signalwertes
|
142 |
|
143 | port_zustand = pcf_portread(pcf_teilnehmer); // erst mal den
|
144 | // Zustand des Portes einlesen
|
145 |
|
146 | port_zustand >>= pin; // Um testen zu können wie der Zustand
|
147 | // des gewünschten Pins ist, schiebt
|
148 | // man das gesuchte Bit ganz nach
|
149 | // rechts (Bit 0).
|
150 |
|
151 | signal = (port_zustand & 1); // Mit der "verundung" erhält man den
|
152 | // aktuellen Zustand des Pins. Ist das
|
153 | // Bit = 1 so ist auch das Ergebnis 1,
|
154 | // sonst 0.
|
155 |
|
156 | return signal; // Wert an Funktionsaufruf
|
157 | }
|
158 | /*********************************************************************/
|
159 |
|
160 |
|
161 |
|
162 | /*********************************************************************/
|
163 | /* Mit diese Funktion kann man ein Pin direkt setzen. Dabei muss man */
|
164 | /* an die Funktion den Teilnehmer und den gewünschte Pin übergeben */
|
165 |
|
166 | pcf_pinset(unsigned char pcf_teilnehmer, unsigned char pin)
|
167 | {
|
168 | unsigned char port_zustand; // aktueller Zustsand des Portes
|
169 | unsigned char maske = 1; // Bitmaske für den Port
|
170 |
|
171 | // !!ACHTUNG!!! Bei angeschlossenen LED's leuchten sie, wenn eine "0"
|
172 | // am Port anliegt. Also muss man etwas umdenken
|
173 |
|
174 | port_zustand = pcf_portread(pcf_teilnehmer); // erst mal den
|
175 | // Zustand des Portes einlesen
|
176 |
|
177 | maske <<= pin; // Um das gewünschte Bit zu setzen wird
|
178 | // erst mal eine "1" an die Bitposition
|
179 | // "geschoben".
|
180 |
|
181 | port_zustand = ~port_zustand; // Der Portzustand wird in der Variable
|
182 | // erst mal invertiert.
|
183 |
|
184 | maske = ~(port_zustand | maske); // der neue Wert für das Port wird
|
185 | // erzeugt in dem man jetzt den inver-
|
186 | // tierten Portzustand mit der maske
|
187 | // "verodert". Diese Ergebnis wird dann
|
188 | // invertiert in der maske gespeichert.
|
189 |
|
190 | // Genaue gesagt handelt es sich um ein "XOR" (exklusiv oder)
|
191 |
|
192 | // wahrheitstabelle:
|
193 | // a|b|y
|
194 | // 0|0|0
|
195 | // 0|1|1
|
196 | // 1|0|1
|
197 | // 0|0|0
|
198 | // mit anderen Worten, immer "eins" wenn etwas ungleich ist!
|
199 |
|
200 | // Bsp.: 11101101 ->LED 4 & 1 leuchten ->1 soll gelöscht werden
|
201 | // maske 00000010
|
202 | // Port neu 00010010 (invertiert)
|
203 | // "!(verodern)" --------
|
204 | // 00010000
|
205 | // "invertiert" 11101111 -> LED 4 leuchtet, 1 ist gelöscht
|
206 |
|
207 | i2c_start(); // Start zur Datenübertragung
|
208 | i2c_write(pcf_teilnehmer | 0);// Die "0" für schreiben senden
|
209 | i2c_write(maske); // neuen Wert schreiben
|
210 | i2c_stop(); // Ende der Datenübertragung
|
211 |
|
212 | }
|
213 | /*********************************************************************/
|
214 |
|
215 |
|
216 |
|
217 | /*********************************************************************/
|
218 | /* Mit diese Funktion kann man ein Pin direkt löschen. Dabei muss man*/
|
219 | /* an die Funktion den Teilnehmer und den gewünschte Pin übergeben */
|
220 |
|
221 | pcf_pinclr(unsigned char pcf_teilnehmer, unsigned char pin)
|
222 | {
|
223 | unsigned char port_zustand; // aktueller Zustsand des Portes
|
224 | unsigned char maske = 1; // Bitmaske für den Port
|
225 |
|
226 | // !!ACHTUNG!!! Bei angeschlossenen LED's leuchten sie, wenn eine "0"
|
227 | // am Port anliegt. Also muss man etwas umdenken
|
228 |
|
229 | port_zustand = pcf_portread(pcf_teilnehmer); // erst mal den
|
230 | // den Zustand des Portes einlesen
|
231 |
|
232 | maske <<= pin; //Um das gewünschte Bit zu löschen wird
|
233 | // erst mal eine "1" an die Bitposition
|
234 | // "geschoben".
|
235 |
|
236 | maske = (port_zustand | maske);// Portzustand wird mit der Maske
|
237 | // "verodert" und neu in maske
|
238 | // gespeichert
|
239 |
|
240 | // Bsp.: 00010010 -> LED 4 & 1 leuchten -> 6 soll gesetzt werden
|
241 | // maske 01000000
|
242 | // "verodern" --------
|
243 | // 01010010 -> LED 6, 4, und 1 leuchten
|
244 |
|
245 |
|
246 |
|
247 | i2c_start(); // Start zur Datenübertragung
|
248 | i2c_write(pcf_teilnehmer | 0);// Die "0" für schreiben senden
|
249 | i2c_write(maske); // neuen Wert schreiben
|
250 | i2c_stop(); // Ende der Datenübertragung
|
251 |
|
252 | }
|
253 | /*********************************************************************/
|
254 |
|
255 |
|
256 |
|
257 |
|
258 | /*********************************************************************/
|
259 | /* Mit diese Funktion kann man eine Variablenwert direkt einem Pin */
|
260 | /* zuordnen. Dabei ist aber darauf zu achten das nur "0" und "1" */
|
261 | /* einen Sinn macht. Normalerweise würde man da eine Bit-Variable */
|
262 | /* verwenden aber das geht bei einer Funktion nicht */
|
263 | /* es handelt sich hier eigentlich nur um eine simple Funktion, kann */
|
264 | /* aber sehr hilfreich sein! */
|
265 |
|
266 | pcf_pinwert(unsigned char pcf_teilnehmer, unsigned char pin, unsigned char wert)
|
267 | {
|
268 | if (wert == 0) pcf_pinclr(pcf_teilnehmer,pin);
|
269 | else pcf_pinset(pcf_teilnehmer,pin);
|
270 |
|
271 | }
|
272 | /*********************************************************************/
|
273 |
|
274 |
|
275 | #pragma used-
|
276 |
|
277 |
|
278 | #endif
|