Forum: Compiler & IDEs PCF8574 Ausgänge


von Philipp P. (Gast)


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
}

von Uwe S. (de0508)


Lesenswert?

Hallo  Philipp,

warum definierst Du alles - UNION, Proceduren und Funktionen in der 
main() {..} ?

Die Anweisungen
1
if (c == 0x32) // A0 Ein
 wären in seiner |switch case(arg)| einfache zu lesen.

: Bearbeitet durch User
von Falk B. (falk)


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
  }

von Falk B. (falk)


Lesenswert?

>       i2c_start(PCF_Read);
>       Pcf_Ausgang = i2c_readNak();
>       bbbk.byte = Pcf_Ausgang;
>       //Pcf_Ausgang |= (1 << a);

Hier fehlt ein I2c_stop

von Falk B. (falk)


Lesenswert?

Es ist auch SEHR schlechter Stil, in einer Funktion, die

char pcf_set2(int a)  //Byte vom Pcf lesen

heißt, auch Bits zu LÖSCHEN! (auch zusätzlich wieder ein Widerspruch 
zwischen Funktionsname und Kommentar)

von Philipp (Gast)


Lesenswert?

Hallo, vielen Dank für die Antworten ich werde heute Abend den Code 
ordnen und eure Ratschläge befolgen:)

MfG Philipp P.

von Philipp P. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

Danke für eure Hilfestellungen, es funktioniert. An meiner 
Programmformatierung muss ich noch arbeiten. Sorry bin da noch ziemlich 
am Anfang. Der Code ist im Anhang, falls es jemanden interessiert.


MfG Philipp P.

von Stefan (Gast)


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

von Falk B. (falk)


Lesenswert?

Richtig, ist aber in der neuen Version korrigiert.

http://www.mikrocontroller.net/attachment/highlight/235566

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.