mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PIC18F2550 und I²C


Autor: Sven E. (azu-fl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin!

Ich versuche mich hier grade mit dem PIC18F2550 an einer I²C-Bus 
Schaltung.

Ich habe mir bei sprut alles angelesen und auch versucht, sein 
Beispielprogramm für den PIC16F87x für meinen PIC abzuändern. Leider 
ohne Erfolg.

Auf der SCL Leitung kommt nichts an und auf der SDA konnte ich mit dem 
Oszilloskop auch keine Signale erkennen.

Vielleicht könnt ihr mir ja ein paar Tipps geben, wo mein Fehler liegt. 
Oder wenn ihr mehr Informationen braucht, fragt bitte. ;)

Danke schonmal im Vorraus!

Lg der Azu

Autor: Severino R. (severino)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kannst Du den Sourcecode posten, am besten reduziert auf das 
Wesentliche?

Autor: Sven E. (azu-fl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist es.
#include <P18F2550.inc>


; einstellen von RB0 & RB1 auf input
    banksel  TRISB            ; Bank 1
    movlw   B'00000011'         ; RB0,1 inputs
    movwf   TRISB
    banksel  TRISC
    movlw  B'00000011'
    iorwf   TRISC, f            ; + RC2=CCP1 output 


; einstellen des I2C-Taktes auf 100 kHz
    banksel  SSPADD            ; Bank 1
       movlw   d'9'                ; clock = 4 MHz /(4*(9+1)) = 100kHz
     movwf   SSPADD              ; für I2C


    banksel  SSPCON1
       movlw   B'00001000'         ; master mode, clock=Fosc/(4*(SSPADD+1))
     movwf   SSPCON1             ;


      bsf     SSPCON1, SSPEN      ; MSSP-Modul enable




;**Schreibe Wert 5 auf Speicher-Adresse 3 in PCF8574AP****************************

        call    i2c_on          ; Bus aktiv
        movlw   B'01110000'     ; 0 111 '000' 0
        call    i2c_tx          ; PCF8574AP zum Schreiben adressieren

        movlw   B'00000000'     ; high Teil der Adresse (Page)
        call    i2c_tx
        movlw   B'01110000'     ; low Teil der  Adresse
        call    i2c_tx

        movlw   B'10101010'     ; Wert der auf Adresse 3 soll
        call    i2c_tx

        call    i2c_off         ; Bus freigeben



;***I2C UNTERPROGRAMME************************************************************
;
; I2C-Bus im Master-Mode übernehmen
i2c_on
    banksel  PIR1
    bcf     PIR1, SSPIF     ; SSPIF Bit löschen
    banksel SSPCON2
        bsf     SSPCON2, SEN    ; Bus Übernahme anweisen
        goto    i2c_warte

; ein Byte aus W senden
i2c_tx
    banksel  SSPBUF
        movwf   SSPBUF          ; -> zum I2C-Slave übertragen
        goto    i2c_warte

;ein Byte vom Slave empfangen (nach SSPBUF)
i2c_rx
    banksel  SSPCON2
        bsf     SSPCON2, RCEN   ; Daten Empfang einschalten
        goto    i2c_warte

; I2C-Bus wieder freigeben
i2c_off
    banksel  SSPCON2
        bsf     SSPCON2, PEN    ; Bus Freigabe anweisen

i2c_warte
    banksel  PIR1
        btfss   PIR1, SSPIF     ; fertig?
        goto    i2c_warte       ; nein, noch nicht
        bcf     PIR1, SSPIF     ; ja, alles fertig, nun noch SSPIF zurücksetzen
        return

;***ENDE UNTERPROGRAMME**********************************************************

end

Autor: azu-fl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin nochmal!

Weiß jetzt schon einer mehr. Wäre echt nett. ;)

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für PIC Assembler ist das hier die falsche Ecke, sprut oder 
fernando-heitor sind da wohl besser geeignet.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist zwar kein Assembler, aber vieleicht reicht es als Tip ;)

//############################################################
void I2C_STOP(void)
{
 SSPCON2bits.PEN=1;    //Sende Stopcondition
 while(SSPCON2bits.PEN);  //warten bis Stopcondition beendet ist
}

//############################################################
void I2C_START(void)
{
 SSPCON2bits.SEN=1;    //Sende Startcondition
 while(SSPCON2bits.SEN);  //warten bis Startcondition beendet ist
}

Autor: Sven E. (azu-fl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include  <p18f2550.h>
#include  <i2c.h>
#include  <p18cxxx.h>


#pragma config OSC = XT  //CPU=4 MHz 
#pragma config PWRT = ON 
#pragma config BOR = OFF 
#pragma config WDT = OFF  //Watchdog Timer 
#pragma config LVP = OFF  //Low Voltage ICSP 



INT8S steps1 = 0;
INT8S steps2 = 0;
INT16S steps = 0;


unsigned char I2CEmpfang(unsigned char Adresse);



unsigned char I2CEmpfang(unsigned char Adresse)
{
IdleI2C();
StartI2C();
IdleI2C();
putcI2C(Adresse);
IdleI2C();
if ( SSPCON2bits.ACKSTAT )  
{
StopI2C();
    return 0;            //Return 0 Not ACK
}  
steps1 = ReadI2C();
IdleI2C();
AckI2C();
IdleI2C();
steps2 = ReadI2C();
IdleI2C();
AckI2C();
StopI2C();
} 



void main(void)
{

TRISC = 0xFF;
#define AdresseHandrad (0xA1)

//Konifiguration I2C Master
SSPSTATbits.SMP = 1; //Slew Rate aus
SSPSTATbits.CKE = 0; // SMBus Inputs Disabled
SSPCON1 = 0b00101000; // MSSP ein  in Mastermodus
SSPCON2 = 0b00001000; // Receive enable
SSPADD = 24; //Bus Takt 100Khz @ 10Mhz crystal

Nop();

while(1)
{
//Empfange 2 Datenbytes vom Handrad
I2CEmpfang(AdresseHandrad); 
// Adresse Handrad = A0 zum lesen verwende ich daher A1 
Nop();


}
}

Dieses Programm haben wir jetzt, aber wir können es nicht compilieren. 
Der Compiler meckert mit dem Error [1224] wegen dem "OSC" herum.

Weiß einer Rat?

Autor: Severino R. (severino)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuchs mal mit

#pragma config OSC = XT_XT  //CPU=4 MHz

Eventuell musst Du das Setting im Manual "PIC18 CONFIGURATION
SETTINGS ADDENDUM" (Dokument 51537D) prüfen. Es gibt ein Dutzend 
Möglichkeiten, aber keine die nur XT heisst.

Autor: Sven E. (azu-fl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah tatsächlich. Danke! Im Addendum haben wir was gefunden. Es muss FOSC 
heißen.
Jetzt sind zwar noch andere Fehler aufgetreten, aber wir versuchen es 
erstmal zu Fuß.
Ich melde mich, wenn ich wieder Hilfe brauche. :P

Autor: Sven E. (azu-fl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So ... das Compilieren klappt nun, aber wenn wir den PIC in die fertige 
Schaltung einsetzen, haben wir nichtmal einen Takt auf dem CLK des I²C 
Bus.

#include  <p18f2550.h>
#include  <i2c.h>
#include  <p18cxxx.h>


#pragma config FOSC = XT_XT  //CPU=4 MHz
#pragma config PWRT = ON
#pragma config BOR = OFF
#pragma config WDT = OFF  //Watchdog Timer
#pragma config LVP = OFF  //Low Voltage ICSP



int steps1 = 0;
int steps2 = 0;
int steps = 0;


unsigned char I2CEmpfang(unsigned char Adresse);



unsigned char I2CEmpfang(unsigned char Adresse)
{
IdleI2C();
StartI2C();
IdleI2C();
putcI2C(Adresse);
IdleI2C();
if ( SSPCON2bits.ACKSTAT )
{
StopI2C();
    return 0;            //Return 0 Not ACK
}
steps1 = ReadI2C();
IdleI2C();
AckI2C();
IdleI2C();
steps2 = ReadI2C();
IdleI2C();
AckI2C();
StopI2C();
}



void main(void)
{

TRISC = 0xFF;
#define AdresseHandrad (0xA1)

//Konifiguration I2C Master
SSPSTATbits.SMP = 1; //Slew Rate aus
SSPSTATbits.CKE = 0; // SMBus Inputs Disabled
SSPCON1 = 0b00101000; // MSSP ein  in Mastermodus
SSPCON2 = 0b00001000; // Receive enable
SSPADD = 24; //Bus Takt 100Khz @ 10Mhz crystal

Nop();

while(1)
{
//Empfange 2 Datenbytes vom Handrad
I2CEmpfang(AdresseHandrad);
// Adresse Handrad = A0 zum lesen verwende ich daher A1
Nop();


}
}

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Pullups eingebaut ?

Autor: Sven E. (azu-fl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja die sind dran. 1,8k

Autor: Severino R. (severino)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achtung!
Es hat zwar keinen Einfluss auf das Fehlen des Takts, aber

#pragma config FOSC = XT_XT  //CPU=4 MHz
..
..
SSPADD = 24; //Bus Takt 100Khz @ 10Mhz crystal

4 != 10

Autor: Sven E. (azu-fl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja stimmt. Bei SSPADD muss eine 9 rein. Danke!

Aber das löst wie du bereits sagtest das Problem mit dem fehlenden Takt 
noch nicht.^^

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kein Takt kann auch bedeuten das das Programm sich
einfach aufhängt. Jetzt musst du mal feststellen wo !

Und nimm mal diese Routine.

unsigned char I2CEmpfang(unsigned char Adresse)
{
IdleI2C();
StartI2C();
  while ( SSPCON2bits.SEN );      // wait until start condition is over
IdleI2C();
WriteI2C(Adresse | 0x01); // Wieso putcI2C(Adresse); ?
IdleI2C();
if ( SSPCON2bits.ACKSTAT )
{
StopI2C();
  while ( SSPCON2bits.PEN );      // wait until stop condition is over
    return 0;            //Return 0 Not ACK
}
steps1 = ReadI2C();
IdleI2C();
AckI2C();
IdleI2C();
steps2 = ReadI2C();
IdleI2C();
AckI2C();
StopI2C();
  while ( SSPCON2bits.PEN );      // wait until stop condition is over
}

Autor: Sven E. (azu-fl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich das im Simulator teste, geht er immer zu den Abfragen und 
wartet auf das PIR1 bit im SSPCON Register. Das ist ja die Antwort vom 
Slave. Wenn ich dieses Bit manuell setze springt er weiter und wartet in 
der nächsten Routine auf das PIR1. So geht das immer weiter, bis der 
Simulator die Simulation mit Hardware Stack Underflow beendet.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Als erstes noch mal zu deinem ASM-Code

>;**Schreibe Wert 5 auf Speicher-Adresse 3 in 
>PCF8574AP****************************
>
>        call    i2c_on          ; Bus aktiv
>        movlw   B'01110000'     ; 0 111 '000' 0
>        call    i2c_tx          ; PCF8574AP zum Schreiben adressieren
>
>        movlw   B'00000000'     ; high Teil der Adresse (Page)
>        call    i2c_tx
>        movlw   B'01110000'     ; low Teil der  Adresse
>        call    i2c_tx
>
>        movlw   B'10101010'     ; Wert der auf Adresse 3 soll
>        call    i2c_tx
>
>        call    i2c_off         ; Bus freigeben

Das ist eine Sequenz für ein I2C EEPROM. Für
PCF8574A nicht geeignet ! Warum nicht ?
Der PCF8574 hat nur ein Register. Speicher Adressen kennt der nicht.

Dann zum C-Code
>#define AdresseHandrad (0xA1)

Die Adresse des PCF8574A ist 0x70.

Der C-Code lässt sich sicher nur mit einigen warnings compilieren.
>#define AdresseHandrad (0xA1)
#define mitten in der main.c

unsigned char I2CEmpfang(unsigned char Adresse)
gibt keinen return Wert zurück.

>Wenn ich das im Simulator teste
Der Simulator gibt dir sicher kein ACK.
Das kann nur der Slave. Und der ist im Simulator nicht drin.

>wartet auf das PIR1 bit im SSPCON Register
PIR1 ist ein Register. SSPCON ist ein Register.
PIR1 kann kein Bit in SSPCON sein. Beim PIC18F2550
gibt es auch nur SSPCON1 und SSPCON2. SSPCON kennt der nicht.

Autor: azu-fl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die ausführliche Antwort!

Also ds Beste wäre für uns, wenn wir den ASM Code ans Laufen kriegen 
würden. Vielleicht hilft uns dein Tipp da ja schon. Mal schauen.

Ja, dass der Simulator mir kein ACK geben kann, weiß ich. Daher meinte 
ich ja das mit dem SSPCON und dem PIR1. Hab mich da etwas vertan.
Ich meinte das SSPIF Bit im PIR1 Register. Darauf wartet das Programm im 
Simulator ständig und wenn ich ihm das manuell gebe, springt er in die 
nächste Schleife und wartet wieder auf das SSPIF, bis er irgendwann mit 
Hardware Stack Underflow endet.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.