mikrocontroller.net

Forum: Compiler & IDEs Probleme mit SPI


Autor: Pizzaman (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Pizzaman (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...)

Autor: Peter Dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Pizzaman (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Pizzaman (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: Peter Dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

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.