pcf_8574_io.h


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