Forum: Mikrocontroller und Digitale Elektronik Arduino 841 ISR SPI


von Herman Uh. (Gast)


Lesenswert?

1
void spi_slave_init(void)
2
{
3
  SPI_DDR = (1<<SPI_MISO);
4
  SPCR = (1<<SPE) | (1<<SPIE);  // Enable SPI | Interrupt aktivieren
5
  SPDR = 0;
6
}
7
8
ISR(SPI_STC_vect)
9
{
10
  data = spi_slave_receive();
11
}

Hallo, ich möchte einen Attiny841 als SPI Slave nutzen, der reagieren 
soll, sobald sich etwas auf dem SPI Bus tut. Jedoch finde ich im 
Datenblatt kein Register, welches für den SPI Interrupt zu nutzen ist.

"21 0x0014 SPI SPI Serial Transfer Complete" ist was anderes.

von Karl H. (kbuchegg)


Lesenswert?

Herman Uh. schrieb:

> Hallo, ich möchte einen Attiny841 als SPI Slave nutzen, der reagieren
> soll, sobald sich etwas auf dem SPI Bus tut.


Wenn du mit 'sobald sich etwas tut' meinst 'sobald der Master mit seinen 
Clock Pulsen anfängt', dann gibt es da auch nichts dazu.

Das einzige was es gibt, ist der Interrupt, so wie er in deinem 
Codeausschnitt ohnehin schon drinn ist, der feuert, wenn ein Transfer 
abgeschlossen ist.

von Herman Uh. (Gast)


Lesenswert?

Ja das Problem ist, den Interrupt "SPI_STC_vect" gibt es beim Attiny841 
scheinbar nicht.

von Arduinoquäler (Gast)


Lesenswert?

Auszug aus dem Manual Seite 158:
-----------------------------------------------
SPSR – SPI Status Register

Bit 7 – SPIF: SPI Interrupt Flag

This bit is set when a serial transfer is complete. An interrupt is 
generated if SPIE in SPCR is set and global interrupts are
enabled. If SS is an input and is driven low when the SPI is in Master 
mode, this will also set the SPIF Flag. SPIF is
cleared by hardware when executing the corresponding interrupt handling 
vector. Alternatively, the SPIF bit is cleared by
first reading the SPI Status Register with SPIF set, then accessing the 
SPI Data Register (SPDR).
-----------------------------------------------

"This bit is set when a serial transfer is complete"

gilt für Senden und Empfangen ("transfer")

von Karl H. (kbuchegg)


Lesenswert?

Normalerweise ist es bei den AVR so, dass nur weil man eine der 
Alternativfunktionen für einen Pin aktiviert, die Basisfunktionalitäten 
deswegen nicht abgeschaltet werden.

Abhängig welchen SCK Pin du benutzt, könntest du mal probieren, ob der 
ganz normale PCINT3 bzw. PCINT4 Pin Change Interrupt (natürlich 
flankengetrieben) da noch durchkommt.

von Karl H. (kbuchegg)


Lesenswert?

Herman Uh. schrieb:
> Ja das Problem ist, den Interrupt "SPI_STC_vect" gibt es beim Attiny841
> scheinbar nicht.

? Warum soll es den nicht geben

Die Bits in den Konfigurationsregistern gibt es ja auch.
Der heisst vielleicht beim Tiny841 nur ein bischen anders.

von Karl H. (kbuchegg)


Lesenswert?

Herman Uh. schrieb:

> "21 0x0014 SPI SPI Serial Transfer Complete" ist was anderes.

Nö.
Das ist schon der richtige.

von Herman Uh. (Gast)


Lesenswert?

ISR(SPI)
{
}

geht als Interrupt Vector nicht. avr/interrupt.h habe ich mit 
eingebunden.

Warning  1  'SPI' appears to be a misspelled signal handler [enabled by 
default]

von Karl H. (kbuchegg)


Lesenswert?

Sieh dir mal die Dependency Liste in deinem Projekt an.
Dort müsste ein File namens iotn841.h aufgeführt sein (Oder so ähnlich. 
Mein Studio kennt den Tiny noch nicht, drum kann ich nichts genaueres 
sagen).

Machs auf und such nach "_vect". Irgendwo da drinn ist der korrekte Name 
für den Interrupt Handler, wie er im gcc heisst.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:
> Sieh dir mal die Dependency Liste in deinem Projekt an.
> Dort müsste ein File namens iotn841.h aufgeführt sein (Oder so ähnlich.
> Mein Studio kennt den Tiny noch nicht, drum kann ich nichts genaueres
> sagen).

Kann sein, dass das Header File auch anders heisst. Sein Name fängt 
normalerweise jedenfalls mit "io" an.

Noch was:
Damit die Dependency List vollständig ist, musst du das Projekt 
mindestens einmal compiliert haben. D.h. alles was Fehler wirft: 
gnadenlos wegkommentieren. Es geht nur darum, dass der Compiler 
durchkommt. Dann stimmt auch die Dependency List

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Ach du Mist.
Du hast in deiner Überschrift ja das Stichwort 'Arduino' benutzt.
Na die IDE kann das nicht. Die ist dafür zu simpel gestrickt.

Da bleibt dir wohl nichts anderes übrig, als im Verzeichnis mit den 
Include Files zu suchen, welches für den Tiny 841 passt. Ausser jemand 
mit eine neuereren Atmel Studio als meines, erbarmt sich und sucht den 
Namen raus.

: Bearbeitet durch User
von Konrad S. (maybee)


Lesenswert?

iotn841.h ist schon korrekt.

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?

Herman Uh. schrieb:
> ISR(SPI)
> {
> }
>
> geht als Interrupt Vector nicht. avr/interrupt.h habe ich mit
> eingebunden.
>
> Warning  1  'SPI' appears to be a misspelled signal handler [enabled by
> default]

Probiers mal mit:
1
#include <avr/interrupt.h>
2
3
ISR(SPI_vect)
4
{
5
}

von Herman Uh. (Gast)


Lesenswert?

Karl Heinz schrieb:
> Ach du Mist.
> Du hast in deiner Überschrift ja das Stichwort 'Arduino' benutzt.
> Na die IDE kann das nicht. Die ist dafür zu simpel gestrickt.
Ähm, gute Frage wieso da Arduino steht, dass sollte Attiny heißen.

SPI_vect ist in den h-Files vorhanden gewesen

von Herman Uh. (Gast)


Lesenswert?

So, hab nun ein bisschen rumgetestet, es wird zumindest schon etwas 
übermittelt. Nur noch nicht ganz so wie gewollt.

Zur Verdrahtung, die beiden Geräte sind wie folgt miteinander verbunden
1
1(M)  -  2(S)
2
SCK   -   SCK
3
MOSI  -  MOSI
4
SS    -    SS


Master
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
#define SPI_DDR    DDRA
6
#define SPI_PORT  PORTA
7
#define SPI_MOSI  PORTA6
8
#define SPI_MISO  PORTA5
9
#define SPI_SS    PORTA7
10
#define SPI_SCK    PORTA4
11
12
void spi_master_init(void)
13
{
14
  SPI_DDR |= (1<<SPI_SS) | (1<<SPI_MOSI) | (1<<SPI_SCK); //MOSI und SCK als Ausgang, Rest ist Eingang
15
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);    //Aktivierung des SPI, Master, Taktrate fck/16
16
}
17
18
void spi_master_transmit(uint8_t r, uint8_t g, uint8_t b)
19
{
20
  SPI_PORT &= ~(1<<SPI_SS);
21
  SPDR = r;                //starte Transmission
22
  while(!(SPSR & (1<<SPIF)));        //warte, bis Transmission abgeschlossen ist
23
  SPDR = g;                //starte Transmission
24
  while(!(SPSR & (1<<SPIF)));        //warte, bis Transmission abgeschlossen ist
25
  SPDR = b;                //starte Transmission
26
  while(!(SPSR & (1<<SPIF)));        //warte, bis Transmission abgeschlossen ist
27
  SPI_PORT |= (1<<SPI_SS);
28
}
29
30
int main(void)
31
{
32
  spi_master_init();
33
  sei();
34
  spi_master_transmit(0,0,0);
35
36
  while(1)
37
  {
38
39
    _delay_ms(1000);
40
    spi_master_transmit(255, 0, 0); // rot
41
    _delay_ms(1000);
42
    spi_master_transmit(0, 255, 0); // gruen
43
    _delay_ms(1000);
44
    spi_master_transmit(0, 0, 255); // blau
45
  }
46
}

Slave
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
#define SPI_DDR    DDRA
6
#define SPI_PORT  PORTA
7
#define SPI_MOSI  PORTA6
8
#define SPI_MISO  PORTA5
9
#define SPI_SS    PORTA7
10
#define SPI_SCK    PORTA4
11
12
volatile uint8_t data0 = 0xff;
13
volatile uint8_t data1 = 0xff;
14
volatile uint8_t data2 = 0xff;
15
volatile uint8_t data_out = 0;
16
17
void spi_slave_init(void)
18
{
19
  SPI_DDR |= (1<<SPI_MISO);
20
  SPCR = (1<<SPE) |(1<<SPIE);
21
}
22
23
uint8_t spi_slave_receive(void)
24
{
25
  while(!(SPSR & (1<<SPIF)));
26
  return SPDR;
27
}
28
29
ISR(SPI_vect)
30
{
31
  data2 = data1;
32
  data1 = data0;
33
  data0 = 255-spi_slave_receive();
34
  
35
  VAL_RED = data0;
36
  VAL_GREEN = data1;
37
  VAL_BLUE = data2;
38
}
39
40
int main(void)
41
{
42
spi_slave_init();
43
sei();
44
  while(1)
45
  {
46
  }
47
}

Im Master möchte ich mit 3 gesendeten 0en die Register data0 - data2 
zurücksetzen. Danach sende ich im Sekundentakt die Werte für eine RGB 
Led. Es soll einzeln rot, grün und blau blinken.

Jedoch geschieht das nicht. Es kommt dauerhaft zur Farbvermischung. Habe 
ich was vergessen?

von Themaverwirrter (Gast)


Lesenswert?

Herman Uh. schrieb:
> Zur Verdrahtung, die beiden Geräte sind wie folgt miteinander
> verbunden1(M)  -  2(S)
> SCK   -   SCK
> MOSI  -  MOSI
> SS    -    SS

Auf den ersten Blick fällt auf dass MOSI an MISO muss.

von Themaverwirrter (Gast)


Lesenswert?

Themaverwirrter schrieb:
> Auf den ersten Blick fällt auf dass MOSI an MISO muss.

Kann sein dass ich da etwas verwirrt war ...

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.