mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PIC12F1840 im I2C Slave Betrieb


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 Chris B. (chrisb20)


Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich versuche gerade einen PIC12F1840 im I2C Slave Modus in Gang zu 
bekommen.
Der Master der den Slave steuert ist ebenfalls ein PIC (PIC16F887)

Erste Aufgabe ist mal nur das der Master den Slave anspricht und dieser 
im
einen Wert zurück senden. Der Master soll dann den empfangenen Wert an 
den LEDs an PortD ausgeben.

Im Moment ist es so das ich entweder die Adresse des Slaves an den LEDs 
sehe oder nichts.

Hat schon einmal jemand vllt etwas mit dem PIC12F1840 in diesem Modus 
gemacht?

Danke für die Hilfe.

Gruß Chris Br

von icke (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Wie wäre es denn mit ein paar mehr Infromationen?
Wie sieht der Aufbau aus?
Hängen noch andere Teilnehmer am Bus?
Wie sieht der Code vom Slave aus? Wie der vom Master?
Hat der master schon mit anderen Slaves funktioniert?

von Chris B. (chrisb20)


Bewertung
0 lesenswert
nicht lesenswert
Hab den Fehler gefunden, lag an einer Varaiblen die den falschen 
Datentyp hatte und an einem Feld das nicht geladen war.

Werde später noch die Syntax als Beispiel für andere User rein stellen, 
wenn das Schreiben zum Slave auch funktioniert.

Gruß Chris Br

von Chris B. (chrisb20)


Bewertung
0 lesenswert
nicht lesenswert
So wie oben versprochen hier ist der Code um zwei PICs über I2C zu 
Betreiben.

Kurz etwas zum Aufbau:

PIC16F887:
Dieser PIC agiert als Master des I2C Bus, am PORTD sind 8 LEDs 
angeschlossen.

PIC12F1840:
Dieser PIC agiert als Slave am I2C Bus, an den nicht verwendeten PINs 
habe ich 3 LEDs angeschlossen.

Das Programm macht folgendes:
Zuerst intialisiert sich jeder Controller als Master oder Slave. Im 
Slave habe ich feste Werte als Rückgabewert eingespeichert.

Der Master schreibt den Slave an das er ihn auslesen möchte und dieser 
gibt ihm die fest vorgegebenen Werte zurück. Wenn der Master dem Slave 
Daten sendet dann habe ich jetzt gerade eine Routine drin die einfach 
wenn der Wert 1 kommt die erste LED einschaltet bei einer 2 die 2te und 
bei einer 3 die dritte.

Source Master:
/*-------------------------------------------------------------------------------------------------------------------------------------------------
  Filename:                         
  Date:                                         
  File Version:     1.0                                    
  Author:                                     
  Company:          ---            
  -------------------------------------------------------------------------------------------------------------------------------------------------
  Features:    
  -------------------------------------------------------------------------------------------------------------------------------------------------
  Ports:     
-------------------------------------------------------------------------------------------------------------------------------------------------*/
#define _LEGACY_HEADERS               // notwendig ab Compiler-Version 9.81
#include <htc.h>                  // einbinden des htc.h headers
#include <pic16f887.h>                // einbinden des pic16f887.h headers

#include "delay.h"                  // einbinden des Pausen Headers
#include "I2C_Treiber.h"              // einbinden des I2C_Treibers der die Ports richtig einrichtet

char Ausg = 0x00;                  // erstellen der Variable Ausg mit dem Datentyp char
int Addr = 0x70;                  // erstellen der Variable Addr für die Adresse des Slaves

void main(void)
{
TRISD = 0x00;                    // setze des TRISD Registers auf 0 => Ausgang
PORTD = 0x00;                    // lösche PORTD


I2C_init();                      // initialisere den Controller als Master

  while(1)
  {
  I2C_start();                  // I2C Startbedingung
  I2C_WriteToAddress(Addr);            // spreche den Slave an und sag ihm das du an ihn schreiben willst
  I2C_SendByte(0x03);                // Sende an den Slave ein Datenpacket
  I2C_stop();                    // I2C Stoppbedingung

  DelayMs(500);                  // warte 500ms

  I2C_start();                  // I2C Startbedingung
  I2C_ReadFromAddress(Addr);            // spreche den Slave an und sag ihm das du von ihm lesen willst
  Ausg = I2C_GetByte();              // schreibe die ausgelesenen Werte in die Variable Ausg
  I2C_SendAck();                  // schicke dem Slave ein Acknowledge damit er das zweite Datenpacket sendet
  Ausg = I2C_GetByte();              // zweites Datenpacket in die Variable Ausg schreiben
  I2C_stop();                    // I2C Stoppbedingung

  PORTD = Ausg;                  // schreibe auf PORTD den Wert aus Ausg
  DelayMs(50);                  // warte 50ms
  PORTD = 0x00;                  // lösche PORTD
  DelayMs(50);                  // warte 50ms
  Ausg = 0x00;                  // lösche die Variable Ausg

  }

}




Source Slave:
#include <htc.h>
#include <pic12f1840.h>
#include "delay.h"
#include "I2C_Treiber_PIC12F1840.h"

/* Variablen fuer die I2C Kommunikation */
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
unsigned char I2C_Adresse = 0x70;                  // I2C_Adresse
unsigned char Befehl = 0;                      // Ankommende Kommandos
unsigned char I2C_Daten[2] = {0x53, 0xAA};              // Feld für die I2C Übertrageung und wird mit Werten gefühlt 
unsigned char Write;                        // Variable Write für 2x Senden der Tachowerte(2 x Byte).          
bit I2C_Status = 0, Read = 0;                    // Statusvariable für den Eingang an Daten. Read für Schreibender parameter (I2C_Level)
bit I2C_level_Bit = 0;                        // Statusbit zum löschen von I2C_level
unsigned char i, loop = 10;                      // Schleifenvariablen

unsigned char Wert_MA = 0;


/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------*/



/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void interrupt my_isr(void)
{
  if(SSP1IE && SSP1IF)                      // Interrupt wird ausgelöst wenn der Interrupt Enable gesetzt ist und das Interrupt Flag gesetzt ist
  {
/*------Schreiben----------------------------------------------------------------*/
    if(R_nW)                          // Antwort von Slave
    {
I2C_Daten[0] = 0x53;                        // Beschreibe die Stelle 1 des Felds I2C_Daten
I2C_Daten[1] = 0xAA;                        // Beschreibe die Stelle 2 des Felds I2C_Daten

      SSP1BUF = I2C_Daten[Write];                // Schreibe die Daten in den SSP1BUF der die Daten über I2C überträgt
      CKP = 1;                        // Setze das Bit CKP
      SSP1IF = 0;                        // Lösche das Interrupt Flag
      I2C_Daten[Write] = 0;                  // Lösche die Daten die gerade übertragen wurden
      for(i = 0; i < loop; i++)                // Warten bis die übertragung vollständig ist
      {
        if(!BF)  break;                    // Warten bis die übertragung vollständig ist
      }    
      if (I2C_ReadAck())                    // Zweiter Byte wird angefragt
      {
        Write++;                      // Index wird erhöht
        if(Write > 1) Write = 0;              // Maximal 2 Byte sind möglch
      }
      else Write = 0;                      // wenn nicht lösche die Variable Write
//      Read = 0;                        
    }


/*------Lesen----------------------------------------------------------------*/
        if(!R_nW)                                               // Befehle vom Master
        {
                if (SSP1BUF == I2C_Adresse)    SSP1BUF = 0;         // Adresse im Register? Dann SSPBUF löschen
                else
                {
                    Befehl = SSP1BUF;                          // Befehl wird gespeichert
                    I2C_Status = 1;                              // Nach dem Eingang der Daten wird Status Bit gesetezt
                }
            SSP1IF = 0;                        // Lösche das Interrupt Flag
        }
  
    if (SSPOV) SSPOV = 0;                    // Überlauf Bit wird gelöscht
    
  }
}

//------------------------------------------------------------------------------
void main()
{
  ANSELA = 0xFF;                          // Konfiguriere den PORTA als Digital
  TRISA = 0x00;                            // Setze das TRISA Register auf 0 => Ausgang
  PORTA = 0x00;                            // Lösche den PORTA
  I2C_Init_Slave();                          // Initialisieren den Controller als Slave
  ei();                                // Enable Interrupt

    while(1)
    {
  if(Befehl == 1)                          // Wenn die Variable Befehl den Wert 1 hat
      {
      RA0 = 1;                        // dann setze RA0 auf 1 => LED    
      }
      
  if(Befehl == 2)                          // Wenn die Variable Befehl den Wert 2 hat
      {
      RA2 = 1;                        // dann setze RA2 auf 1 => LED    
      }
      
  if(Befehl == 3)                          // Wenn die Variable Befehl den Wert 3 hat
      {
      RA4 = 1;                        // dann setze RA4 auf 1 => LED  
      }
  }
  
}


Hoffe es hilft dem ein oder anderen weiter.

Gruß Chris Br

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.