Arduino 841 ISR SPI

Gast #4042016
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.
#4042028
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.
Gast #4042032
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")
#4042033
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.
#4042067
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.
#4042071
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
#4042076
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.
Gast #4042255
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?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren