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.
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...)
"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
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.
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.
Daran hat es leider nicht gelegen. Selbst wenn ich den Master mit 1MHz laufen lasse und den Slave mit 8MHz tritt der Fehler auf.
@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
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).
"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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.