Forum: Mikrocontroller und Digitale Elektronik PIC < > AVR (mit IIC)


von PIC N. (eigo) Benutzerseite


Angehängte Dateien:

Lesenswert?

Guten Morgen zusammen,
der Betreff sagt es eigentlich schon ganz gut. Ich bin dabei meine 
ersten Gehversuche mit dem IIC Bus zu machen und bin im Augenblick 
irgendwie fest gefahren. Kurz zu meiner Situation: Ich habe mir vor 
Jahren mal einen RP6 Roboter gekauft und bastle daran i.M. wieder ein 
bisschen herum.

Ich möchte eine IIC Verbindung von einem PIC18F2550 zu dem ATMEGA32 
aufbauen. Der ATMEGA32 ist der Hauptcontroller auf dem RP6. Der 
Hersteller liefert ein fertiges Slave Programm für den ATMEGA mit, mit 
dem es möglich sein soll alles über einen zweiten Controller als Master 
steuern zu lassen.

Also der PIC ist mein Master und der Atmel der Slave. Und mein Vorhaben 
zunächst ist, die digitalisierten Akku Werte aus dem Atmel zu laden 
(möchte diese an meinem LCD am PIC ausgeben). Es scheint leider nicht zu 
funktionieren. Meine Variablen bleiben leer (debugge mit ICD2).

Hier einmal mein kompletter main.c Code:
1
**********************************************************************************************/
2
//  Include Dateien
3
/**********************************************************************************************/
4
5
#include <p18cxxx.h>         // Für den PIC - wird autom. erkannt
6
#include "delays.h"                  // Für die Warteschleife
7
#include "RP6.X/lcd.h"
8
#include "RP6.X/adu.h"
9
#include "../h/i2c.h"
10
11
/**********************************************************************************************/
12
//  Konfiguration
13
/**********************************************************************************************/
14
15
#pragma config FOSC = HS      // Taktbereich auswählen
16
#pragma config PWRT = ON      // Power On Timer An
17
#pragma config BOR = OFF      // Brown Out Reset Aus
18
#pragma config WDT = OFF        // Watchdog Timer Aus
19
#pragma config LVP = OFF      // Low Voltage Programming Disable
20
#pragma config PBADEN = OFF      //
21
#pragma config VREGEN = OFF      //
22
#pragma config MCLRE = ON      // Master Clear Reset An
23
24
/**********************************************************************************************/
25
//  Globale Variablen deklarieren
26
/**********************************************************************************************/
27
28
unsigned char i;
29
unsigned char Akku[3];
30
31
/**********************************************************************************************/
32
//  Hauptprogramm
33
/**********************************************************************************************/
34
35
void main(void)
36
{
37
    unsigned char i;
38
39
    for(i=0;i<3;i++)Akku[i]=0;
40
41
// Konfiguration
42
    LATA=LATB=LATC=0;               //
43
    TRISA = 0x01;                   // PA1  --> Input Rest --> Output
44
    TRISB = 0x00;                   // Alle --> Output
45
    TRISC = 0x00;                   // Alle --> Output
46
47
    Setup_ADC();                    // AD Wandler Konfigurieren
48
    Init_LCD();                     // LCD Initialisieren
49
    OpenI2C(MASTER,SLEW_OFF);       // IIC Bus konfigurieren
50
    SSPADD=19;                      // 100kHz=8MHz/4*(SSPADD+1)
51
52
    while(1)
53
    {
54
        //I2C
55
        IdleI2C();
56
        StartI2C();                         //Start I2C
57
        WriteI2C(0x0A|0x00);                //Adresse senden (nächster Befehl schreibend)
58
        while(WriteI2C(0x15)!=0);           //Schreiben
59
        IdleI2C();                          //
60
        RestartI2C();                       //
61
        IdleI2C();                          //
62
        WriteI2C(0x0A|0x01);                //Adresse senden (nächster Befehl lesend)
63
        getsI2C(Akku,2);                    //Lesen und Ergebnis in Akku
64
        Akku[2]='\0';                       //Abschluss '0'
65
        NotAckI2C();                        //Not acknowledge
66
        while( SSPCON2bits.ACKEN!=0);       //
67
        CloseI2C();                         //I2C beenden
68
69
        //ADC
70
        Read_ADC(0);                        //Analog - Digital Pin auslesen
71
    }
72
}

Btw.: Ich benutze MPLAB X und den C18 Compiler.


Das Slave Programm vom Atmel ist im Anhang.

Viele Grüße Nico

von Oliver J. (skriptkiddy)


Lesenswert?

Mit dem Oszi oder dem LA mal den Bus angeschaut?

von PIC N. (eigo) Benutzerseite


Lesenswert?

Ja, da ist einiges im Gange (sorry für die blöde Ausdrucksweise). Ich 
versuche gerade die Daten von meinem DSO als csv herunter zu holen..

von PIC N. (eigo) Benutzerseite


Angehängte Dateien:

Lesenswert?

Schaut ziemlich wüst aus. Im Anhang sind die ersten Signalverläufe als 
Diagramm im *.xls Format. Anbei noch ein Shot vom DSO.

Liebe Grüße

von PIC N. (eigo) Benutzerseite


Angehängte Dateien:

Lesenswert?

Die Übertragung der Slave Adresse (0x0A) scheint jetzt schonal zu 
funktionieren.. So mal weiter schauen..

von Peter D. (peda)


Lesenswert?

Man schreibt beim I2C nicht einfach so ins Blaue hinein.
Du mußt nach jedem Adresse/Daten schreiben prüfen, ob ein ACK kommt.

Beim Lesen sendet der Master nach jedem Byte ein ACK und nach dem 
letzten Byte ein NACK.

Der Master muß das SCL-Stretching beherrschen.


Peter

von Peter D. (peda)


Lesenswert?

Nico M. schrieb:
> Die Übertragung der Slave Adresse (0x0A) scheint jetzt schonal zu
> funktionieren..

Sieht man aber nicht.
Das wichtigste Bit (ACK) hast Du schön abgeschnitten.


Peter

von PIC N. (eigo) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hallo Peter,
das stimmt.. Meine Aussage vor voreilig. Das ACK Bit wird nämlich nicht 
gesendet (warum auch immer).

Edit:
1
IdleI2C();
2
StartI2C();              //Start I2C
3
Data = SSPBUF;            //read any previous stored content in buffer to clear buffer full status
4
5
do
6
{
7
  Status = WriteI2C(0x0A|0x00);  //Adresse senden bis..
8
  if(Status == -1)                //Bus Kollision?
9
  {
10
    Data = SSPBUF;        //upon bus collision detection clear the buffer,
11
    SSPCON1bits.WCOL=0;         //Bus Kollisions Bit löschen
12
  }
13
}
14
while(Status!=0);                    //..die Übertragung erfolgreich war

von holger (Gast)


Lesenswert?

>  Status = WriteI2C(0x0A|0x00);  //Adresse senden bis..

Sende doch mal:

  Status = WriteI2C( 0x0A << 1 );  //Adresse senden bis..

von PIC N. (eigo) Benutzerseite


Lesenswert?

Hi Holger, das ändert nichts.

von Peter D. (peda)


Lesenswert?

Probier mal einfach alle 128 Adressen durch.


Peter

von PIC N. (eigo) Benutzerseite


Lesenswert?

Nabend zusammen,
konnte mich jetzt erst zurück melden war unterwegs. Also nach einiger 
Recherche bin ich auf das 
(http://www.roboternetz.de/community/threads/54623-%DCber-I2C-den-Akkuwert-aus-dem-Atmel-auslesen/page2?p=523311) 
gestoßen. Hier wird berichtet, dass die Adresse fälschlicherweise nicht 
dez. 10 sondern dez. 5 ist. Allerdings hat das nicht geholfen.

Ich werde jetzt wirklich mal alle Adressen durch probieren.

Gruß Nico

Edit: Stop mal, wenn die ADR dez. 5 ist, dann ist das 8.Bit ja "1" 
sprich der Controller gibt Daten zum Lesen bereit.. Dürfen I2C Bausteine 
denn nicht nur gerade Adressen haben?

von holger (Gast)


Lesenswert?

>Edit: Stop mal, wenn die ADR dez. 5 ist, dann ist das 8.Bit ja "1"
>sprich der Controller gibt Daten zum Lesen bereit.. Dürfen I2C Bausteine
>denn nicht nur gerade Adressen haben?

Was meinst du warum ich dir oben das mit dem links schieben
empfohlen habe? Die I2C Adresse ist in den oberen sieben Bit.

von PIC N. (eigo) Benutzerseite


Lesenswert?

=) So ich habe mal eine ältere Version des Slave Programms für den AVR 
herunter geladen, hier ist der Adressfehler noch nicht vorhanden. Jetzt 
läuft es wie folgt ab:

-> Adressierung
<- ACK
-> Senden 22 (High Register Akku)
-> Adressierung +1
<- ACK
<- Empfange FFh (das wird falsch sein ist auch FFh wenn ich den Low Wert 
auslese)

Das ausgelesene Byte muss falsch sein, da der Akkuwert sich iwo im 
Bereich von dez.: 720 bewegen muss. Was kann jetzt noch falsch sein?

Hier die Übertragung:
1
        IdleI2C();
2
        StartI2C();                         //Start I2C
3
       
4
        Data = SSPBUF;                      //read any previous stored content in buffer to clear buffer full status
5
        do
6
  {
7
  Status = WriteI2C(ADR|0x00);        //Adresse senden bis..
8
            if(Status == -1)                //Bus Kollision?
9
            {
10
                Data = SSPBUF;              //upon bus collision detection clear the buffer,
11
                SSPCON1bits.WCOL=0;         //Bus Kollisions Bit löschen
12
            }
13
  }
14
        while(Status!=0);                   //..die Übertragung erfolgreich war
15
        
16
        WriteI2C(22);                       //Dezimal: 22 Schreiben
17
        WriteI2C(ADR|0x01);                 //Adresse senden (nächster Befehl lesend)
18
        AKKUH=ReadI2C();                    //Lesen und Ergebnis in Akku
19
        IdleI2C();
20
        CloseI2C();                         //I2C beenden

PS: Habe zum Testen erst mal nur das High Register ausgelesen.

Gruß Nico

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.