Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
microcontrollertechnik:spi_kommunikation [2022/06/24 08:25] tfischermicrocontrollertechnik:spi_kommunikation [2024/01/10 01:18] (aktuell) – gelöscht mexleadmin
Zeile 1: Zeile 1:
-====== SPI Kommunikation ====== 
  
-Bei der Simulide Software 1255 und jünger kommt es vor, dass am Slave die Daten nicht durch das SPI eingelesen werden können. 
- 
-Im Folgenden ist ein Bugfix beschrieben. 
- 
- 
-**ACHTUNG: Der beschriebene Bugfix erlaubt nur eine Kommunikation vom Master zum Slave. Eine Rückkommunikation ist hiermit NICHT möglich.** 
- 
-=== Master === 
- 
-Änderungen 
-  * Es sollte nur ''SPCR = ...|(1<<SPR1)|(1<<SPR0);'' oder ''SPCR = ...|(1<<SPR1);'' verwendet werde und keine schnelleren SPI-Frequenzen 
-  * Der Bugfix wurde nur mit einer zeitlichen Verzögerung von ca. $10\mu s$ zwischen dem Versenden von Nachrichten getestet. \\ Bei kürzeren Verzögerungen kann es dazu kommen, dass beim Empfänger die Daten im SPDR Register gestört ankommen. 
-      
-<sxh c; first-line: 1> 
-#ifndef F_CPU 
-#define F_CPU 12288000UL 
-#endif 
- 
-#include <avr/io.h> 
-#include <util/delay.h> 
- 
-uint8_t i=0; 
-int main() 
-{ 
- DDRC  &= 0b11111100; 
- PORTC |= 0b00000011; 
-  
- DDRB = 0b00111100; 
- SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0); // bugfix nur mit (SPR1=1, SPR0=0) oder (SPR1=1, SPR0=1)  möglich 
-  
- while(1) 
- { 
- if(!(PINC & 1<<PINC0)) 
- { 
- PORTB &= ~(1 << PORTB2); 
- SPDR = 0b10101100; 
- while(!(SPSR & (1<<SPIF))); 
- PORTB |=  1 << PORTB2; 
- _delay_us(10); // für SPI Bugfix: 10us sollte reichen, falls die Daten nicht korrekt übertragen werden, dann Wert erhöhen 
- } 
- } 
-} 
-</sxh> 
- 
-=== Slave=== 
- 
-Änderungen 
-  * Es ist zusätzlich die Unterfunktion ''SPIsoft_Init()'' hinzugekommen, welche einen Pin Change Interrupt auf die CLK und SS Leitung legt. 
-  * Ein Rückversandt der Daten vom Slave zum Master (MISO) ist nicht möglich. Entsprechend ist von einem Beschreiben von SPDR (Zeile 22) abzusehen, da diese den Bugfix stören. 
-  *  
-  * Eine Verwendung des SPI Interrupt ( ''ISR(SPI_STC_vect)'') ist NICHT möglich. 
-  * Das ''SPIF'' Bit kann genutzt werden. Vor der Verwendung der Daten muss aber eine zeitliche Verzögerung von ca. $10\mu s$ gewartet werden. \\ Bei kürzeren Verzögerungen kann es dazu kommen, dass beim Empfänger die Daten im SPDR Register gestört auswertet. 
-  * Zusätzlich wird der Interrupt $ISR(PCINT0_vect)$ zur Signalerkennung genutzt. 
- 
- 
-<sxh c; first-line: 1> 
-#ifndef F_CPU 
-#define F_CPU 12288000UL 
-#endif 
- 
-#include <avr/io.h> 
-#include <avr/interrupt.h> // Definition von Interrupts 
-#include <util/delay.h> 
- 
-void SPIsoft_Init(); 
- 
-int main() 
-{ 
- DDRB = (1<<DDB4); 
- 
- DDRD = 0xFF; 
- SPCR = (1<<SPE);  
-  
- SPIsoft_Init(); // für SPI Bugfix - Init Routine 
-  
- while(1) 
- { 
- // SPDR = 0x01; 
- while(!(SPSR & (1<<SPIF))); 
- _delay_us(10); // für SPI Bugfix: 10us sollte reichen, falls die Daten nicht korrekt übertragen werden, dann Wert erhöhen 
- PORTD = SPDR; 
- } 
-} 
- 
-void SPIsoft_Init() 
-{ 
- PCICR |= 1<<PCIE0;                  // Pin Change Interrupt, auf PortB aktivieren 
- PCMSK0|= 1<<PINB5 |     // Pin Change Interrupt, wenn CLK Pin geändert 
- 1<<PINB2;     // Pin Change Interrupt, wenn SS Pin geändert 
- sei(); 
-} 
- 
-ISR(PCINT0_vect) 
-{ 
- if( !(PINB>>PINB5) &    1 ) {return;};                  // Falls nicht steigende Flanke , dann abbrechen 
-  
- SPDR = ( SPDR << 1 ) + ((PINB>>PINB3)& 1); // Bit-Wert von PinB3 in SPDR schieben 
-} 
-</sxh>