mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Master <->Slave SPI - Kommunikationsprotokoll


Autor: Viktor (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo allerseits!

Ich versuche zur zeit ein Kommunikationsprotokoll zwischen ATmega128 und 
ATMega8 aufzubauen.

Der Master schick zuerst ein CMDByte an den Slave, dieser entscheidet 
was demnächst geschieht. Wenn der MSBit(R/W-Bit) im CMDByte gesetzt ist, 
dann sollen die Daten gelesen wereden, d.h. es kommen nach dem CMDByte 
keine Daten mehr an. Slave wertet die untersten 5Bits aus dem CMDByte 
aus und entscheidet je nach Befehl, welche Daten in den Sendepuffer 
gelegt werden sollen. Anschließend teilt er dem Master mit Hilfe des 
BUSY Signals mit, dass er die Daten jetzt abholen kann. Darauf hin 
schickt Master die entsprechende anzahl der Dummy-Bytes zum Slave.

Im Schreibmodus soll Master die Möglichkeit haben, entweder sehr kurze 
Befehle an Slave (nur den Befehlsbyte(CMDByte)), oder nach dem CMDByte 
auch weitere Bytes mit dazugehörigen Parametern senden zu können.

CMDByte
MSB
[RWBit|X|X|CMDBit4|CMDBit3|CMDBit2|CMDBit1|CMDBit0]

Pinbelegung________
ATMega182    ATMega8
MISO <======= MISO
MOSI =======> MOSI
SCK ========> SCK
/SS ========> /SS
PE7 <======== PB1(BUSY)

Nun zu meinem Problem...
Die Hardware funktioniert schon, die Übertragung funktioniert in beiden 
Richtungen. Ich kann mehrere Bytes aus dem voreingestellten Puffer 
lesen.
Auch wenn ich zuerst ein CMDByte mit dem Schreibbefehl sende um den 
Puffer zu manipulieren, klappt es ebenfalls, denn ich finde die Zahl 
auch in den gelesenen Daten wieder.

Nun, wenn ich jetzt aber beim Schreibvorgang auch paar Bytes hinterher 
sende und anschließend versuche die Daten aus dem Puffer zu lesen, 
erhalte nur 0 0 0 0 anstatt 9 33 1 1.

Hat jemand schon so etwas gemacht?
Wie könnte man das ganze noch verbessern (Programmiertechnisch)?

Da ich mich noch nicht soo gut in Sachen C auskenne, bitte ich um Hilfe.
//######### Master ############################################################
int main(void){

  unsigned char i,dummy,data,k=0;
  unsigned char rxdata[5]= {};
  unsigned char txdata[5]= {9,1,2,9};
  char buffer [10]= {0};
  
  glcd_print(0,0,"write...");
  
  PORTB &= ~(1<<PB0);       // /SS Pin am Slave auf low
  dummy= spi_transceive(0x12);    // Commandobyte (RWBit(7)=0,lesen + Befehl 0x12)
  PORTB |= (1<<PB0);      // /SS Pin am Slave auf high
  _delay_us(5);
  /*
  while(!(PINE & (1<<PE7)));    // Warte bis Slave bereit(solange PE7=0)
  PORTB &= ~(1<<PB0);       // /SS Pin am Slave auf low
  for(i=0;i<4;i++){      // sende daten
    data= txdata[i];
    dummy= spi_transceive(data);
    _delay_us(5);
  }*/

  delay_nms(2000);
  glcd_print(0,0,"read...");
  
  PORTB &= ~(1<<PB0);       // /SS Pin am Slave auf low
  dummy=spi_transceive(129);    // Commandobyte (RWBit(7)=1,lesen + Befehl 0x01)
  PORTB |= (1<<PB0);      // /SS Pin am Slave auf high
  _delay_us(5);        // !muss noch evtl. noch verringert werden
  
  while(!(PINE & (1<<PE7)));    // Warte bis Slave bereit(solange PE7=0)
  PORTB &= ~(1<<PB0);       // /SS Pin am Slave auf low
  for(i=0;i<4;i++){      // Hole die Daten
    rxdata[i]= spi_transceive(0x00);
    _delay_us(5);
  }
  PORTB |= (1<<PB0);      // /SS Pin am Slave auf high
  
  //Daten ausgeben
  for(i=0;i<4;i++){
    data= rxdata[i];
    sprintf(buffer,"%1d",data);
    glcd_print(k,1,buffer);
    k+=2;
  }

  return(0);
}


//######### Slave ############################################################

//************************************************************************
//    GLOBAL VARIABLES
//************************************************************************
volatile unsigned char rx_buf[12]= {0x00};  //Schreibpufer
volatile unsigned char tx_buf[12]= {0x00};  //Lesepufer
volatile unsigned char rx_cnt= 0;                //RX Zähler
volatile unsigned char tx_cnt= 0;                //TX Zähler
volatile unsigned char CFREG= 0x00;              //ControlFlagRegister
static unsigned char cmd_byte= 0x00;            //Commando byte

enum{DB0= 0,DB1,DB2,DB3,DB4,DB5,DB6,DB7,DB8,DB9,DB10,DB11};
volatile unsigned char buffer[10] = {9,1,1,1,5,6,7,8,9,0};


//************************************************************************
//    I S R
//************************************************************************
ISR(SPI_STC_vect){
  rx_buf[rx_cnt++]= SPDR;  //Daten Byteweise ins Puffer schreiben
  SPDR= tx_buf[++tx_cnt];  //Daten Byteweise aus dem Puffer lesen
}

//************************************************************************
//    MAINLOOP
//************************************************************************
int main(void){
  main_init();
  
  while(1){
    if(!(PINB & (1<<P_SS))){      //Übertragung beginnt
      while(!(PINB & (1<<P_SS)));    //Warte bis CMDByte übertragen wurde
      P_BUSY_LOW();        //Master wartet
      cmd_byte= rx_buf[DB0];      //CMDByte abholen
      
      if(!(cmd_byte & (1<<RW))){      //R/W-Bit=0, Master schreibt
        rx_cnt= 0;        //RX Zähler zurücksetzen
        P_BUSY_HIGH();        //Master kann die Daten übetragen
        while(!(PINB & (1<<P_SS)));    //Warte bis Übertragung abgeschlossen
        cmd_byte= cmd_byte & CMDBITS;
        switch(cmd_byte){
          case 0x12:{
            buffer[1] = 33;
            //tx_buf[1] = 99;
            //unsigned char i;
            //for(i=0;i<2;i++){
            //  buffer[i]= rx_buf[i];
            //}
          } break;
          
        }
      }
      if((cmd_byte & (1<<RW))){
      //else{
        cmd_byte= cmd_byte & CMDBITS;
        switch(cmd_byte){
          case 0x01:{
            unsigned char i;
            for(i=0;i<4;i++){
              tx_buf[i]= buffer[i];
            }
          } break;
        }
        
        tx_cnt= 0;      //TX Zähler zurücksetzen
        SPDR= tx_buf[tx_cnt];    //Erstes Byte in SPDR laden
        P_BUSY_HIGH();      //Master kann die Daten abholen
        while(!(PINB & (1<<P_SS)));  //Warte bis Übertragung abgeschlossen
      }
    }
    
    
    
  }
  return(0);
}

Autor: Peter Diener (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wie wird sichergestellt, dass in der ISR im Slave nicht eine zu hohe 
Pufferadresse angesprochen wird, wenn schnell hintereinander Daten 
kommen?

Außerdem weiß ich nicht was passiert, wenn man in einem array nur ein 
Element initialisiert
volatile unsigned char rx_buf[12]= {0x00};  //Schreibpufer
Mach das besser in einer Initialisierungsroutine, wenn es wichtig ist, 
dass 0 drin steht.
Außerdem würde ich den Empfangspuffer als Ringpuffer implementieren, es 
sollte aber auch so gehen.

Sonst fällt mir im Moment nichts auf, was nicht funktionieren sollte.

Viele Grüße,

Peter

Autor: Viktor (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tut ich habe einfach nicht dran gedacht. Die beiden Zähler werden in der 
main_init();
mit 0 initializiert

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.