Forum: Mikrocontroller und Digitale Elektronik SPI übertragungsablauf


von Kimmy (Gast)


Lesenswert?

Tag,
eine Frage zum ablauf einer Übertragung von Nachrichten über SPI.

Controller A sendet Daten nach Controller B.
Controller setzt einen Pin auf high und startet direkt danach die 
ÜBertragung. Nach der Übertragung wird der Pin wieder auf Low gesetzt.
Im Controller B wird durch dem von Controller A auf high gesetztem Pin 
ein Interrupt ausgelöst. In der ausgelösten ISR werden die Daten, 
herausgeholt.

Wie schnell sind die Daten vom Controller A da? Kann es vorkommen, dass 
Controller B die Daten abfragt obwohl die Übertragung noch gar nicht 
abgeschlossen ist? Also Controller A sendet noch und Controller B fragt 
schon ab.

Eigentlich werden die Daten doch alle zunächst automatisch in einem 
Register gespeichert, wo ich mir die nur rausziehe oder?

Aber wie kann ich sicher sein, dass die Übertragung zu ende ist?
Oder wie frage ich am besten nach den Daten ab?

Kimmy

von Falk B. (falk)


Lesenswert?

@ Kimmy (Gast)

>Controller A sendet Daten nach Controller B.
>Controller setzt einen Pin auf high und startet direkt danach die
>ÜBertragung.

Jain. Meistens sind die Chip Select Signale Low aktiv, d.h. für die 
Auswahl des SPI-Slave wuird das SIgnal auf LOW gesetzt und am Ende 
wieder auf High.

>Nach der Übertragung wird der Pin wieder auf Low gesetzt.
>Im Controller B wird durch dem von Controller A auf high gesetztem Pin
>ein Interrupt ausgelöst. In der ausgelösten ISR werden die Daten,
>herausgeholt.

Jain. Der Empfänger kann auch mehrere Bytes empfangen und dann muss er 
schon, sobal das CS-Signal aktive (=low) wird in die passende ISR 
springen.

>Wie schnell sind die Daten vom Controller A da?

So schnell, wie er sie sendet.

> Kann es vorkommen, dass
>Controller B die Daten abfragt obwohl die Übertragung noch gar nicht
>abgeschlossen ist?

Nein, denn Controller A gibt den Takt vor.

>Also Controller A sendet noch und Controller B fragt
>schon ab.

Geht nicht.

>Eigentlich werden die Daten doch alle zunächst automatisch in einem
>Register gespeichert, wo ich mir die nur rausziehe oder?

Ja. Und wenn die Übertragung von einem Byte abgeschlossen ist, wird ein 
passendes Flag in einem IO-Register gesetzt. Das muss der Empfänger 
abfragen und dann die Daten auslesen.

von Kimmy (Gast)


Lesenswert?

Ja, das mit dem Aktive Low für den SlaveSelect war mir bekannt, hatte 
ich jetzt aber vergessen. Werde ich aber so umsetzen.


Falk B. schrieb:
> Ja. Und wenn die Übertragung von einem Byte abgeschlossen ist, wird ein
> passendes Flag in einem IO-Register gesetzt. Das muss der Empfänger
> abfragen und dann die Daten auslesen.


Also Controller A setzt den Pin auf Low und fängt an zu übertragen.
Controller B springt in die ISR und wartet, bis die Übertragung beendet 
ist.

richtig?

von Sto (Gast)


Lesenswert?

Kimmy schrieb:
> Controller A sendet Daten nach Controller B.
...
> Wie schnell sind die Daten vom Controller A da? Kann es vorkommen, dass
> Controller B die Daten abfragt obwohl die Übertragung noch gar nicht
> abgeschlossen ist? Also Controller A sendet noch und Controller B fragt
> schon ab.

Am besten dürfte es sein, dass wir nicht von Controller A und B sondern 
von Master und Slave sprechen. Der Master bestimmt die Geschwindigkeit 
(er gibt die Clock vor) und dementsprechend auch wann was passiert. Nur 
der Master kann Übertragungen beginnen. Das muss man als Programmierer 
natürlich im Master richtig handeln, dass sich da nichts überschneidet. 
Der Slave muss natürlich entsprechend reagieren können, wenn der Master 
seine Anfragen sendet - das muss bei der Programmierung des Masters 
beachtet werden.

Kimmy schrieb:
> Controller B springt in die ISR und wartet, bis die Übertragung beendet
> ist.
>
> richtig?

Das kann man so pauschal nicht sagen. Meistens wird der Interrupt erst 
ausgelöst, wenn die Übertragung (für gewöhnlich 8 bit) beendet ist. Dann 
steht das Ergebnis in einem Register und kann verarbeitet werden. 
Größere Controller haben einen Puffer oder DMA, damit man nicht ständig 
mit Interrupt Requests zugeballert wird. Das wäre z.B. bei einem 30 MHz 
SPI ziemlich nervig, wenn mit ca. 3,75MHz Interrupt Requests (IRQs) 
kommen.

von Kimmy (Gast)


Lesenswert?

Sto schrieb:
> Meistens wird der Interrupt erst
> ausgelöst, wenn die Übertragung (für gewöhnlich 8 bit) beendet ist.

Dazu habe ich noch einmal eine Frage
Das Auslösen des Interrupts mache ich ja mit einem extra pin. Ich muss 
bei der Programmierung selber den Pin auf Low und dann wieder auf High 
setzen, wodurch beim Slave der Interrupt ausgelöst wird.
Soll ich diesesn wechsel dann erst nach dem senden machen?

Die Sende-Funktion sieht ja wie folgt aus
1
void spi_transmit (uint8_t data)
2
{
3
  SPDR = data;
4
  while((SPSR & (1<<SPIF))==0);
5
}

angenommen, der SlaveSelect Pin ist auf PB0

soll ich dann nach der while-schleife PB0 auf low setzen und sofort 
wieder auf high?

ich hätte jetzt vor der while schleife PB0 auf low gesetzt und danach 
wieder auf high.
Dann wäre es aber wie ich denke, dass der Slave empfängt, während der 
Master noch sendet

ISR vom Slave:
1
ISR(INT0_vect){
2
while(!(SPSR & (1<<SPIF)))
3
received_data = SPDR;
4
}

von Falk B. (falk)


Lesenswert?

@ Kimmy (Gast)

>> Meistens wird der Interrupt erst
>> ausgelöst, wenn die Übertragung (für gewöhnlich 8 bit) beendet ist.

Das kann man machen, das macht den Slave aber nochmal langsamer.

>Das Auslösen des Interrupts mache ich ja mit einem extra pin. Ich muss
>bei der Programmierung selber den Pin auf Low und dann wieder auf High
>setzen, wodurch beim Slave der Interrupt ausgelöst wird.

Ja.

>Soll ich diesesn wechsel dann erst nach dem senden machen?

Nein.

>void spi_transmit (uint8_t data)
>{
>  SPDR = data;
>  while((SPSR & (1<<SPIF))==0);
>}

Soweit OK.

>angenommen, der SlaveSelect Pin ist auf PB0

Also sind deine Controller AVRs.

>soll ich dann nach der while-schleife PB0 auf low setzen und sofort
>wieder auf high?

Nein! VOR der Übertragung setzt man CS auf LOW, DANACH wieder auf High!

>ich hätte jetzt vor der while schleife PB0 auf low gesetzt und danach
>wieder auf high.

Genau so!

>Dann wäre es aber wie ich denke, dass der Slave empfängt, während der
>Master noch sendet

Muss er doch!


>ISR vom Slave:

>ISR(INT0_vect){
>while(!(SPSR & (1<<SPIF)))
>received_data = SPDR;
>}

Genau so.

von Kimmy (Gast)


Lesenswert?

Der Slave sollte ein Attiny2313 sein. Ist es mit diesem überhaupt 
möglich Daten zu empfangen? Wenn ja, wie? Im Datenblatt stehen leider 
nur Beispiele wie man Daten Sendet.

von holger (Gast)


Lesenswert?

>Im Datenblatt stehen leider
>nur Beispiele wie man Daten Sendet.

Ach was? Ich sehe ein Kapitel

SPI Slave Operation Example

von Kimmy (Gast)


Lesenswert?

Ja, das habe ich auch, aber da ist nur die Initalisierung und das Senden

The following code demonstrates how to use the USI module as a SPI 
Slave:
1
init:
2
ldi r16,(1<<USIWM0)|(1<<USICS1)
3
out USICR,r16
4
...
5
SlaveSPITransfer:
6
out USIDR,r16
7
ldi r16,(1<<USIOIF)
8
out USISR,r16
9
SlaveSPITransfer_loop:
10
sbis USISR,USIOIF
11
rjmp SlaveSPITransfer_loop
12
in r16,USIDR
13
ret

von S. Landolt (Gast)


Lesenswert?

I'll be darned, lad' ich mir aus diesem Anlass extra das aktuelle 
Datenblatt herunter, steht noch immer "Preliminary" auf der ersten 
Seite.

von holger (Gast)


Lesenswert?

>Ja, das habe ich auch, aber da ist nur die Initalisierung und das Senden

Nein, dort steht nicht senden sondern Transfer.
Und diese Zeile

in r16,USIDR

holt die empfangenen Daten ab.

Ansonsten ist dieses USI Geraffel eher sowas wie ein
ständiges jucken im Arsch.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Kimmy schrieb:
> Frage zum ablauf einer Übertragung von Nachrichten über SPI.
Da sollte man sich vielleicht vorher mal im Klaren sein, was "SPI" 
überhaupt ist. Das sind letztlich nur 2 gekoppelte Schieberegister mit 
nachgeschalteten Latches: 
http://www.lothar-miller.de/s9y/archives/15-SPI.html

Und wenn man sich diese Ablauf bewusst gemacht hat, kann man die 
Zeitpunkte, wo diese Register am besten beschrieben werden sollten, viel 
besser vorstellen. Dann ist auch klar, dass ein Slave eigentlich immer 
"alte" Daten sendet. Und dass ein Slave nichts senden kann, wenn der 
Master nich4s sendet...

von jkidghwd (Gast)


Lesenswert?

>Das Auslösen des Interrupts mache ich ja mit einem extra pin.

Das ist falsch.
Der Slave Select löst i.A keinen Interrupt aus, sondern steuert
nur die SPI HW.

Interrupt hat ja nur einen Sinn, wenn ein Datum zum Slave übertragen 
wurde und von der SW abgeholt werden kann.

>Controller B springt in die ISR und wartet, bis die Übertragung beendet
>ist.
>
>richtig?

Nein. Da ist nix mit Warten. Slave Interrupt wenn Übertragung fertig.

von Falk B. (falk)


Lesenswert?

@ jkidghwd (Gast)

>>Das Auslösen des Interrupts mache ich ja mit einem extra pin.

>Das ist falsch.
>Der Slave Select löst i.A keinen Interrupt aus, sondern steuert
>nur die SPI HW.

Nicht zwangsläufig. Ein AVR als Slave ist eher langsam, der braucht ein 
paar Dutzend Takte, eher er im Interrupt ist (in C).

>>Controller B springt in die ISR und wartet, bis die Übertragung beendet
>>ist.
>
>>richtig?

>Nein. Da ist nix mit Warten. Slave Interrupt wenn Übertragung fertig.

Wenn er erst in die SPI-ISR springt, wenn die Übertragung beendet ist, 
dauert das relativ lange, das kann bei hohen SPI-Taktraten zu langsam 
sein.

von Frank (Gast)


Lesenswert?

Jetzt verstehe ich immer weniger.
Der Master Sendet wie folgt Daten zum Slave
1
void spi_transmit (uint8_t data)
2
{
3
  PORTB &= ~(1<<PB2);
4
  SPDR = data;
5
  while((SPSR & (1<<SPIF))==0);
6
  PORTB |= (1<<PB2);
7
}


PORTB &= ~(1<<PB2); SlaveSelect wird auf low geschaltet
  -> Slave sprint in ISR (Leitung ist mit INT0 vom Slave verbunden)

SPDR = data; Schreibe Daten ins Register und Sende diese Raus

while((SPSR & (1<<SPIF))==0); Warte bis fertig gesendet worden ist

Also bevor die Daten ins Register geschrieben worden sind und er Master 
noch nicht fertig gesendet hat, springt der Slave in die ISR und wartet, 
dass der Master fertig ist.

von S. Landolt (Gast)


Lesenswert?

> Jetzt verstehe ich immer weniger.
Ich auch - wo kommt jetzt plötzlich der Frank her?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

S. Landolt schrieb:
> wo kommt jetzt plötzlich der Frank her?
Frank und Kimmy: nur 1 Name pro Thread!
Siehe Nutzungsbedingungen
Aber da kann man schon mal durcheinanderkommen, nicht wahr?

: Bearbeitet durch Moderator
von S. Landolt (Gast)


Lesenswert?

an Kimmy/Frank:

In der INT0-ISR wird USI zurückgesetzt, um eine definierte 
Anfangsbedingung zu schaffen. Gewartet wird anschließend nicht, der 
Slave kann irgendetwas anderes machen. Wenn der Master fertig gesendet 
hat, springt der Slave in die USI_OVF-ISR und holt das eben empfangene 
Byte ab.

(Ich bin kein Spezialist in Sachen USI)

von Kimmy (Gast)


Lesenswert?

Hallo, leider funktioniert das alles noch nicht so wie gewünscht. Daher 
bitte ich noch einmal um eure Hilfe

Atmega SPI:
1
#define PORT_SPI    PORTB
2
#define DDR_SPI     DDRB
3
#define DD_MISO     DDB4
4
#define DD_MOSI     DDB3
5
#define DD_SS       DDB2
6
#define DD_SCK      DDB5
7
8
volatile unsigned char spi_data;
9
volatile unsigned char new_spi_data;
10
11
void spi_init()
12
// Initialize pins for spi communication
13
{
14
  /* Set MOSI SCK and SS output, all others input */
15
  DDR_SPI = ((1 << DD_MOSI) | (1 << DD_SCK) | (1 << DD_SS));
16
  PORT_SPI |= (1 << DD_SS);
17
  DDR_SPI &= ~(1 << DD_MISO);
18
19
  /* Enable SP */
20
  SPCR = ((1<<SPE)|               // SPI Enable
21
      (1<<SPIE)|              // SPI Interupt Enable
22
      (0<<DORD)|              // Data Order (0:MSB first / 1:LSB first)
23
      (1<<MSTR)|              // Master/Slave select
24
      (0<<SPR1)|(1<<SPR0)|    // SPI Clock Rate
25
      (0<<CPOL)|              // Clock Polarity (0:SCK low / 1:SCK hi when idle)
26
      (0<<CPHA));             // Clock Phase (0:leading / 1:trailing edge sampling)  
27
}
28
29
uint8_t spi_fast_shift (uint8_t data)
30
// Clocks only one byte to target device and returns the received one
31
{
32
  usart_transmit_string("\r\nsend data: ");
33
  PORT_SPI &= ~(1 << DD_SS);
34
  SPDR = data;
35
  while((SPSR & (1<<SPIF))==0);
36
  return SPDR;
37
  PORT_SPI |= (1 << DD_SS);
38
}

main Atmega:
1
int main(void){
2
  spi_data = 0;
3
  usart_data = 0;
4
  new_usart_data = 0;
5
  usart_init(USART_MYUBRR);
6
  usart_transmit_string("RX devices ready"); 
7
  spi_init();
8
  usart_transmit_string("\r\nSPI device ready");
9
10
  sei(); // Global Interrupts activate
11
  while (1){
12
    if(new_usart_data == 1){
13
      usart_transmit_string("\r\nnew data: ");
14
      spi_data = spi_fast_shif(0x02);
15
      usart_transmit_char(spi_data);
16
      new_usart_data = 0;
17
18
    }
19
20
  }
21
}


Wie in der Funktion spi_fast_shift zu sehen ist, setze ich vor dem 
Senden den Pin PB2 auf low, wodurch der ATtiny in die ISR springt. 
Zunächst soll dieser nur eine LED Toggeln, damit ich sehe, der Attiny in 
die ISR gesprungen ist.



Attiny SPI
1
#define PORT_SPI    PORTB
2
#define DDR_SPI     DDRB
3
#define DD_MISO     DDB4
4
#define DD_MOSI     DDB3
5
#define DD_SS       DDB2
6
#define DD_SCK      DDB5
7
8
volatile unsigned char spi_data;
9
volatile unsigned char new_spi_data;
10
11
void spi_init()
12
// Initialize pins for spi communication
13
{
14
  /* --- SLAVE --- */
15
  /* Set MISO as output, all others input */ 
16
  DDR_SPI = (1 << DD_MISO);
17
  DDR_SPI &= ~((1 << DD_MOSI) | (1 << DD_SCK) | (1 << DD_SS));
18
19
  /* Enable SP */
20
  USICR = ((0<<USISIE)|            // Start Condition Interrupt Enable
21
       (0<<USIOIE)|            // Counter Overflow Interrupt Enable
22
       (0<<USIWM1)|(1<<USIWM0)|      // Three-wire mode
23
       (1<<USICS1)|(0<<USICS0)|(0<<USICLK)|
24
       (0<<USITC));            // Toggle Clock Port Pin
25
26
  extern_interrupt_init();
27
28
}
29
30
void extern_interrupt_init(void){
31
  DDRB &= ~(1 << DDD2); // External Interrupt on INT0
32
33
  MCUCR |= (1 << ISC01); // INT0 falling edge
34
  MCUCR &= ~(1 << ISC00); // INT0 falling edge
35
36
  GIMSK |= (1 << INT0);  // enable INT0 interrupt
37
}
38
39
ISR(INT0_vect){
40
  PORTB ^= (1<<PORTB5); // Toggle PD5
41
  while(!(USIDR& (1<<USIOIF)))
42
  spi_data = USIDR;
43
  new_spi_data = 1;
44
}

Attiny main
1
int main(void){
2
  _delay_ms(200);
3
  spi_data = 0;
4
  usart_data = 0;
5
  new_usart_data = 0;
6
  usart_init(USART_MYUBRR);
7
  usart_transmit_string("USART devices ready \r\n"); 
8
  spi_init();
9
  usart_transmit_string("SPI devices ready \r\n"); 
10
  sei(); // Global Interrupts activate
11
  DDRB |= (1<<PORTD5); // PD5 -> Output
12
  PORTD &= ~(1>>PORTD5); // PD5 -> Low
13
  while (1){
14
    if(new_spi_data==1){
15
      new_spi_data = 0;
16
    }
17
18
  }
19
}

Was passiert?
der Atmega resettet sich bei der funktion spi_fast_shift. Der Attiny 
toggelt auch nicht die LED. Verbunden habe ich es wie folgt:
Atmega -> ATtiny
MISO -> MISO
MOSI -> MOSI
SCK -> SCK
PB2 -> INT0

von holger (Gast)


Lesenswert?

>der Atmega resettet sich bei der funktion spi_fast_shift.

Natürlich tut er das. Du gibst den SPI Interrupt frei, hast
aber keine Interruptroutine dafür. Bumm.

Ausserdem wird der Slave Select nie wieder high:

  return SPDR;
  PORT_SPI |= (1 << DD_SS);

Da sollte der Compiler doch wenigstens ein "unreachable code"
als Warnung ausspucken.

von S. Landolt (Gast)


Lesenswert?

>       (1<<SPIE)|              // SPI Interupt Enable
? Passt nicht zum Polling
>   while((SPSR & (1<<SPIF))==0);

von S. Landolt (Gast)


Lesenswert?

Diese Definitionen unter 'Attiny SPI' - reden wir überhaupt noch vom 
ATtiny2313?

von Bastian W. (jackfrost)


Lesenswert?

Dein
1
If(new_usart_data ==1)

wird nicht ausgeführt da du die Variable mit 0 initialisierst.

Gruß JackFrost

von S. Landolt (Gast)


Lesenswert?

>   PORTD &= ~(1>>PORTD5); // PD5 -> Low
Nanu?

von Kimmy (Gast)


Lesenswert?

holger schrieb:
> return SPDR;
>   PORT_SPI |= (1 << DD_SS);

Ja, dass war ein Denkfehler. Ich wollte erst am Ende der Funktion die 
Leitung wieder auf High setzen, habe aber nicht berücksichtigt, dass die 
Funktion beim return beendet wird.

Das mit dem Interrupt hatte ich auch falsch gedacht. Habe beides 
geändert. Jetzt stürzt der Atmega wenigstens schon einmal nicht ab.
Der Attiny scheint aber nicht in die ISR zu springen, da die LED aus 
bleibt.

von holger (Gast)


Lesenswert?

Und dann das hier:

uint8_t spi_fast_shift (uint8_t data)

      spi_data = spi_fast_shif(0x02);

Das oben gezeigte Programm ist doch nie und nimmer durch den Compiler
und Linker gekommen.

von Kimmy (Gast)


Lesenswert?

S. Landolt schrieb:
> Diese Definitionen unter 'Attiny SPI' - reden wir überhaupt noch vom
> ATtiny2313?

Ja. Der Attiny hat ja kein richtiges SPI, sondern über USI.

Bastian W. schrieb:
> If(new_usart_data ==1)
>
> wird nicht ausgeführt da du die Variable mit 0 initialisierst.

Sollte aber in der ISR auf 1 gesetzt werden, wenn eine neue Nachricht 
eintrifft

S. Landolt schrieb:
>>   PORTD &= ~(1>>PORTD5); // PD5 -> Low
> Nanu?

Da ist die LED angeschlossen.

von S. Landolt (Gast)


Lesenswert?

>   while(!(USIDR& (1<<USIOIF)))
USIOIF steht in USISR.

>Ja. Der Attiny hat ja kein richtiges SPI, sondern über USI.
Schon, aber ich lese in meinem Datenblatt eine andere Pin-Belegung.

> Da ist die LED angeschlossen.
Schon, aber Sie schieben nach rechts.


Am besten nochmal, in aller Ruhe, gründlich über die Bücher.

von Kimmy (Gast)


Lesenswert?

holger schrieb:
> Das oben gezeigte Programm ist doch nie und nimmer durch den Compiler
> und Linker gekommen.

doch

Build succeeded.
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped 
==========

von holger (Gast)


Lesenswert?

>> Das oben gezeigte Programm ist doch nie und nimmer durch den Compiler
>> und Linker gekommen.

>doch

>Build succeeded.

Merkwürdig.

      spi_data = spi_fast_shif(0x02);

Hinter dem _shif fehlt das 't'.

von Kimmy (Gast)


Lesenswert?

S. Landolt schrieb:
> Schon, aber Sie schieben nach rechts.

tatsache, ist mir gar nicht aufgefallen

S. Landolt schrieb:
> Schon, aber ich lese in meinem Datenblatt eine andere Pin-Belegung.

Wie meinst du das?

von Bastian W. (jackfrost)


Lesenswert?

Kimmy schrieb:
>
> Bastian W. schrieb:
>> If(new_usart_data ==1)
>>
>> wird nicht ausgeführt da du die Variable mit 0 initialisierst.
>
> Sollte aber in der ISR auf 1 gesetzt werden, wenn eine neue Nachricht
> eintrifft
>
>

Dann müsste die Variable global und volatil sein.

Poste bitte den ganzen Code mit allen ISR die du schon hast.

Gruß JackFrost

von Kimmy (Gast)


Lesenswert?

spi.c
1
#include "spi.h"
2
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
6
void extern_interrupt_init(void);
7
8
#define PORT_SPI    PORTB
9
#define DDR_SPI     DDRB
10
#define DD_MISO     DDB4
11
#define DD_MOSI     DDB3
12
#define DD_SS       DDB2
13
#define DD_SCK      DDB5
14
15
volatile unsigned char spi_data;
16
volatile unsigned char new_spi_data;
17
18
void spi_init()
19
// Initialize pins for spi communication
20
{
21
  /* --- SLAVE --- */
22
  /* Set MISO as output, all others input */ 
23
  DDR_SPI = (1 << DD_MISO);
24
  DDR_SPI &= ~((1 << DD_MOSI) | (1 << DD_SCK) | (1 << DD_SS));
25
26
  /* Enable SP */
27
  USICR = ((0<<USISIE)|            // Start Condition Interrupt Enable
28
       (0<<USIOIE)|            // Counter Overflow Interrupt Enable
29
       (0<<USIWM1)|(1<<USIWM0)|      // Three-wire mode
30
       (1<<USICS1)|(0<<USICS0)|(0<<USICLK)|
31
       (0<<USITC));            // Toggle Clock Port Pin
32
33
  extern_interrupt_init();
34
35
}
36
37
void extern_interrupt_init(void){
38
  DDRB &= ~(1 << DDD2); // External Interrupt on INT0
39
40
  MCUCR |= (1 << ISC01); // INT0 falling edge
41
  MCUCR &= ~(1 << ISC00); // INT0 falling edge
42
43
  GIMSK |= (1 << INT0);  // enable INT0 interrupt
44
}
45
46
ISR(INT0_vect){
47
  PORTB ^= (1<<PORTB5); // Toggle PD5
48
  while(!(USIDR& (1<<USIOIF)))
49
  spi_data = USIDR;
50
  new_spi_data = 1;
51
}

in spi.h
extern volatile unsigned char spi_data;
extern volatile unsigned char new_spi_data;

von S. Landolt (Gast)


Angehängte Dateien:

Lesenswert?

> Wie meinst du das?

> #define DD_MISO     DDB4
> #define DD_MOSI     DDB3
> #define DD_SCK      DDB5

Bei mir steht es anders.

von Kimmy (Gast)


Lesenswert?

Habe den Fehler gefunden.
Wen die LED an PD5 angeschlossen ist, sollte man auch diesen Pin 
Toggeln.

Kimmy schrieb:
> PORTB ^= (1<<PORTB5); // Toggle PD5

von Kimmy (Gast)


Lesenswert?

Ich habe noch einmal eine etwas andere Frage.
Und zwar flashe ich den ATtiny mit dem Diamex Prog S Programmer. Da 
dieser allerdings ebenfalls an der SPI schnittstelle verbunden ist, gibt 
es Probleme, wenn der ATmega gleichzeitig dran hängt. Bisher habe ich 
immer die Kabel zwischen ATtiny und Atmega entfernt, geflasht und neu 
verbunden. Gibt es da irgendwie eine Alternative?

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.