Forum: Compiler & IDEs Probleme mit SPI


von Pizzaman (Gast)


Lesenswert?

Hallo,
ich versuche Daten über SPI zwischen 2 Atmega32 zu übertragen, habe
dabei aber leider das Problem das unregelmässig ein komplettes Byte
nicht ankommt. Ob der Fehler beim Sender oder Empfänger liegt weiß ich
nicht, hier mein Code:

Master:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

#ifndef F_CPU
#define F_CPU 8000000UL
#endif

unsigned char status = 0;
volatile unsigned char count;

void spi_master_init (void);
void spi_putc (unsigned char data);

SIGNAL (SIG_SPI) {
  return;
}



void spi_puts(const char *s )
{
    while (*s)
      spi_putc(*s++);
}

void spi_master_init (void) {
  DDRB = (1<<PB0) | (1<<PB5) | (1<<PB7) | (1<<PB4);  //als Ausgang
  DDRB &= ~(1<<PB6);          //als Eingang
  PORTB = (1<<PB7) | (1<<PB0);        // SCK und PB0 high (ist mit SS am
Slave verbunden)
  SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0);
  status = SPSR;
}

void spi_putc (unsigned char data)
{
  PORTB &= ~(1<<PB0);
  SPDR = data;
  while (!(SPSR & (1<<SPIF)));
  PORTB |= (1<<PB0);
}

int main (void)
{
  spi_master_init ();
  sei ();
  spi_puts("Test abc123");
  for (;;);
  return 0;
}


Slave:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

#include "uart.h"

#ifndef F_CPU
#define F_CPU 8000000UL
#endif
#define UART_BAUD_RATE      19200

volatile unsigned char data;
unsigned char status;

SIGNAL (SIG_SPI)
{
  data = SPDR;
  uart_putc(data);
}

void spi_slave_init (void)
{
  DDRB |= (1<<PB6);
  SPCR = (1<<SPE) | (1<<SPIE);
  status = SPSR;
}

int main (void)
{
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
  uart_putc('T');
  spi_slave_init ();
  sei ();

  for (;;);
  return 0;
}

Für die UART-Ausgabe benutze ich die Routinen von Peter Fleury.
Wäre schön wenn mir jemand weiterhelfen könnte.

von Pizzaman (Gast)


Lesenswert?

Kann denn wirklich keiner helfen?
Ich finde einfach den Fehler nicht, habe schon alles mögliche versucht
(Taktänderung, Ausgabe auf LCD statt UART falls sich da was beisst...)

von Peter Dannegger (Gast)


Lesenswert?

"Kann denn wirklich keiner helfen?"

Erklär uns und vor allem Dir ganz genau, was das Programm machen soll
und wie jede einzelne Routine funktionieren soll.

Da es ja eine Kommunikation sein soll, mußt Du vor allem das Protokoll
erklären (wie synchronisieren sich die beiden, wie sind die Pakete
aufgebaut, welche Fehler werden wie abgefangen usw.).

Am besten, mache einen Ablaufplan (für jede CPU einen).

Hinweise auf irgendwelche XY-Routinen sind ganz schlecht.
Der Code muß vollständig sein, damit ein anderer was damit anfangen
kann.
Du mußt alles bereitstellen, damit der Code mit 0 Fehlern und 0
Warnungen compiliert wird.
Keiner hat Lust erstmal die Compilereinstellungen zu erraten und nach
ominösen Includes zu surfen.

Je mehr Zeit Du Dir nimmst, um Dein Problem darzulegen ...


Und schreibe getrennte Programme in getrennte Files und dann alles als
Anhang gezippt


Peter

von Pizzaman (Gast)


Angehängte Dateien:

Lesenswert?

Ok,
im Anhang jetzt der komplette Quellcode mit makefiles.

Das Programm soll ein Zeichen (oder eine Zeichenfolge) über SPI von
einem Master zu einem Slave übertragen.

Ich habe mich dabei so gut es ging an das Datenblatt gehalten.

Da es sich um den im ATmega32 integrierten SPI handelt muss ich mich,
soweit ich weiß ja nicht um die synchronisierung der beiden CPUs
kümmern, dafür ist die SCK zuständig (beide CPUs laufen mit der
gleichen Taktfrequenz).

Ich verstehe nicht ganz was an der UART-Library von Peter Fleury ominös
sein soll, ich dachte die wäre hier so eine Art "Quasi-Standart". Gibt
es damit irgendwelche Probleme?


Das Problem das nun beim ausführen der Programme auftritt ist
folgendes:

der Master sendet seine Zeichenfolge, in diesem Fall "Test abc123"
der Slave empfängt ihn und gibt ihn über UART an ein Terminal-Programm
aus.

Statt der vollständigen Zeichenfolge wird im Terminalprogramm aber nur
"Test ab13" "est abc13" usw gezeigt. In seltenen Fällen werden auch
alle Zeichen angezeigt, ein Muster bei den fehlenden Zeichen konnte ich
nicht erkennen.

Zu Testzwecken hatte ich auch schon die Ausgaben statt über UART auf
ein LCD gegeben mit dem selben Effekt.
Ich vermute also dass der Fehler bei der SPI-Übertragung auftritt.

von Alex (Gast)


Lesenswert?

Drossel die Geschwindigkeit einfach mal drastisch. Dein Slave schafft es
 wahrscheinlich einfach nicht, die Daten so schnell abzuholen wie neue
kommen. Dadurch werden manche Zeichen einfach überschrieben.

von Pizzaman (Gast)


Lesenswert?

Daran hat es leider nicht gelegen.
Selbst wenn ich den Master mit 1MHz laufen lasse und den Slave mit 8MHz
tritt der Fehler auf.

von Peter Dannegger (Gast)


Lesenswert?

@Pizzaman,

"Ich verstehe nicht ganz was an der UART-Library von Peter Fleury
ominös
sein soll, ich dachte die wäre hier so eine Art "Quasi-Standart".
Gibt
es damit irgendwelche Probleme?"


Nun, da sie nicht Bestandteil des AVR-GCC, ist sie kein Standard.
Und daß sie einige benutzen, heißt doch nicht, daß sie alle kennen
müssen.
Und es kann ja auch unterschiedliche Versionen bzw. unterschiedliche
Einstellungen (Puffergröße usw.) geben.

Daher sind Angaben wie "XY-Programm" immer nebulös und nicht
nachzuvollziehen.


Als erstes soltest Du den SPI-Handler im Master raushauen. Eins geht
nur, entweder Interrupt oder Polling, aber nicht beides.


Dann solltest Du doch eine Synchronistation einfügen, z.B. der Slave
macht einen 1-0-1 Puls auf einem Pin, um dem Master zu sagen, daß er
nun empfangsbereit ist.

Dann würde ich testen, obs was mit der UART-Lib zu tun hat (die ist ja
sehr umfangreich), also erstmal alle Zeichen in einen Puffer und dann
erst im Main auf die UART ausgeben.


Peter

von Rahul (Gast)


Lesenswert?

Ich würde nie aus einer InterruptServiceRoutine eine andere Funktion
aufrufen.
Schieb die Daten lieber in einen Puffer und lass das Hauptprogramm dann
das Versenden per UART erledigen.

Die ISR des Masters kann man sich wohl auch schenken (das SPIE-Bit gar
nicht erst setzen).

von Peter Dannegger (Gast)


Lesenswert?

"Dann solltest Du doch eine Synchronistation einfügen, z.B. der Slave
macht einen 1-0-1 Puls auf einem Pin, um dem Master zu sagen, daß er
nun empfangsbereit ist."


Erstmal vor dem ganzen Paket und wenn das nichts hilft, vor jedem
Byte.


Peter

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.