Forum: Mikrocontroller und Digitale Elektronik I2C-Eingänge / Ausgänge


von Knoddelpusch (Gast)


Lesenswert?

Hallo Zusammen,

bin gerade dabei einen I2C-Bus mit einer Eingangs Karte sowie einer 
Ausgangskarte zu Programmieren.

Die Ausgangskarte kann ich Ansteuern und läuft schön mit einer Schleife 
durch wo ich nach und nach die Ausgänge schalte.

Die Eingangskarte wird auch irgendwie Ausgelesen aber kann das nicht auf 
die Ausgangskarte übertragen.
1
/*******************************************************
2
 Öffentliche Funktion: I2C_Init
3
4
 Zweck: Initialisieren Sie die I2C-Master-Schnittstelle
5
6
 Eingabeparameter:
7
 - uint16_t I2C_Bitrate (Hz)
8
9
 Rückgabewert: uint8_t
10
   - FALSE:  Bitrate too high
11
   - TRUE:    Bitrate OK
12
13
*******************************************************/
14
uint8_t I2C_Init (uint32_t I2C_Bitrate)
15
{
16
  /*
17
    Stelle I2C bitrate
18
    Wenn die Bitrate zu hoch ist, wird der Fehler zurückgegeben
19
  */
20
  
21
  TWBR = ((F_CPU/I2C_Bitrate)-16)/2;
22
  if (TWBR < 11) return FALSE;
23
24
  return TRUE;
25
}
26
27
/*******************************************************
28
 Öffentliche Funktion: I2C_Start
29
30
 Zweck: Starten Sie die I2C-Master-Schnittstelle
31
32
 Eingabeparameter:
33
      - uint8_t Geräteadresse
34
      - uint8_t Art der erforderlichen Operation:
35
                I2C_READ: Liest Daten vom Slave
36
                I2C_WRITE: Schreibe Daten in den Slave
37
38
 Rückgabewert: uint8_t
39
      - TRUE: OK, I2C Master erreichbar
40
      - FALSE: Fehler beim Starten von I2C Master
41
42
*******************************************************/
43
uint8_t I2C_Start (uint8_t Address, uint8_t I2C_Type)
44
{
45
  uint8_t    twst;
46
47
  //Senden Sie die START-Bedingung
48
49
  TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
50
51
  //Warten Sie, bis die Übertragung abgeschlossen ist
52
53
  while (!(TWCR & (1<<TWINT)));
54
55
  //Überprüfen Sie den Wert des I2C-Statusregisters. Maskieren Sie Prescaler-Bits.
56
57
  twst = TWSR & 0xF8;
58
  if ((twst != I2C_START) && (twst != I2C_REP_START)) return FALSE;
59
60
  //Geräteadresse senden
61
  TWDR =(Address<<1)+ I2C_Type; //(Address<<1) + I2C_Type;
62
  TWCR = (1<<TWINT)|(1<<TWEN);
63
64
  //Warten Sie, bis die Übertragung abgeschlossen ist und ACK / NACK empfangen wurde
65
66
  while (!(TWCR & (1<<TWINT)));
67
68
  //Überprüfen Sie den Wert des TWI-Statusregisters. Maskieren Sie Prescaler-Bits.
69
  
70
  twst = TWSR & 0xF8;
71
  if ((twst != I2C_MTX_ADR_ACK) && (twst != I2C_MRX_ADR_ACK)) return FALSE;
72
73
  return TRUE;
74
}
75
76
/*******************************************************
77
 Öffentliche Funktion: I2C_Stop
78
79
 Zweck: Stoppen Sie den I2C-Master
80
81
 Eingabeparameter: Keine
82
83
 Rückgabewert: Keine
84
85
*******************************************************/
86
void I2C_Stop (void)
87
{
88
  //Sendebedingung senden
89
90
  TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
91
92
  //Warten Sie, bis die Stoppbedingung ausgeführt und der Bus freigegeben ist
93
94
  while (TWCR & (1<<TWINT));
95
}
96
97
/*******************************************************
98
Öffentliche Funktion: I2C_Write
99
100
Zweck: Schreiben Sie ein Byte an den Slave
101
102
Eingabeparameter:
103
- uint8_t Zu sendendes Byte
104
105
Rückgabewert: uint8_t
106
- TRUE: OK, Byte gesendet
107
- FALSE: Fehler bei der Byteübertragung
108
109
*******************************************************/
110
uint8_t I2C_Write (uint8_t byte)
111
{
112
  uint8_t   twst;
113
114
  //Senden Sie Daten an das zuvor adressierte Gerät
115
116
  TWDR = byte;
117
  TWCR = (1<<TWINT)|(1<<TWEN);
118
119
  //Warten Sie, bis die Übertragung abgeschlossen ist
120
121
  while (!(TWCR & (1<<TWINT)));
122
123
  //Überprüfen Sie den Wert des TWI-Statusregisters. Maskieren Sie Prescaler-Bits
124
125
  twst = TWSR & 0xF8;
126
  if (twst != I2C_MTX_DATA_ACK) return 1;
127
128
  return 0;
129
}
130
131
/*******************************************************
132
Öffentliche Funktion: I2C_ReadAck
133
134
Zweck: Lesen Sie ein Byte vom Slave und fordern Sie das nächste Byte an
135
136
Eingabeparameter: Keine
137
138
Rückgabewert: uint8_t
139
- uint8_t Lese-Byte
140
141
*******************************************************/
142
uint8_t I2C_ReadAck (void)
143
{
144
  TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
145
  while (!(TWCR & (1<<TWINT)));    
146
147
  return TWDR;
148
}
149
150
/*******************************************************
151
Öffentliche Funktion: I2C_ReadAck
152
153
Zweck: Liest das letzte Byte vom Slave
154
155
Eingabeparameter: Keine
156
157
Rückgabewert: uint8_t
158
- uint8_t Lese-Byte
159
160
*******************************************************/
161
uint8_t I2C_ReadNack (void)
162
{
163
  TWCR = (1<<TWINT)|(1<<TWEN);
164
  while(!(TWCR & (1<<TWINT)));
165
  
166
  return TWDR;
167
}
168
169
/*************************************************************************
170
 Issues a start condition and sends address and transfer direction.
171
 If device is busy, use ack polling to wait until device is ready
172
 
173
 Input:   address and transfer direction of I2C device
174
*************************************************************************/
175
void I2C_Start_Wait(uint8_t Address, uint8_t I2C_Type)
176
{
177
    uint8_t   twst;
178
179
180
    while ( 1 )
181
    {
182
      // send START condition
183
      TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
184
    
185
      // wait until transmission completed
186
      while(!(TWCR & (1<<TWINT)));
187
    
188
      // check value of TWI Status Register. Mask prescaler bits.
189
      twst = TWSR & 0xF8;
190
      if ((twst != I2C_START) && (twst != I2C_REP_START)) continue;
191
    
192
      // send device address
193
      /*TWDR =(Address<<1)+ I2C_Type;*/TWDR = Address;
194
      TWCR = (1<<TWINT) | (1<<TWEN);
195
    
196
      // wail until transmission completed
197
      while(!(TWCR & (1<<TWINT)));
198
    
199
      // check value of TWI Status Register. Mask prescaler bits.
200
      twst = TWSR & 0xF8;
201
      if ( (twst == I2C_MTX_ADR_NACK )||(twst ==I2C_MRX_DATA_NACK) ) 
202
      {          
203
          /* device busy, send stop condition to terminate write operation */
204
          TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
205
          
206
          // wait until stop condition is executed and bus released
207
          while(TWCR & (1<<TWSTO));
208
          
209
          continue;
210
      }
211
      //if( twst != TW_MT_SLA_ACK) return 1;
212
      break;
213
     }
214
215
}
1
uint8_t Send1;
2
char Send;
3
I2C_Start_Wait(Ausgaenge, I2C_WRITE);
4
I2C_Write(Send1);
5
I2C_Stop();
6
7
I2C_Start_Wait(Eingaenge, I2C_READ);
8
Send= I2C_ReadAck();
9
I2C_Stop();

Wird nur eine kleiner Fehler sein wo ich gerade nur zu blind dafür bin.

von WF88 (Gast)


Lesenswert?

Knoddelpusch schrieb:
> Wird nur eine kleiner Fehler sein wo ich gerade nur zu blind dafür bin.

Zuerst lesen und dann senden wäre sinnvoll.

Oder die GANZE main-Datei. Die I2C Datei kannste weglassen.

von Forist (Gast)


Lesenswert?

Knoddelpusch schrieb:
> Wird nur eine kleiner Fehler sein wo ich gerade nur zu blind dafür bin.

Möchtest du es vorgelesen haben?

*Wichtige Regeln - erst lesen, dann posten!*
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

von Knoddelpusch (Gast)


Lesenswert?

Ja wäre besser gewessen.
Das Senden und Lesen hängt in einer While Schleife.
Sind noch ein paar Temperaturfühler über 1-Wire angeschlossen die laufen 
ohne Problem sowie das Display.
1
//***************************************************************
2
uint16_t overflow =0;
3
uint16_t LED_Freq = 3125;
4
5
ISR(TIMER0_OVF_vect)
6
{
7
  if (overflow <= LED_Freq)
8
  {
9
    overflow ++;
10
  }
11
  else
12
  {
13
    PORTA ^= (1<<PA4);
14
    overflow =0;
15
  }
16
}
17
//***************************************************************
18
19
20
int main (void)
21
{
22
  uart_init();
23
  I2C_Init(F_SCL);
24
25
  lcd_init(Display_1);
26
  lcd_init(Display_2);
27
  
28
  lcd_light(Display_1, true);
29
  lcd_light(Display_2, true);
30
      
31
//******** Timer 0 für Funktion des IC's Laufes**********************
32
  TIMSK |= (1<<TOIE0);  //Overflow Interrupt aktivieren
33
  TCCR0 |= (1<<CS01);    // Prescaler auf 1 setzen, Takt = 8MHz  
34
  sei();
35
  
36
  
37
/***Search Tempsensor*********************************************************************************************************************/
38
  Dallas_suchen_an();  
39
/***Search Tempsensor end*****************************************************************************************************************/
40
/***Feste Seriennummer********************************************************************************************************************/
41
  int zaehler = 2;
42
  for (int e = 0; e <8; e++)
43
  {
44
    Tempfuehler1[e] = FeuhlerArray[1][zaehler+1];
45
    Tempfuehler2[e] = FeuhlerArray[2][zaehler+1];
46
    Tempfuehler3[e] = FeuhlerArray[3][zaehler+1];    
47
    Tempfuehler4[e] = FeuhlerArray[4][zaehler+1];
48
    Tempfuehler5[e] = FeuhlerArray[5][zaehler+1];
49
    Tempfuehler6[e] = FeuhlerArray[6][zaehler+1];    
50
    Tempfuehler7[e] = FeuhlerArray[7][zaehler+1];
51
    Tempfuehler8[e] = FeuhlerArray[8][zaehler+1];
52
    Tempfuehler9[e] = FeuhlerArray[9][zaehler+1];    
53
    Tempfuehler10[e] = FeuhlerArray[10][zaehler+1];
54
    Tempfuehler11[e] = FeuhlerArray[11][zaehler+1];
55
    Tempfuehler12[e] = FeuhlerArray[12][zaehler+1];
56
    Tempfuehler13[e] = FeuhlerArray[13][zaehler+1];
57
    Tempfuehler14[e] = FeuhlerArray[14][zaehler+1];
58
    zaehler = zaehler+ 1;    
59
  }
60
/***Vergebene ID Nummer*******************************************************************************************************************/
61
  ID1 = FeuhlerArray[1][0];
62
  ID2 = FeuhlerArray[2][0];
63
  ID3 = FeuhlerArray[3][0];
64
  ID4 = FeuhlerArray[4][0];
65
  ID5 = FeuhlerArray[5][0];
66
  ID6 = FeuhlerArray[6][0];
67
  ID7 = FeuhlerArray[7][0];
68
  ID8 = FeuhlerArray[8][0];
69
  ID9 = FeuhlerArray[9][0];  
70
  ID10 = FeuhlerArray[10][0];
71
  ID11 = FeuhlerArray[11][0];
72
  ID12 = FeuhlerArray[12][0];
73
  ID13 = FeuhlerArray[13][0];
74
  ID14 = FeuhlerArray[14][0];
75
/*****************************************************************************************************************************************/
76
/***while Schleife************************************************************************************************************************/
77
  uint8_t Send1, Send;
78
  char test =0;
79
  
80
int FuehlerID, FuehlerArrayID;
81
  
82
  while(1)
83
  {
84
85
86
87
/*****Ausgänge I2C-Bus setzten************************************************************************************************************/
88
I2C_Start_Wait(Ausgaenge, I2C_WRITE);
89
I2C_Write(test);
90
I2C_Stop();
91
92
/*****Ausgänge I2C-Bus setzten ende*******************************************************************************************************/
93
/*****Eingänge I2C-Bus lesen**************************************************************************************************************/
94
95
I2C_Start_Wait(Eingaenge, I2C_READ);
96
Send1= I2C_ReadAck();
97
I2C_Stop();
98
/*****Eingänge I2C-Bus lesen ende*********************************************************************************************************/    
99
100
itoa(Send1,test,10);
101
/*if (Send1 == 255)
102
{
103
  Send1 =0;
104
}
105
Send1 = Send1 +1 ;
106
*/
107
108
    Bus_Reset();
109
    Byte_Schreiben(Skip_Rom);
110
    Byte_Schreiben(Convert_T);
111
112
    Temperatur_Messung(Temp1, Tempfuehler1, ID1);
113
    Temperatur_Messung(Temp1, Tempfuehler2, ID2);
114
    Temperatur_Messung(Temp1, Tempfuehler3, ID3);
115
    Temperatur_Messung(Temp1, Tempfuehler4, ID4);
116
    Temperatur_Messung(Temp1, Tempfuehler5, ID5);
117
    Temperatur_Messung(Temp1, Tempfuehler6, ID6);
118
    Temperatur_Messung(Temp1, Tempfuehler7, ID7);
119
    Temperatur_Messung(Temp1, Tempfuehler8, ID8);
120
    Temperatur_Messung(Temp1, Tempfuehler9, ID9);
121
          Temperatur_Messung(Temp_Zimmer, Tempfuehler10, ID10);
122
          Temperatur_Messung(Temp_Sonne, Tempfuehler11, ID11);
123
          Temperatur_Messung(Temp_Schatten, Tempfuehler12, ID12);
124
          Temperatur_Messung(Temp_Photovoltaik, Tempfuehler13, ID13);
125
    Temperatur_Messung(Temp1, Tempfuehler14, ID14);
126
127
    
128
    lcd_gotolc(Display_2, 1,1);
129
    lcd_print(Display_2, "Zimmer:");
130
    lcd_gotolc(Display_2, 1,12);
131
    lcd_print(Display_2, Temp_Zimmer);
132
133
    lcd_gotolc(Display_2, 2,1);
134
    lcd_print(Display_2, "Sonne:");
135
    lcd_gotolc(Display_2, 2,12);
136
    lcd_print(Display_2, Temp_Sonne);
137
138
    lcd_gotolc(Display_2, 3,1);
139
    lcd_print(Display_2, "Schatten:");
140
    lcd_gotolc(Display_2, 3,12);
141
    lcd_print(Display_2, Temp_Schatten);
142
143
    lcd_gotolc(Display_2, 4,1);
144
    lcd_print(Display_2, "Photo:");
145
    lcd_gotolc(Display_2, 4,12);
146
    lcd_print(Display_2, Temp_Photovoltaik);
147
  }
148
149
}

von Hermann Kokoschka (Gast)


Lesenswert?

Forist schrieb:
> Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Knoddelpusch schrieb:
> Ja wäre besser gewessen.

Ich glaube es einfach nicht.
Und SOFORT DANACH sendet der TO schon wieder 2 Seiten Code im Text...

von WF88 (Gast)


Lesenswert?

Du schreibst den Inhalt von test, liest aber nach Send1. Sehr sinnvoll 
;)


Pseudocode:
1
uint8_t data=0;
2
while(1) {
3
  i2csend(data);
4
  data = i2cread();
5
}

von Knoddelpusch (Gast)


Lesenswert?

Hallo,

ich bitte um Entschuldigung, werd in Zukunft länger Cods als Datei 
Anhängen, was ja wirklich Sinvoller ist wie ich das gemacht hab.

Ich habe jetzt mal den Code so Angepasst das ganze hängt in der 
while-Schleife.
1
uint8_t Send = 0;
2
I2C_Start_Wait(Eingaenge, I2C_READ);
3
Send = I2C_ReadAck();
4
I2C_Stop();
5
6
I2C_Start_Wait(Ausgaenge, I2C_WRITE);
7
I2C_Write(Send);
8
I2C_Stop();

Lass mir das gerade auf einem "normalen" Ausgangsprot von einem IC 
anzeigen. Da wäre dann der Ausgang 3 und 7. Wenn ich Eingänge am 
I2C-Eingang ändere tut sich nichts.

Ich denke also ich hab da einen Einlesefehler. Wobei mir der I2C-IC sagt 
das die Eingägne abgefragt wurden (Led-Ansteuerung).

von Peter D. (peda)


Lesenswert?

Knoddelpusch schrieb:
> Wenn ich Eingänge am
> I2C-Eingang ändere tut sich nichts.

Wenn Du sie von floatend auf High änderst, darf sich auch nichts tun.

von Guest (Gast)


Lesenswert?

1
Tempfuehler1[e] = FeuhlerArray[1][zaehler+1];
2
.....
3
ID1 = FeuhlerArray[1][0];
4
.....
5
int FuehlerID, FuehlerArrayID;
6
.....
kommt mir komisch vor!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Wenn ich mir die vielen _zaehler+1_ so ansehe:
1
  int zaehler = 2;
2
  for (int e = 0; e <8; e++)
3
  {
4
    Tempfuehler1[e] = FeuhlerArray[1][zaehler+1];
5
    :
6
    :
7
    Tempfuehler14[e] = FeuhlerArray[14][zaehler+1];
8
    zaehler = zaehler+ 1;    
9
  }
dann frage ich mich, warum der zaehler nicht einfach mit 3 
initialisiert:
1
  int zaehler = 3;
2
  for (int e = 0; e <8; e++)
3
  {
4
    Tempfuehler1[e] = FeuhlerArray[1][zaehler];
5
    :
6
    :
7
    Tempfuehler14[e] = FeuhlerArray[14][zaehler];
8
    zaehler = zaehler+ 1;    
9
  }
oder gleich am Anfang incrementiert wird:
1
  int zaehler = 2;
2
  for (int e = 0; e <8; e++)
3
  {
4
    zaehler = zaehler+ 1;    
5
    Tempfuehler1[e] = FeuhlerArray[1][zaehler];
6
    :
7
    :
8
    Tempfuehler14[e] = FeuhlerArray[14][zaehler];
9
  }

BTW: das FeuhlerArray hat ja wohl noch einen Schreibfeuhler in sich.

von Knoddelpusch (Gast)


Lesenswert?

Hallo,

Peter D. schrieb:
> Wenn Du sie von floatend auf High änderst, darf sich auch nichts tun.

Versteh gerad nicht so richtig was du damit meinst.
Wenn ich doch eine 1 bzw eine 0 am Eingang habe muss sich doch der 
Ausgang auch dementsprechen ändern auch wenn die Signal über den I2C-Bus 
kommen.


Lothar M. schrieb:
> Wenn ich mir die vielen _zaehler+1_ so ansehe:

Es war zwischenzeitlich noch eine anderes Arry mit in der Schleife wegen 
dem hab ich das mit
1
zaehler = zaehler+ 1;

gemacht. Man hätte aber auch gleich zwei Zähler anlegen können.

von Knoddelpusch (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich bin immer noch am Verzweifeln was das Ansteuern der I2C-Ausgänge 
angeht.
Habe jetzt schon ein neues Programm angelegt wo nur die Eingänge gelesen 
werden und auf die Ausgänge geschrieben wird zusätzlich lass ich mir 
jetzt auch den Takt des IC Anzeigen. Wobei mir der Takt wo mir die 
LED-Anzeigt nicht mit dem Übereinstimmt wie es eingestellt ist.

Die Warte Zeit nach dem Ausschalten der Ausgänge sollten normal 5 sek. 
sein. Es sind aber max nur 2 sek. Hab auch einen Screenshot von der 
Hardware-Einstellung der CPU bei gefügt.

von Knoddelpusch (Gast)


Lesenswert?

Noch was wo ich vergessen hab zu erwähnen.
An der Ausgangskarte geht immer das 2 und 6 bit an.

von Peter D. (peda)


Lesenswert?

Knoddelpusch schrieb:
> Wenn ich doch eine 1 bzw eine 0 am Eingang habe

Und woher kommen die?

Ein Schaltplan ist immer nützlich.

von Knoddelpusch (Gast)


Lesenswert?

Hallo

hab den Taster bzw dein Eingang so angeschlossen
1
5V --------------
2
      |
3
      |
4
      |
5
     |  ---> Stellt ein Taster da
6
      |
7
      |
8
      |----------- Eingang am I2C-IC
9
      |
10
     ---
11
    |   | 10 kOhm
12
    |   |
13
     ---
14
      |
15
0V ----------------

Das heist ich hab am Eingang durchgehen eine 0 anliegen bis ich den 
Taster Betätig dann kommt die 1

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.