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 | = 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