Forum: Compiler & IDEs SPI Daten aufnehmen


von Dirk (Gast)


Lesenswert?

Hallo,

ich wollte ein SPI Bus Sniffer in C programmieren. Leider komme ich
nicht zum richtigen Ergebnis und hoffe auf ein wenig Unterstuetzung.

Die Daten werden vom meinem Master AVR recht simpel ausgegeben.
Im IdleMod ist CLOCK = HIGH.

Ich trigger auf die fallende Flanke des Clocksignal's , wenn das Clock
Signal auf LOW geht lese ich den Zustand vom DATA Pin ein und trigger
auf die steigende Flanke des CLOCK Signals.
Danach shifte ich meine Daten um 1 Bit nach links (die Daten kommen
spaeter MSB). Die Schleife wird 8 mal ausgefuehrt um einen Byte
zuerhalten.

Sende ich zum Slave 0xF0 funktioniert es, wenn aber das LSB != 0 ist
geht es nicht mehr.

Ich hoffe mir kann jemand ein kleinen Denkanstoss geben.


Mfg

Dirk
---- Master Code ----

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <stdio.h>
#include <avr/delay.h>
#include <avr/pgmspace.h>
#include <stdlib.h>

#include "uart.h"
#define XTAL_CPU      4000000
#define UART_BAUD_RATE      19200    // 9600 baud *

#define SNIFFER_PORT  PORTD
#define CLK        7
#define  DATA      6
#define CLKHIGH      SNIFFER_PORT |= (1<<CLK);
#define CLKLOW      SNIFFER_PORT &= ~(1<<CLK);
#define DATAHIGH    SNIFFER_PORT |= (1<<DATA);
#define DATALOW      SNIFFER_PORT &= ~(1<<DATA);
volatile unsigned char i;
unsigned char s[30];


int main( void )
{

  DDRD = 0xFF;  // AUSGANG
  CLKHIGH
  for(i=0;i<200;i++)
  {
    _delay_ms(1);

  }


  for(;;)
  {
  for(i=0;i<4;i++)
  {
    CLKLOW
    _delay_ms(1);
    DATALOW
    _delay_ms(1);
    CLKHIGH
    _delay_ms(1);
  }
  for(i=0;i<4;i++)
  {
    CLKLOW
    _delay_ms(1);
    DATAHIGH
    _delay_ms(1);
    CLKHIGH
    _delay_ms(1);
  }
  CLKHIGH

    _delay_ms(20);
    _delay_ms(20);
    _delay_ms(20);
    _delay_ms(20);
    _delay_ms(20);

    _delay_ms(20);
    _delay_ms(20);
    _delay_ms(20);
    _delay_ms(20);
    _delay_ms(20);


    _delay_ms(20);
    _delay_ms(20);
    _delay_ms(20);
    _delay_ms(20);
    _delay_ms(20);

    _delay_ms(20);
    _delay_ms(20);
    _delay_ms(20);
    _delay_ms(20);
    _delay_ms(20);

    _delay_ms(20);
    _delay_ms(20);
    _delay_ms(20);
    _delay_ms(20);
    _delay_ms(20);


  }


}



---- Slave Coe ----
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <stdio.h>
#include <avr/delay.h>
#include <avr/pgmspace.h>
#include <stdlib.h>

#include "uart.h"
#define XTAL_CPU      7372800
#define UART_BAUD_RATE      115200    // 9600 baud *

#define SNIFFER_PIN    PIND
#define CLK        2
#define  DATA      3


volatile unsigned char spi_data;
volatile unsigned char counter;
unsigned char s[30];


int main( void )
{
  DDRD = 0x00;              // PORTD = INPUT
  PORTD = 0xFF;              // PULL UP's ON
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,XTAL_CPU) );  // UART INIT

  sei();                  // GLOBALE INT's ON
  for(;;){
  uart_puts_P("START TRIGGERING\n\r");
  _delay_ms(20);

  spi_data = 0x00;
  counter = 0x00;



  do{
  if(!(SNIFFER_PIN & (1<<CLK)))       // if clock = 0 check DATA PIN
    {
      if(!(SNIFFER_PIN & (1<<DATA)))  // if DATAPIN = LOW
      {
        spi_data <<=1;
        spi_data |= 0x00;

      }else{              // if DATAPIN = HIGH
        spi_data <<=1;
        spi_data |= 0x01;
       }
       while (!( SNIFFER_PIN & (1<<CLK) )) ; // warten bis steigende
flanke auf CLK
      counter++;
    }
  }while(counter<8);            // 8Bit (1Byte) einlesen

  uart_puts_P("Byte: ");
  itoa(spi_data , s, 2); // Key Code
  uart_puts(s);
  uart_puts_P("\n\r");
  spi_data = 0;
  counter = 0;
  _delay_ms(1);
  }
}

von Dirk (Gast)


Lesenswert?

Hi,

mein Master AVR sendet 0000 1111. Mein Slave AVR erhaelt immer 1000
0111.

von Dirk (Gast)


Lesenswert?

Hi,

vielleicht hilft es weiter:

Ich sende 0000 1111 und empfange 1000 0111.

Ich sende 0001 1000 und empfange 1100 0000.

Anscheinend shifte ich meine Daten zu oft, aber ehrlich gesagt sehe ich
den Fehler nicht.

Mfg
Dirk

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Nächstes Mal bitte den Code in den Anhang, steht doch deutlich da.

von mthomas (Gast)


Lesenswert?

Nur Vermutung: Vielleicht ein Timing-Problem, Clock Low, Daten aber
"noch nicht" richtig gesetzt (delay zw. clock low und DATA* im
Sender) aber werden dennoch schon gesampled. Testweise vielleicht im
Sender erst Datenpin setzen und dann Clock "stroben".

von Dirk (Gast)


Lesenswert?

Hi,

ich danke Dir. Es funktioniert nun ich hoffe es geht spaeter auch an
der realen Hardware.

Mfg

Dirk

von peter dannegger (Gast)


Lesenswert?

"Es funktioniert nun"

Das ist reiner Zufall !


Der Trick beim SPI ist, Du brauchst ein Strobe-Signal.

Damit wird dann dem Slave gesagt, wann ein neues Byte oder Datenpaket
beginnt und wann es zuende ist.

Manche Slaves haben auch noch zusätzlich ein Startbit, d.h sie
ignorieren alle Takte, bis ein 1-Bit kommt.
Bei diesen kann man dann den Strobe-Eingang fest auf GND legen.


Ohne Strobe oder Startbit hast Du keine Chance, beide Teilnehmer zu
synchronisieren.


Peter

von Dirk (Gast)


Lesenswert?

Hi,

ich hatte zu spaet gesehen das die eigentliche Hardware ein Chip Select
Pin aktiviert bevor die Uebertragung beginnt. Aus diesem Grund bin ich
auf den HW Spi meines Mega's umgestiegen.

Es funktioniert nun Tadellos.

Mfg
Dirk

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.