Forum: Mikrocontroller und Digitale Elektronik PIC 18F2550 I²C Kommunikation XC8 Compiler


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von simon (Gast)


Lesenswert?

Hallo liebe User,

bin gerade echt am verzweifeln :-(

Mein Ziel: I²C Kommunikation über MPLab zwischen PIC18F2550 und einer 
Analog/Digital Input-Karte von Horter. Ich würde gerne analoge Daten von 
Sensoren einlesen und im Microkontroller anzeigen lassen.

Ich habe bisher versucht über eine Step-by-Step Anleitung eine 
Kommunikation herzustellen 
(https://electrosome.com/i2c-pic-microcontroller-mplab-xc8/). Den dort 
zur Verfügung gestellten Quellcode habe ich versucht auf meinen PIC 
anzupassen (im Tutorial wurde ein anderer PIC verwendet). Genau genommen 
habe ich nur die Eingangsports für SCL und SDA auf meinen Chip 
angepasst. Der Code lässt sich auch compilieren. Leider bin ich auf dem 
Gebiet noch ein blutiger Anfänger.

Meine Fragen:

1. Wo kann ich nun die Slave Adresse ansprechen (Ich habe eine Slave 
Adresse, habe diese jedoch nirgends im Code angesprochen)?

2. Wie mache ich nachdem alle Konfigurationen vorgenommen worden sind 
weiter? Wie bekomme ich meine Spannungswerte vom Slave eingelesen und in 
MPLab angezeigt?



Zur Hilfe habe ich euch meinen Programmcode einmal kopiert:



void I2C_Master_Init(const unsigned long c)
{
  SSPCON1 = 0b00101000;            //SSP Module as Master
  SSPCON2 = 0;
  SSPADD = (_XTAL_FREQ/(4*c))-1; //Setting Clock Speed
  SSPSTAT = 0;
  TRISB1 = 1;                   //Setting as input as given in datasheet
  TRISB0 = 1;                   //Setting as input as given in datasheet
}

void I2C_Master_Wait()
{
  while ((SSPSTAT & 0x04) || (SSPCON2 & 0x1F)); //Transmit is in 
progress
}


void I2C_Master_Start()
{
  I2C_Master_Wait();
  SEN = 1;             //Initiate start condition
}

void I2C_Master_RepeatedStart()
{
  I2C_Master_Wait();
  RSEN = 1;           //Initiate repeated start condition
}

void I2C_Master_Stop()
{
  I2C_Master_Wait();
  PEN = 1;           //Initiate stop condition
}

void I2C_Master_Write(unsigned d)
{
  I2C_Master_Wait();
  SSPBUF = d;         //Write data to SSPBUF
}

unsigned short I2C_Master_Read(unsigned short a)
{
  unsigned short temp;
  I2C_Master_Wait();
  RCEN = 1;
  I2C_Master_Wait();
  temp = SSPBUF;      //Read data from SSPBUF
  I2C_Master_Wait();
  ACKDT = (a)?0:1;    //Acknowledge bit
  ACKEN = 1;          //Acknowledge sequence
  return temp;
}


void I2C_Slave_Init(short address)
{
  SSPSTAT = 0x80;
  SSPADD = address; //Setting address
  SSPCON1 = 0x36;    //As a slave device
  SSPCON2 = 0x01;
  TRISB1 = 1;       //Setting as input as given in datasheet
  TRISB0 = 1;       //Setting as input as given in datasheet
  GIE = 1;          //Global interrupt enable
  PEIE = 1;         //Peripheral interrupt enable
  SSPIF = 0;        //Clear interrupt flag
  SSPIE = 1;        //Synchronous serial port interrupt enable
}


void interrupt I2C_Slave_Read()
{
  if(SSPIF == 1)
  {
    SSPCON1bits.CKP = 0;

    if ((SSPCON1bits.SSPOV) || (SSPCON1bits.WCOL)) //If overflow or 
collision
    {
      double z = SSPBUF; // Read the previous value to clear the buffer
      SSPCON1bits.SSPOV = 0; // Clear the overflow flag
      SSPCON1bits.WCOL = 0; // Clear the collision bit
      SSPCON1bits.CKP = 1;
    }
  }

  if(!SSPSTATbits.D_nA && !SSPSTATbits.R_nW) //If last byte was Address 
+ Write
  {
   double z = SSPBUF;
    while(!BF);
    PORTA = SSPBUF;
    SSPCON1bits.CKP = 1;
  }
  else if(!SSPSTATbits.D_nA && SSPSTATbits.R_nW) //If last byte was 
Address + Read
  {
   double z = SSPBUF;
    BF = 0;
    SSPBUF = PORTD ;
    SSPCON1bits.CKP = 1;
    while(SSPSTATbits.BF);
  }

  SSPIF = 0;
  }





Freue mich über jegliche Anregung :-)


Gruß Simon

von simon (Gast)


Lesenswert?

was ich bräuchte wäre ein Denkanstoß der mich irgendwie weiterbringt ... 
:)

von Michael .. (gismi)


Lesenswert?

Also ich versuche es mal, damit du wenigstens eine Antwort kriegst:

1) Wenn du nur einen zusammenkopierten unvollständigen Code hier 
reinschreibst, und keine Ahnung hast, was überhaupt gemacht werden soll, 
wird dir niemand helfen.

2) wenn du I2C mit XC8 benutzen willst, nutze doch die plib von 
Microchip (separater Download + aktivierung in den Linkeroptionen) oder 
die aktullere Variante: du lässt dir vom  Codeconfigurator ein 
.c/.h-Files erzeugen.

3) In diesem Forum wird dir keiner deine Aufgabe von Grund auf (ohne 
Bezahlung) machen. Aber wenn du zeigst, dass du etwas gemacht hast, und 
an einem speziellem Problem hängst, wir dir gerne geholfen.

mach folgende Schritte:
* Such dir eine Tutorial für PICs
* arbeite das durch und lass die ersten LEDs Blinken
* Wenn du verstanden hast, was du bis zu diesem Punkt alles gemach hast, 
such dir im Internet eine Beschreibung zu I2C und verstehe das Protokoll
* liess das Datenblatt dieser ominösen "Analog/Digital Input-Karte" und 
versuch zu verstehen, wie diese über I2C angesteuert werden kann
* Versuch das aus dem Datenblatt auf dein PIC umzusetzen

Wenn du Fortschritt mit einem kompletten minimalbeispiel zeigst, wirst 
du auch Antworten bekommen. Mit den Angaben wie aktuell, wird sich 
keiner die mühe machen.

von simon (Gast)


Lesenswert?

Michael .. schrieb:
> Also ich versuche es mal, damit du wenigstens eine Antwort
> kriegst:
>
> 1) Wenn du nur einen zusammenkopierten unvollständigen Code hier
> reinschreibst, und keine Ahnung hast, was überhaupt gemacht werden soll,
> wird dir niemand helfen.
>
> 2) wenn du I2C mit XC8 benutzen willst, nutze doch die plib von
> Microchip (separater Download + aktivierung in den Linkeroptionen) oder
> die aktullere Variante: du lässt dir vom  Codeconfigurator ein
> .c/.h-Files erzeugen.
>
> 3) In diesem Forum wird dir keiner deine Aufgabe von Grund auf (ohne
> Bezahlung) machen. Aber wenn du zeigst, dass du etwas gemacht hast, und
> an einem speziellem Problem hängst, wir dir gerne geholfen.
>
> mach folgende Schritte:
> * Such dir eine Tutorial für PICs
> * arbeite das durch und lass die ersten LEDs Blinken
> * Wenn du verstanden hast, was du bis zu diesem Punkt alles gemach hast,
> such dir im Internet eine Beschreibung zu I2C und verstehe das Protokoll
> * liess das Datenblatt dieser ominösen "Analog/Digital Input-Karte" und
> versuch zu verstehen, wie diese über I2C angesteuert werden kann
> * Versuch das aus dem Datenblatt auf dein PIC umzusetzen
>
> Wenn du Fortschritt mit einem kompletten minimalbeispiel zeigst, wirst
> du auch Antworten bekommen. Mit den Angaben wie aktuell, wird sich
> keiner die mühe machen.



Hallo Gismi,

Danke für deine Antwort.

Der Code Configurator wird auch in einigen tutorials verwendet um die 
Einstellungen für die I2C Kommunikation zu treffen. Leider wird mein 
Chip (PIC18F2550) nicht für dieses Plugin unterstützt (Es gibt zwar 
zusätzliche Bibliotheken für die 18F Familie, jedoch ist in dieser Liste 
mein Chip nicht dabei --> ich bekomme beim Startversuch eine 
Fehlermeldung).

Habe die Konfiguration der Register und das Ansprechen auch einigermaßen 
verstanden. Was meinst du damit, die plib von Microchip zu verwenden?

Gruß, Simon

von simon (Gast)


Angehängte Dateien:

Lesenswert?

Habe mal einen Screenshot der Fehlermeldung angehangen. Kannst du mir 
genauer sagen, wie ich diese plib einbinden kann?

von Michael .. (gismi)


Angehängte Dateien:

Lesenswert?

simon schrieb:
> Kannst du mir
> genauer sagen, wie ich diese plib einbinden kann?

Hier meine abgelegten Notizen dazu:
Pblib / plib.h  XC8
Folgendes muss gemacht werden
  • Plib downloaden
  http://www.microchip.com/mplab/compilers
  -> Download -> runter scrollen
  • In den Pfad vom XC8 compiler installieren
  • Plib linken aktivieren


im Installationsverzeichnis hat es entpsrechende Hilfe als pdf

von Volker S. (vloki)


Angehängte Dateien:

Lesenswert?

Was für eine XC8 Version hast du installiert?
Bis v1.34 müsste die PLib automatisch dabei sein.
Spätere Versionen erfordern eine separate Installation.
Die Installationsdatei findet sich da, wo auch der XC8 runter geladen 
werden kann (ganz unten unter "PIC18F Legacy Peripheral Libraries v..." 
)

Es kann allerdings sein, dass die PLib nicht mehr kompatibel mit deiner 
XC8 Version ist. Bei einigen PICs wurden Änderungen in den Headern 
gemacht, welche jetzt Fehler verursachen.

Eingebunden wird die Lib dann in den Projekt-Properties.
Haken bei "Link in Peripheral Library!
(geht bei meinem Projekt nicht, weil kein PIC18)

von Michael .. (gismi)


Lesenswert?

Volker S. schrieb:
> Was für eine XC8 Version hast du installiert?
> Bis v1.34 müsste die PLib automatisch dabei sein.

Bis wohin plib inkludiert ist wusste ich nicht. Ich glaube es ist v1.38 
die ich installiert habe.
Da es klang, dass simon frisch mit dem Thema anfängt, bin ich von einer 
aktuellen Version ausgegangen.

von simon (Gast)


Lesenswert?

Danke für eure Hilfe!

habe die plib.h nun in mein Projekt einbinden können (nutze MPLab X IDE 
v3.45). Hab noch 2 Fragen:

1. Was bringt mir die zusätzliche Bibliothek eigentlich?


2. Könnt ihr mir einen Tip geben, wo das Einrichten einer I2C 
Kommunikation gut erklärt wird? Mit dieser 
(https://electrosome.com/i2c-pic-microcontroller-mplab-xc8/) komme ich 
nicht so gut zurecht, bzw ich weiß nicht wie ich am Ende wenn ich den 
Code verstanden und angepasst habe, weiterkomme...

von Volker S. (vloki)


Lesenswert?

simon schrieb:
> habe die plib.h nun in mein Projekt einbinden können
Das ist nicht nötig. Wird über xc.h mit erledigt.

>(nutze MPLab X IDE v3.45). Hab noch 2 Fragen:
Die Version der IDE ist != der Version der Compiler.

>1. Was bringt mir die zusätzliche Bibliothek eigentlich?
PLib enthält Funktionen für die Benutzung der in Hardware 
implementierten Module. Schau am besten mal in die Doku 
MPLAB_XC8_Peripheral_Libraries.pdf
Die müsste im docs Ordner des Compilers sein.

von simon (Gast)


Lesenswert?

Volker S. schrieb:
> simon schrieb:
>> habe die plib.h nun in mein Projekt einbinden können
> Das ist nicht nötig. Wird über xc.h mit erledigt.
>
>>(nutze MPLab X IDE v3.45). Hab noch 2 Fragen:
> Die Version der IDE ist != der Version der Compiler.
>
>>1. Was bringt mir die zusätzliche Bibliothek eigentlich?
> PLib enthält Funktionen für die Benutzung der in Hardware
> implementierten Module. Schau am besten mal in die Doku
> MPLAB_XC8_Peripheral_Libraries.pdf
> Die müsste im docs Ordner des Compilers sein.


Sorry habe mich vertan, die Version des Compilers ist v1.38

von simon (Gast)


Angehängte Dateien:

Lesenswert?

Hallo nochmal. Ich bin jetzt ein wenig weitergekommen. Leider klappt es 
immernoch nicht so ganz mit der Kommunikation.

Ich habe das Programm darauf im Debug Modus laufen gelassen.
Irgendwas stimmt mit dem I2C_Read Befehl nicht. Er hängt sich in einer 
while-Schleife auf und macht an diesem Punkt nicht weiter (s. 
Screenshot, SSPSTATbits.BF), er empfängt anscheinend keine Daten. Habt 
ihr eine Ahnung wodrann das liegen könnte?


Wem es hilft dem habe ich außerdem noch meinen Quellcode beigefügt.




1
void INIT_I2C(void){
2
    OpenI2C(MASTER, SLEW_OFF);
3
    SSPADD = 19;
4
}
5
6
7
8
  
9
  unsigned int TEST = 0x0000;
10
  unsigned char LSB = 0x00, MSB = 0x00;
11
  
12
  
13
 
14
while(1) 
15
    
16
{
17
18
  
19
  
20
    StartI2C();              // Start condition I2C on bus
21
    IdleI2C();
22
23
    WriteI2C(0x95);          // addresses the chip + 1 LESEN
24
    IdleI2C();
25
   // AckI2C();
26
    
27
    
28
   
29
    LSB = ReadI2C();        // read the value from the SLAVE and store in TEST variable.
30
    IdleI2C();
31
   // AckI2C();
32
    MSB = ReadI2C();
33
    IdleI2C();
34
    
35
    
36
 //   NotAckI2C();               // Not Acknowledge condition. This will signal the SLAVE that reading data has completed.
37
    IdleI2C();
38
39
    StopI2C();              // Stop condition I2C on bus
40
    
41
    
42
    TEST = MSB << 8 | LSB;
43
    
44
    MSB=0x00;
45
    LSB=0x00;
46
}

von Volker S. (vloki)


Lesenswert?

simon schrieb:
> Analog/Digital Input-Karte von Horter. Ich würde gerne analoge Daten von
> Sensoren einlesen und im Microkontroller anzeigen lassen.

Poste doch mal einen Link zu einem Datenblatt. Dann könnten wir da rein 
schauen um eine Idee zu bekommen was zu tun ist...

von simon (Gast)


Lesenswert?

Volker S. schrieb:
> simon schrieb:
>> Analog/Digital Input-Karte von Horter. Ich würde gerne analoge Daten von
>> Sensoren einlesen und im Microkontroller anzeigen lassen.
>
> Poste doch mal einen Link zu einem Datenblatt. Dann könnten wir da rein
> schauen um eine Idee zu bekommen was zu tun ist...


Beschreibung:

http://www.horter.de/blog/i2c-analog-input-5-kanaele-10-bit/

Datenblatt steht leider nicht viel drinn:

http://www.horter.de/doku/i2c-hs-analog-input_db.pdf


Ich bin mir jedoch nicht sicher ob es was mit den Slave Modulen zutun 
hat. Denn der I2C_Read Befehl müsste doch auch ohne Slave funktionieren 
oder (Rückgabewert wäre dann halt random)?

Als Pull Up Resistors verwende ich 1,8kOhm.

Komisch das er gerade in dieser While-Schleife hängt...

von Michael .. (gismi)


Lesenswert?

du rufst INIT_I2C() gar nicht auf?

bitte poste immer komplette minimalbeispiele

von simon (Gast)


Lesenswert?

Michael .. schrieb:
> du rufst INIT_I2C() gar nicht auf?
>
> bitte poste immer komplette minimalbeispiele

Muss ich die Methode nochmal aufrufen?

Ich dachte eigentlich es genügt, durch den Befehl SSPADD = 19; die 
Baudrate festzulegen.

von Volker S. (vloki)


Lesenswert?

simon schrieb:
> Beschreibung:
>
> http://www.horter.de/blog/i2c-analog-input-5-kanaele-10-bit/
>
> Datenblatt steht leider nicht viel drinn:

Dachte mir, dass es sich um diese Teile handelt. Die Doku ist 
bescheiden.

Ich nehme jetzt einfach mal an, du willst immer den selben der 5 input 
Kanäle lesen und weiterhin, dass der Register-Zeiger innerhalb der Karte 
bei jedem Lesevorgang um eins erhöht wird. Dann müsstest du den Zieger 
in der while(1) Schleife immer wieder zurück stellen, also schreiben in 
das Zeigerregister.
Da die Adresse des Zeigerregisters nirgends angegeben wird könnten wir 
jetzt annehmen, dass jeder Schreibzugriff automatisch auf das 
Zeigerregister zugreift.
FALLS jetzt alle Annahmen zutreffen würden, dann könnte ein Lesezugriff 
so aussehen:
1
unsigned int readAdcRegister(unsigned char regAddress)
2
{
3
    unsigned int value;
4
5
    IdleI2C1();
6
    StartI2C1(); 
7
    while(SSP1CON2bits.SEN);
8
9
    WriteI2C1(MODUL_ADDRESS_WR);
10
    while(SSP1CON2bits.ACKSTAT);
11
12
    WriteI2C1(regAddress);
13
    while(SSP1CON2bits.ACKSTAT);
14
15
    RestartI2C1();
16
    while(SSP1CON2bits.SEN);
17
    WriteI2C1(MODUL_ADDRESS_RD);
18
    while(SSP1CON2bits.ACKSTAT);
19
20
    value = ReadI2C1();
21
    AckI2C1();
22
    value += 256 * ReadI2C1();
23
    NotAckI2C1();
24
    StopI2C1();
25
26
    return value;
27
}

von simon (Gast)


Lesenswert?

Habe jetzt den Code
1
OpenI2C(MASTER, SLEW_OFF);
2
    SSPADD = 19;

nochmal for die While-Schleife kopiert, funktioniert leider trotzdem 
nicht

von Volker S. (vloki)


Lesenswert?

simon schrieb:
> Ich bin mir jedoch nicht sicher ob es was mit den Slave Modulen zutun
> hat. Denn der I2C_Read Befehl müsste doch auch ohne Slave funktionieren
> oder (Rückgabewert wäre dann halt random)?

Nein, ohne Slaves geht das nicht. Die müssen ja SDA als ACKnoledge auf 
Low ziehen...

von simon (Gast)


Lesenswert?

> {
>     unsigned int value;
>
>     IdleI2C1();
>     StartI2C1();
>     while(SSP1CON2bits.SEN);
>
>     WriteI2C1(MODUL_ADDRESS_WR);
>     while(SSP1CON2bits.ACKSTAT);
>
>     WriteI2C1(regAddress);
>     while(SSP1CON2bits.ACKSTAT);
>
>     RestartI2C1();
>     while(SSP1CON2bits.SEN);
>     WriteI2C1(MODUL_ADDRESS_RD);
>     while(SSP1CON2bits.ACKSTAT);
>
>     value = ReadI2C1();
>     AckI2C1();
>     value += 256 * ReadI2C1();
>     NotAckI2C1();
>     StopI2C1();
>
>     return value;
> }

Hi Volker,

danke für deine Umfangreiche Hilfe.

Ich habe deinen Quellcode ausprobiert. Leider bekomme ich auch bei 
diesem Code im Debug Modus den Hänger in der genannten Schleife, wie 
oben im Screenshot gepostet (SSPSTATbits.BF). Worann kann das liegen das 
er immer bei diesem Schritt streikt? Der Rest funktioniert (glaube ich 
:-D )

von j.p. (Gast)


Lesenswert?

hallo,
versuch doch mal vor der while-schleife
 SSPBUF = 0; (später wieder entfernen)
wenns dann nicht mehr hängt, dann ist das SSPBUF-Register nach der 
Initialisierung nicht gelöscht worden.
Gruss j.p.

von Michael .. (gismi)


Lesenswert?

liess mal folgende Register aus, wärend er in der Schleife hängt:
SSPSTAT
SSPCON1
SSPCON2
SSPBUF
http://ww1.microchip.com/downloads/en/DeviceDoc/39632e.pdf 19.4

Und wenn du die möglichkeit hast, die Pins SCL/SDA mit einem Oszilloskop 
oder Logicanalyzer mal aufzeichnen.

: Bearbeitet durch User
von Volker S. (vloki)


Lesenswert?

Michael .. schrieb:
> Und wenn du die möglichkeit hast, die Pins SCL/SDA mit einem Oszilloskop

+1

von j.p. (Gast)


Lesenswert?

Hallo,
war gestern etwas müde, das mit dem SSPBUF = 0; würde nicht klappen.
Es ist normal, dass das Programm nicht aus der Schleife kommt, da ja in 
dieser while-Schleife das Programm darauf wartet, dass das 
SSPBUF-Register mit einem Daten-byte gefüllt wird.
Evtl. könnte man vorübergehend das (!) in der while-schleife entfernen, 
nur so, um das weitere Programm zu beobachten....
Gruss j.p.

von Volker S. (vloki)


Lesenswert?

j.p. schrieb:
> Evtl. könnte man vorübergehend das (!) in der while-schleife entfernen,

Das ist nicht so einfach, weil der Code ja in der Bibliothek schon 
kompiliert ist. Man muss die Funktion in das Projekt kopieren und da 
ändern, damit sich das überhaupt auswirkt.

von simon (Gast)


Lesenswert?

Michael .. schrieb:
> liess mal folgende Register aus, wärend er in der Schleife hängt:
> SSPSTAT
> SSPCON1
> SSPCON2
> SSPBUF
> http://ww1.microchip.com/downloads/en/DeviceDoc/39632e.pdf 19.4
>
> Und wenn du die möglichkeit hast, die Pins SCL/SDA mit einem Oszilloskop
> oder Logicanalyzer mal aufzeichnen.

Hello again und danke für eure Geduld mit mir. Die Möglichkeit mit einem 
Oszi den Bus zu beobachten habe ich leider nicht.

Im Anhang habe ich einen Screenshot der ausgelesenen Register 
angehangen.

Selbst wenn ich die Registeradresse um einen Kanal anzusprechen nicht 
kenne müsste ich ja eigentlich zumindest mal einen Random Kanal auslesen 
oder?

hmm habt ihr noch Ideen was da nicht klappt? :-(

von simon (Gast)


Angehängte Dateien:

Lesenswert?

sorry, hier der Screenshot

von simon (Gast)


Lesenswert?

hilft mir noch jemand? :-(

von Michael .. (gismi)


Lesenswert?

ohne eine Aufzeichnung, wass wirklich auf dem Bus passiert, ist es aus 
der Ferne extrem schwierig.
Für solche sachen habe ich >immer< einen Logicanalyzer in Betrieb.
Es gibt schon sehr günstige Modelle.

Stell mal die übertragungsfrequenz auf 100kHz.
Mit was für einer Frequenz betreibst du den PIC?

von j.p. (Gast)


Lesenswert?

Ist denn überhaupt ein Slave (richtig?) angeschlossen? evtl. Foto deiner 
Schaltung.

von simon (Gast)


Lesenswert?

@Michael:

Übertragungsfrequenz ist bereits auf 100kHz eingestellt
PIC-Takt: 8MHz

@j.p.:

Ich habe neben der o.g. Input Karte einen weiteren Slave angeschlossen, 
bleibt ebenso im gleichen Schritt hängen.

Ich mache heute Nachmittag mal ein Bild der Schaltung, bin gerade auf 
einer Weiterbildung.



Gruß Simon

von j.p. (Gast)


Lesenswert?

Hallo,
ein häufiger Fehler ist, dass GND von Slave und GND von Master nicht 
verbunden wurde, wenn beide nicht dieselbe Speisespannung haben....

von simon (Gast)


Lesenswert?

j.p. schrieb:
> Hallo,
> ein häufiger Fehler ist, dass GND von Slave und GND von Master nicht
> verbunden wurde, wenn beide nicht dieselbe Speisespannung haben....

Ist alles der selbe ground auf einem steckbrett

von j.p. (Gast)


Lesenswert?

welchen Programmer/debugger benutzt du?
Oder benutzt du nur den blanken Simulator von Mplabx?

von simon (Gast)



Lesenswert?

j.p. schrieb:
> welchen Programmer/debugger benutzt du?
> Oder benutzt du nur den blanken Simulator von Mplabx?

Ich benutze den ICD 3 Programmer.

Im Anhang hab ich euch mal einen Screenshot meiner Schaltung angehangen. 
Kann man ja "eigentlich" nicht viel falsch machen.

von simon (Gast)


Angehängte Dateien:

Lesenswert?

und noch eine Frage: Wie kann es überhaupt sein, dass die Variable "x" 
(s. Anhang) einen Wert (0x00F2) erhält? Müsste das nicht heißen das die 
I2C_Read Funktion einen Wert liefert ?

von j.p. (Gast)


Lesenswert?

Hallo,
deine Schaltung ist etwas abenteuerlich. Womit werden der Master und die 
Slaves gespiesen?
Ich an deiner Stelle würde vorläufig nur einen von beiden Slaves 
anhängen.
Die Slave-Adresse muss natürlich auch stimmen, sonst bleibt die 
while-Schleife hängen.
poste doch mal den komletten Code des pic18f2550 als Anhang.
Gruss j.p.

von simon (Gast)


Angehängte Dateien:

Lesenswert?

j.p. schrieb:
> Hallo,
> deine Schaltung ist etwas abenteuerlich. Womit werden der Master und die
> Slaves gespiesen?
> Ich an deiner Stelle würde vorläufig nur einen von beiden Slaves
> anhängen.
> Die Slave-Adresse muss natürlich auch stimmen, sonst bleibt die
> while-Schleife hängen.
> poste doch mal den komletten Code des pic18f2550 als Anhang.
> Gruss j.p.

Die Speisung der Schaltung ist wie folgt.

Master: ICSP Speisung durch ICD3
Slaves: VCC+GND des Mikrocontrollers (Masters)

Beide Jeweils von 5V versorgt.

Im Anhang der gewünschte Code. Habe die gesamte Projektdatei als Archiv 
hochgeladen.

von j.p. (Gast)


Lesenswert?

Hallo,
versuch mal in deinem header.h-file:    #pragma config PBADEN = OFF.

Gruss j.p.

von Volker S. (vloki)


Lesenswert?

simon schrieb:
> Habe die gesamte Projektdatei als Archiv
> hochgeladen.

Da ist >90% temporärer Müll drin!
Schau dir doch mal das an:

Package a Project Into a Zip File
http://microchip.wikidot.com/mplabx:projects-package

von Volker S. (vloki)


Lesenswert?

> #define ADRREAD 0x31
> #define ADRWRITE 0x31

Sollte ADRWRITE nicht 0x30 sein?

>    RestartI2C();
>    while(SSPCON2bits.SEN);
>    WriteI2C(ADRWRITE);
>    while(SSPCON2bits.ACKSTAT);

>    value = ReadI2C();

Lesen sollte man von ADRREAD!

von Volker S. (vloki)


Lesenswert?

>    while(1)
>
>    {
>
>    OpenI2C(MASTER, SLEW_OFF);
>    SSPADD = 19;

Einmal öffnen reicht -> raus aus der Endlosschleife!

von simon (Gast)


Lesenswert?

Hallo Leute,

j.p. schrieb:
> Hallo,
> versuch mal in deinem header.h-file:    #pragma config PBADEN = OFF.
>
> Gruss j.p.

Hab ich gemacht und seitdem kann ich das Programm debuggen OHNE in der 
genannten Schleife hängen zu bleiben :-) Ein Problem gelöst, danke!!

Die Addressen hab ich angepasst, also

ADRREAD 0x30
ADRWRITE 0x31

komischerweise funktionieren auch NUR diese Adressen, wenn ich andere 
Adressen ausprobiere bleibt  er beim debuggen hängen. Anscheinend merkt 
der Debugger, ob man die Slaves mit richtiger Adresse anspricht.

Leider bekomme ich noch keine realistichschen Werte eingelesen. Wie ihr 
auf meinem obigen Schaltungsbild sehen könnt, versuche ich mit einem 
Poti und Widerstand in Reihe verschiedene Spannung auf die Input Karte 
zu geben.

Nun lese ich in MPLab ALLE Eingänge aus (5*LSB+5*MSB+Zeiger), also 11 
Byte. Mache dies, da die Karte nicht gut dokumentiert ist und ich bis 
jetzt nicht genau weiß wie ich einen der 5 Kanäle anspreche (Adresse 
unbekannt).

Ergebnis: Alle 11 Read-Funktionen liefern den Wert "0x00FF". Eigentlich 
habe ich erwartet, das zumindest 2 Byte (LSB + MSB) einen Wert analog 
zur Eingangsspannung ausgeben :-( Pustekuchen...

von j.p. (Gast)


Lesenswert?

Hallo Simon,
hast du das Poti auch richtig angeschlossen?
Bevor du die Poti-Spannung in den ADC des Slaves gibst würde ich diese 
mit einem Voltmeter über den ganzen Poti-bereich messen, sie darf 2,048 
in keiner Stellung des Potis übersteigen, sonst droht die Zerstörung des 
ADC's....

von simon (Gast)


Lesenswert?

j.p. schrieb:
> Hallo Simon,
> hast du das Poti auch richtig angeschlossen?
> Bevor du die Poti-Spannung in den ADC des Slaves gibst würde ich diese
> mit einem Voltmeter über den ganzen Poti-bereich messen, sie darf 2,048
> in keiner Stellung des Potis übersteigen, sonst droht die Zerstörung des
> ADC's....


Jep das hab ich gemacht, habe den Widerstand so dimensioniert das UMax 
1,5V beträgt

von j.p. (Gast)


Lesenswert?

Bin etwas auf Kriegsfuss mit den Libraries von Microchip, aber beim 
Betrachten deines Codes glaube ich, dass du die Variable "value" für den 
low-Bereich des 16-bit-Wertes so wie in deinem Code brauchst, dann aber 
noch eine  Variable z.B. "valueH" für den high-Bereich des 16-bit-Wertes 
brauchtest, so in etwa:
  valueH += 256 * ReadI2C();
Was genau in dem ganzen Code vor sich geht kann ich leider nicht 
beurteilen, da ich die Peripherie-Bibliotheken nicht installiert habe.
Gruss

von j.p. (Gast)


Lesenswert?

Vergiss was ich geschrieben habe, value ist ja schon 16-bit (int value).

von Volker S. (vloki)


Lesenswert?

simon schrieb:
> Die Addressen hab ich angepasst, also
> ADRREAD 0x30
> ADRWRITE 0x31

Sollte das nicht eher umgekehrt sein?

von simon (Gast)


Lesenswert?

Volker S. schrieb:
> simon schrieb:
>> Die Addressen hab ich angepasst, also
>> ADRREAD 0x30
>> ADRWRITE 0x31
>
> Sollte das nicht eher umgekehrt sein?

Entschuldigung habe mich vertippt, ja! Ist auch im Code richtig 
definiert. Echt sehr komisch das sich da nix tut :-( Alle Return Werte 
der Read-Funtion 0x00FF (komischerweise genau 255 dezimal)...

Ich bin jetzt schon seit Tagen an diesem Mist Bus drann :-/

Habe am kommenden Montag einen Termin in meiner Firma, an dem ich die 
Möglichkeit habe das Bus Protokoll mit einem Oszi anzusehen. Ich hoffe 
das bringt Klarheit.

Bedanke mich bis hierhin nochmal für eure Hilfe heute und die der 
letzten Tage, mich fasziniert echt der Traffic, den dieses Forum 
bietet...

Zur vervollständigung nochmals der Code bis hierhin :-)
1
     OpenI2C(MASTER, SLEW_OFF);
2
     SSPADD = 19;
3
   
4
    while(1)
5
        
6
    {   
7
    
8
    int regAddress=0x01;
9
    unsigned int value=0;
10
    unsigned int x, LSB, MSB, Zeiger, a, b, c, d, e, f, g, h;
11
    
12
    IdleI2C();
13
    StartI2C(); 
14
    while(SSPCON2bits.SEN);
15
16
    WriteI2C(0x30);
17
    while(SSPCON2bits.ACKSTAT);
18
19
  //  WriteI2C(redAddress);
20
  //  while(SSPCON2bits.ACKSTAT);
21
22
    RestartI2C();
23
    while(SSPCON2bits.SEN);
24
    WriteI2C(0x31);
25
    while(SSPCON2bits.ACKSTAT);
26
27
    
28
    Zeiger = ReadI2C();
29
    AckI2C();
30
    LSB = ReadI2C();
31
    AckI2C();
32
    MSB = ReadI2C();
33
    value = MSB << 8 | LSB;
34
    x = value;
35
36
    NotAckI2C();
37
    StopI2C();
38
    
39
   }
40
41
42
    return;

von Volker S. (vloki)


Lesenswert?

Warum hast du das schreiben der gewünschten Adresse,
welche du auslesen willst, auskommentiert?

Dann solltest du es besser ganz bleiben lassen.

: Bearbeitet durch User
von Klaus (Gast)


Lesenswert?

simon schrieb:
> ( Alle Return Werte
> der Read-Funtion 0x00FF (komischerweise genau 255 dezimal)...

Da ist nix komisch. Der Bus wird durch die Pullups auf High gezogen, ein 
ungetriebener Bus liefert also immer Einsen. Und das ist nun mal Hex 
0xff. Wer das komisch findet, hat I2C nicht verstanden.

MfG Klaus

von Volker S. (vloki)


Lesenswert?

Vielleicht findet er es nur komisch, dass HB immer 0x00 und LB immer 
0xFF sein soll?

@Simon:
Lies doch mal alle direkt nacheinander.
Also Adresse auf Null setzen und dann 11 mal lesen und die Bytes in 
deine Werte einsortieren.


simon schrieb:
> Habe am kommenden Montag einen Termin in meiner Firma, an dem ich die
> Möglichkeit habe das Bus Protokoll mit einem Oszi anzusehen. Ich hoffe
> das bringt Klarheit.

Ich weiß gar nicht wie ich ohne Oszilloskop irgendwas entwickeln könnte 
;-)

: Bearbeitet durch User
von K. J. (Gast)


Lesenswert?

simon schrieb:

> komischerweise funktionieren auch NUR diese Adressen, wenn ich andere
> Adressen ausprobiere bleibt  er beim debuggen hängen. Anscheinend merkt
> der Debugger, ob man die Slaves mit richtiger Adresse anspricht.
>
Kann das sein das deine Config für den Slave so ist das er auf alle 
Adressen Reagiert, und dadurch stehen bleibt ?

Ansonsten ist die Logic vom MSSP bei I²C recht dumm, Adresse + Daten 
kommen rein und müssen im Programm gegen gescheckt werden, und dann 
kannst erst Daten wieder herausschieben.

Wie Klaus schon schrieb 0xFF ist ein Zeichen dafür das da nix Rausgeht, 
eventuell passen die Pullups nicht, aber das kannst ja dann die Tage mal 
ausmessen.

von simon (Gast)


Lesenswert?

ES KLAPPT!!!!!!! Zumindest mit einem I2C Temperatursensor.

@ Volker:

Hab die Register aus dem Grund ausgeklammert, da ich nicht weiß wie die 
Registeradressen angeordnet sind -> Daher habe ich einfach 11 Bytes 
ausgelesen (daher auch so viele Variablen oben deklariert) und gehofft 
den richtigen Ausgang damit auf jedenfall zu messen.

Bei dem Temperatursensor funktioniert es einwandfrei, dort kenne ich 
auch die Registervergabe.

Werde jetzt den Hersteller anfragen ob es zu dieser Input Karte auch ein 
Registerverzeichnis gibt.

Vielen Dank

von j.p. (Gast)


Lesenswert?

Hallo Simon,
na, da hast du aber echt Fortschritte gemacht, gratuliere!
Ich denke du wolltest lernen, mit I2-bus umzugehen, sonst könnte man 
nämlich einfacher, schneller und billiger Sensoren direkt mit dem ADC 
des PIC18F2550 auslesen und die Resultate z.B. mit dem chipeigenen USB 
desselben Pics direkt am PC ansehen, Microchip stellt dazu sogar eine 
VC-USB-Anwendung zur Verfügung.
Gruss j.p.

von simon (Gast)


Lesenswert?

j.p. schrieb:
> Hallo Simon,
> na, da hast du aber echt Fortschritte gemacht, gratuliere!
> Ich denke du wolltest lernen, mit I2-bus umzugehen, sonst könnte man
> nämlich einfacher, schneller und billiger Sensoren direkt mit dem ADC
> des PIC18F2550 auslesen und die Resultate z.B. mit dem chipeigenen USB
> desselben Pics direkt am PC ansehen, Microchip stellt dazu sogar eine
> VC-USB-Anwendung zur Verfügung.
> Gruss j.p.

Ja es ging mir wie du schon sagtest darum, den Bus zu verstehen und zum 
laufen zu bekommen. Mache gerade das Abschlussprojekt zum staatlich 
gepr. Elektrotechniker, und da sollen wir zeigen, das wir was draufhaben 
(oder auch nicht) :-D

von Heiner (Gast)


Lesenswert?

simon schrieb:
> und da sollen wir zeigen, das wir was draufhaben
> (oder auch nicht) :-D

für mich komplett durchgefallen. Armutszeugnis für den
Techniker-Titel.

lg Heiner

von j.p. (Gast)


Lesenswert?

Hallo Simon,
lass dich ja nicht von Heiner runterkriegen, er ist nicht dein 
Prüfungsexperte!
Viel Erfolg wünscht dir Jochen-Paul

von simon (Gast)


Lesenswert?

Leider stehen in RLP Mikrocontroller nicht im Lehrplan, obwohl ich das 
Thema sehr interessant finde....ist daher für mich, genau wie auch das 
Thema Bus Systeme (kenne die nur auf dem Papier, Strukturen etc) alles 
Neuland...Fachrichtung Energieelektronik halt :-)

von Ingo S. (schicki)


Lesenswert?

Hallo,

ich nutze zum Init eines PIC18F46K80 bei 25MHz folgenden Code
1
/************************************************************************/
2
// Include-Dateien
3
/************************************************************************/
4
#include <i2c.h>        // Include für die I²C Schnittstelle
5
/************************************************************************/
6
7
/************************************************************************/
8
// I²C Schnittstelle initialisieren
9
/************************************************************************/
10
void Init_I2C_Master(unsigned short int Takt)
11
{ 
12
   TRISDbits.TRISD5  = 1;    // SDA-Leitung
13
   TRISDbits.TRISD6  = 1;    // SCL-Leitung
14
15
      switch (Takt) {
16
      case 100:    SSPADD = 62; // 100 KHz Takt bei 25 MHz
17
                OpenI2C(MASTER, SLEW_OFF);
18
              break;
19
/************************************************************************/
20
      case 400:    SSPADD = 15; // 400 KHz Takt bei 25 MHz
21
              OpenI2C(MASTER, SLEW_ON);
22
              break;
23
          }
24
}
25
/************************************************************************/

Ich habe ebenfalls die Zusatz-Libary mit eingefügt. Bei den Chips 
PCF8574, PCF8591 und MCP23017 funktioniert das ganze. Wenn Du willst 
kann ich Dir die Libarys zusenden.

Ingo

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.