Dies ist eine alte Version des Dokuments!


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

Master

#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
		}
	}
}

Slave

#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;
		_delay_us(10);						// für SPI Bugfix: 10us sollte reichen, falls die Daten nicht korrekt übertragen werden, dann Wert erhöhen
		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
}