PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : I2C mit Master und Slave



inschenjoer
20.02.2007, 17:53
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 8-[ ein bißchen verzweifelt.

mfg
Sebastian

PicNick
20.02.2007, 18:30
Mich nur oberflächlich mit PIC und I2C beschäftigt:

Woher weiß der Slave, daß er die Adresse FE hat ? Das gehört doch ins SPADD ? Oder nicht ?