Forum: Mikrocontroller und Digitale Elektronik PIC: I2C mit Master und Slave


von inschenjoer (Gast)


Lesenswert?

Hallo,

ich habe zwei PIC16F873. Einer davon soll als Master arbeiten und einer 
als Slave.

Master:
=======
void i2c_test()
{
  SEN = 1;               // Bus übernehmen
  while (SSPIF == 0);    // warten bis der Bus übernommen wurde
  SSPIF = 0;             // Bit zurücksetzen

  SSPBUF = 0b.0100.1110 & 0xFE; // an Adresse 0b.0100.1110 schreiben
  while (SSPIF == 0);    // warten bis ein ACK kommt
  SSPIF = 0;             // Bit zurücksetzen

  SSPBUF = 'a';          // ein 'a' schreiben
  while (SSPIF == 0);    // warten bis ein ACK kommt
  SSPIF = 0;             // Bit zurücksetzen

  PEN = 1;               // Bus wieder freigeben
  while (SSPIF == 0);    // warten bis der Bus freigegeben wurde
  SSPIF = 0;             // Bit zurücksetzen
}

void main(void)
{
  ...

  // alle analogen Eingänge auf digital umstellen
  ADCON1 = 7;               // Die analogen Eingänge werden als digitale 
Eingänge
                            // genutzt.
  // RA0 bis RA3 sind externe Eingänge der originalen Platine zur
  // Motoransteuerung
  // RA4 und RA5 sind UNBELEGTE Pins
  TRISA = 0b.1111.1111;      // Alle Pins des Ports A sind als Eingänge 
geschaltet.

  // RB1 und RB2 sind die Ausgänge um die Richtung der beiden Motoren zu 
steuern
  // RB0, RB3 bis RB7 sind UNGENUTZTE Pins
  TRISB = 0b.0000.0000;      // Alle Pins des Ports B sind als Ausgänge 
geschaltet.
  PORTB = 0b.0000.0000;     // Alle Pins des Port B auf low schalten

  // RC0 und RC5 sind ungenutzte Pins
  // RC1 und RC2 sind PWM-Ausgänge zur Geschwindigkeitsregelung der 
Motoren
  // RC3 und RC4 sind I2C-Leitungen
  // RC6 ist der serielle Ausgang
  // RC7 ist der serielle Eingang
  TRISC = 0b.1001.1000;     // Alle Pins bis auf RC3, RC4 und RC7 als 
Ausgänge definiert
                            // RC3 = I2C, RC4 = I2C
  PORTC = 0b.0000.0000;     // Alle Pins des Port C auf low schalten

  delay100(40);

  // I2C einstellen und aktivieren
  SSPADD = 0b.0000.1100;    // Teiler von 12 -> i1c-takt von 385kHz
  SSPCON = 0b.0000.1000;    // I2C master mode
  SSPEN = 1;

  PEIE = 1;   // Peripheral Interrupt Enable bit
  RCIE = 1;   // USART Receive Interrupt Enable bit
  GIE = 1;    // global interrupt enable
  erasebuffer();

  while(1)
  {
    i2c_test();
  }
}

Slave:
======
#pragma origin 4      // Der folgende Code steht ab Adresse 4

interrupt int_handler(void)
{
  int_save_registers      // W, STATUS (und  PCLATH) retten
  char sv_FSR = FSR;  // save FSR if required

  //Interrupt from MSSP (I2C)-module
  if(SSPIF)
  {
    SSPIF=0; //Reset interrupt from MSSP-module.

    char x = SSPBUF;
    PORTB.0 = 1;
    PORTB.1 = 1;
    PORTB.3 = 1;
  }

  FSR = sv_FSR;       // restore FSR if saved
  int_restore_registers      // W, STATUS (und PCLATH) Wiederherstellen
}

void main(void)
{
  // alle analogen Eingänge auf digital umstellen
  ADCON1 = 7;               // Die analogen Eingänge werden als digitale 
Eingänge
                            // genutzt.

  // RA0, RA3 und RA4 werden als Eingänge genutzt
  TRISA = 0b.1111.1111;      // Alle Pins des Ports A sind als Eingänge 
geschaltet.

  // RB0, RB1 und RB3 sind Ausgänge, die auf low geschaltet werden
  // RB2, RB5, RB6 und RB7 sind Eingänge
  TRISB = 0b.1110.0100;
  PORTB = 0b.0000.0000;

  // RC2 ist ein Eingang
  // RC3 und RC4 sind für I2C
  // RC5 und RC6 ist ein Ausgang

  TRISC = 0b.0001.1100;
  PORTC = 0b.0000.0000;     // Alle Pins des Port C auf low schalten

  // I2C einstellen und aktivieren

  SSPADD = 0x40;    // Teiler von 12 -> i1c-takt von 385kHz
  SSPCON = 0b.0011.0110;    // I2C slave mode
  SSPEN = 1;

  PEIE = 1;   // Peripheral Interrupt Enable bit
  SSPIE = 1;  // Synchronous Serial Port Interrupt Enable bit
  GIE = 1;    //global interrupt enable

  SSPIF = 0;      // clear SSPIF interrupt flag

  while(1)
  {
  }
}

Wenn alles funktionieren würde, dann würde zumindest erstmal die 
Interrupt-Routine des Slave aufgerufen. Dort sollten dann die Ausgänge 
RB0, RB1 und RB2 auf high gezogen werden. Das passiert aber leider 
nicht. Hat evtl. jemand eine Idee was ich falsch mache? Ich bin schon 
wieder ein bißchen verzweifelt.

mfg
Sebastian

von Bernd R. (Firma: Promaxx.net) (bigwumpus)


Lesenswert?

Am Slave hast Du in SSPADD etwas abgelegt. Du meinst, es sei die 
Geschwindigkeit, der PIC meint, es sei seine I2C-Adresse.

Das paßt nicht.

Nur der Master setzt die Geschwindigkeit, der Slave setzt seine Adresse 
(0b.0100.1110).

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.