PCF8574 Ausgänge

Gast #3868980
Lesenswert?

Hallo,

habe mit einem Atmega328PU eine Schaltung aufgebaut, die einen PCF8574PA
ansteuern soll. Er soll nur für Ausgänge benutzt werden. Bevor ein 
Ausgang geschrieben wird, sollte der PCF ausgelesen werden und der 
aktuelle Zustand in der Struktur bbbk gespeichert werden. Per Uart 
Befehl soll der Schreibvorgang für den entsprechenden Ausgang gestartet 
werden z.B. 32 soll A0 setzen. Verbindung habe ich, er schaltet auch die 
Ausgänge bis A0 durch, aber merkt sich nicht den vorherigen Zustand. 
Könnt ihr mir ein Hinweis geben warum es nicht funktioniert? Die I2C lib 
ist von Peter Fleury.

MfG Philipp

1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <avr/pgmspace.h>
5
#include <string.h>
6
#include <stdio.h>
7
#include "uart.h"
8
#include "lcd.h"
9
#include "i2cmaster.h"
10
#include <util/delay.h>
11

12

13
/* 9600 baud */
14
#define UART_BAUD_RATE      9600 
15
     
16
#define DS1307     0xD0         //Adresse des DS1307
17
#define PCF_Write  0x70      //Adresse für PCF Porterweiterung schreiben
18
#define PCF_Read   0x71     //Adresse für PCF Porterweiterung lesen
19

20

21
  unsigned char time_s;        
22
  unsigned char time_m;        
23
  unsigned char time_h;         
24
  unsigned char time_dayofweek;  //nicht benutzt  
25
  unsigned char time_day;        //nicht benutzt 
26
  unsigned char time_month;      //nicht benutzt 
27
  unsigned char time_year;      
28
  unsigned char buffer1[10];      // Buffer für itoa RTC 
29
  unsigned char buffer2[10];    // Buffer für Pcf Ausgangswert
30
  
31

32
  uint8_t ausgangswert;
33

34
int main(void)
35
{
36

37

38
  union          //8Bit Array
39
{
40
  uint8_t byte;
41
  struct
42
  {
43
    uint8_t b0 : 0;
44
    uint8_t b1 : 0;
45
    uint8_t b2 : 0;
46
    uint8_t b3 : 0;
47
    uint8_t b4 : 0;
48
    uint8_t b5 : 0;
49
    uint8_t b6 : 0;
50
    uint8_t b7 : 0;
51

52
  }bit;
53
}bbbk;
54
  
55

56

57
    char set_clock (unsigned char reg, unsigned char val) //Uhr setzen
58
    {
59
       if (i2c_start(DS1307+I2C_WRITE) != 0) return 1;
60
       i2c_write(reg);
61
       i2c_write(val);
62
       i2c_stop();
63
       return 0;
64
    } 
65

66
    char get_time(unsigned char reg)  //Zeit aus dem RTC lesen
67
    {
68
    unsigned char val;
69

70
        i2c_start(DS1307+I2C_WRITE);
71
       i2c_write(reg);
72
       i2c_stop();
73
       i2c_start(DS1307+I2C_READ);
74
       val = i2c_readNak();
75
       i2c_stop();
76
       return val;
77
    }
78

79
  
80

81
    char pcf_read()  //Byte vom Pcf lesen
82
    {
83
       uint8_t val;
84
           
85
       i2c_start(PCF_Read);
86
       val = i2c_readNak();
87
       i2c_stop();
88
       return val;
89
    }
90

91

92
    char pcf_set2(int a)  //Byte vom Pcf lesen
93
    {
94
    uint8_t Pcf_Ausgang;
95
    
96
           
97
       i2c_start(PCF_Read);
98
       Pcf_Ausgang = i2c_readNak();
99
       bbbk.byte = Pcf_Ausgang;
100
       //Pcf_Ausgang |= (1 << a);
101

102
       switch (a) 
103
       
104
       {
105
          case 0:  bbbk.bit.b0 = 1;    // A0 Led
106
          break;
107
          case 1:   bbbk.bit.b1 = 1;    // A1 Led
108
          break;
109
          case 2:  bbbk.bit.b2 = 1;    // A2 Led
110
          break;
111
          case 3:   bbbk.bit.b3 = 1;   // A3 Led
112
          break;
113
          case 4:   bbbk.bit.b4 = 1;    // A4 Relais über ULN2003 Ein
114
          break;
115
          case 5:  bbbk.bit.b5 = 1;    //  n. A.
116
          break;
117
        case 6:  bbbk.bit.b4 = 0;    // A4 Relais über ULN2003 Aus
118
       }
119

120
       i2c_start(PCF_Write);
121
       i2c_write(bbbk.byte);
122
       _delay_ms(100);
123
       i2c_stop;
124
       return 0;
125
       }
126

127

128
    int int_to_char(int B)            //int to char
129
    {
130
    unsigned char Buffer[10];
131
      
132
      itoa( B, Buffer, 10 );
133
      return( Buffer ); 
134
    }
135

136
    int digit_to_int(unsigned char d)    //strtol
137
    {
138
     char str[2];
139

140
     str[0] = d;
141
     str[1] = '\0';
142
     return (int) strtol(str, NULL, 10);
143
    }
144

145
    void lcd_puti( int number )        //itoa
146
    {
147
      char buffer[10];
148

149
       itoa( number, buffer, 10 );
150
        lcd_puts( buffer );
151
    }
152

153
  
154
    void lcd_putu( unsigned int number )  //utoa
155
    {
156
         char buffer[10];
157

158
      utoa( number, buffer, 10 );
159
      lcd_puts( buffer );
160
    }
161

162

163

164

165

166

167

168

169
    i2c_init();                //I2c starten
170

171
      _delay_ms(300);              // delay
172

173

174
    lcd_init(LCD_DISP_ON);          //Lcd starten
175

176
   
177
      uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );   // Uart starten
178
    
179
   
180
      sei();
181
    
182
         
183

184
 
185
    uart_putc('\r');
186
    lcd_clrscr();
187

188

189
      //set_clock(0x07, 0x00);   // CH 0 setzen
190

191
         //set_clock(0x02, 0x00);
192
         //set_clock(0x01, 0x00);
193
         //set_clock(0x00, 0x00); 
194
      
195

196
  
197
    for(;;)
198

199
  
200
  
201
{
202

203
      time_s = get_time(0x00);    //Zeiten auslesen
204
      time_m = get_time(0x01);
205
      time_h = get_time(0x02);
206

207
      _delay_ms(10);
208
  
209
        lcd_clrscr();
210

211
      sprintf(buffer1, "Zeit: %02x:%02x:%02x", time_h, time_m, time_s);
212
          lcd_puts(buffer1);
213

214

215
      //uart_puts(buffer1);
216
      //ausgangswert = pcf_read();
217
      //itoa(ausgangswert, buffer2, 10);
218
      //uart_puts(buffer2);
219

220

221

222

223
    // Per UART Zeichen einlesen
224
    c = uart_getc();
225
      if (!( c & UART_NO_DATA ))
226
    {
227
      // In Char-Array "command" speichern & testweise ausgeben
228
      command[ci] = c;
229
      ci = ci<20 ? ci+1 : 0;
230
      /*uart_putc(c);*/
231

232
  /*intwert = digit_to_int(c);*/
233
  
234
  lcd_putu(c);
235
  
236

237
     
238
      // Wenn CR empfangen wurde
239

240

241
    if (c == 0x32) // A0 Ein
242
    {
243
      pcf_set2(0);
244
    }
245
          else if (c == 0x33) //A1 Ein
246
    {    
247
      pcf_set2(1);    
248
    }
249
        else if (c == 0x34) //A2 Ein
250
    {
251
      pcf_set2(2);
252
    }
253
          else if (c == 0x35) //A3 Ein
254
    {
255
      pcf_set2(3);
256
    }
257
        else if (c == 0x36) //A4 Ein
258
    {
259
      pcf_set2(4);    
260
    }
261
      else if (c == 0x37) //A4 Aus
262
    {
263
      pcf_set2(6);
264
    }
265
      else if (c == 0x38) //
266
    {
267
    
268
    }
269
      else if (c == 0x39) //
270
    {    
271
    
272
    }
273

274
    }
275

276

277
    }
278
   
279
             
280
}
#3869116
Lesenswert?

@Philipp P. (Gast)

>habe mit einem Atmega328PU eine Schaltung aufgebaut, die einen PCF8574PA
>ansteuern soll. Er soll nur für Ausgänge benutzt werden. Bevor ein
>Ausgang geschrieben wird, sollte der PCF ausgelesen werden und der
>aktuelle Zustand in der Struktur bbbk gespeichert werden.

Wozu? Halte einfach eine Kopie der Daten im Prozessor und gut. Deutlich 
einfacher, schneller und sicherer!

> Per Uart
>Befehl soll der Schreibvorgang für den entsprechenden Ausgang gestartet
>werden z.B. 32 soll A0 setzen.

Was für ein A0? A0 ist eine Adresseingang am IC, der fest auf LOW oder 
HIGH geleget wird. Per Software wird dort nichts eingestellt. Die IOs 
heißen P0-P7.

> Verbindung habe ich, er schaltet auch die
>Ausgänge bis A0 durch, aber merkt sich nicht den vorherigen Zustand.
>Könnt ihr mir ein Hinweis geben warum es nicht funktioniert?

Zuserst solltest du die Netiquette beherzigen, lange Quelltexte 
gehören in den Anhang.

Dann solltest du DRINGEND deinen Quelltexte besser formatieren, vor 
allem die Einrückung ist WICHTIG!

Siehe Strukturierte Programmierung auf Mikrocontrollern

>      else if (c == 0x37) //A4 Aus
>    {
>      pcf_set2(6);
>    }

Hier stimmen Quelltext und Kommentar nicht überein! Ja was denn nun?
Wie bereits gesagt ist ein switch hier DEUTLICH besser, weil 
übersichtlicher!
1
  switch(c) {
2
    case 0x32: pcf_set2(0); break;
3
    case 0x33: pcf_set2(1); break;
4
    case 0x34: pcf_set2(2); break;
5
    case 0x35: pcf_set2(3); break;
6
    case 0x36: pcf_set2(4); break;
7
    case 0x37: pcf_set2(5); break;
8
    case 0x38: pcf_set2(6); break;
9
    case 0x39: pcf_set2(7); break;
10
  }

Aber auch das ist hier noch reichlich akademisch und umständlich. 
Einfacher und ausreichend ist hier.
1
  if (c >= 0x32 && c <= 0x39) {
2
    pcf_set2(c-0x32)
3
  }
Gast #3872558
Lesenswert?

Hallo,

was das den ?
1
 union          //8Bit Array
2
{
3
  uint8_t byte;
4
  struct
5
  {
6
    uint8_t b0 : 0;
7
    uint8_t b1 : 0;
8
    uint8_t b2 : 0;
9
    uint8_t b3 : 0;
10
    uint8_t b4 : 0;
11
    uint8_t b5 : 0;
12
    uint8_t b6 : 0;
13
    uint8_t b7 : 0;
14

15
  }bit;
16
}bbbk
steht nicht hinter dem Doppelpunkt die Länge des Bitfeldes ???

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren