Forum: Mikrocontroller und Digitale Elektronik SPI-Kommunikation ATTiny45 --> ATTiny45?


von The SphereX (Gast)


Lesenswert?

Hi Leute !!!

Ich möchte gern eine Funkstrecke zwischen zwei ATTiny45 mittels zweier 
nRF24L01+ Module aufbauen, welche über SPI angesprochen werden. Da ich 
allerdings mit diesem Interface noch nicht gearbeitet habe, wollte ich 
die SPI-Kommunikation zunächst einmal nur zwischen den direkt 
miteinander verbundenen µCs testen.

Dabei sendet der Master abwechselnd im Abstand von 20 Sekunden jeweils 
den Wert "1" und "2". Empfängt der Slave eine "1", schaltet er eine LED 
an, empfängt er eine "2", wieder aus. Als Sendesignal blinkt am Master 
eine LED kurz. Das Ganze sollte dementsprechend also folgendermaßen 
ablaufen:

> Master-LED blinkt --> Wert "1" wird gesendet --> Slave empfängt "1" --> LED am 
Slave leuchtet
> 20 Sekunden warten
> Master-LED blinkt --> Wert "2" wird gesendet --> Slave empfängt "2" --> LED am 
Slave aus
> 20 Sekunden warten

usw. .....

Leider tut sich am Slave nichts, d. h. die LED bleibt aus.

------------------------------------------------------------------------
' MASTER

$regfile = "attiny45.dat"
$crystal = 128000
$hwstack = 36
$swstack = 8
$framesize = 24

Dim Datatosend As Byte

Config Portb.2 = Output                     ' USCK ----> SCK (Slave)
Config Portb.1 = Output                     ' DO   ----> SDI (Slave)
Config Portb.0 = Input                      ' DI   ----> SDO (Slave)
Portb.0 = 1                                 ' Pullup
Config Portb.4 = Output                     ' Sende-LED
Portb.4 = 0

Usicr = Bits(usiwm0 , Usics1 , Usiclk , Usitc)

Do

  Datatosend = 1
  Gosub Transmission
  Wait 20
  Datatosend = 2
  Gosub Transmission
  Wait 20

Loop

End

Transmission:

Portb.4 = 1
Waitms 200
Portb.4 = 0

Usisr = Bits(usioif)             ' USIOIF löschen und USI-Zähler auf 0
Usidr = Datatosend               ' Datenregister beschreiben
While Usisr.usioif = 0 : Set Usicr.usitc : Wend

Return

------------------------------------------------------------------------
' SLAVE

$regfile = "attiny45.dat"
$crystal = 128000
$hwstack = 36
$swstack = 8
$framesize = 24

Dim Empfangsbyte As Byte

Config Portb.2 = Output                     ' USCK ----> SCK (Slave)
Config Portb.1 = Output                     ' DO   ----> SDI (Slave)
Config Portb.0 = Input                      ' DI   ----> SDO (Slave)
Portb.0 = 1                                 ' Pullup
Config Portb.4 = Output                     ' Signal-LED

Usicr = Bits(usiwm0 , Usics1 , Usiclk , Usitc)

Do

  Usisr = Bits(usioif)           ' USIOIF löschen und USI-Zähler auf 0

  ' 8 Takte warten bis Byte übertragen
  While Usisr.usioif = 0 : Set Usicr.usitc : Wend

  Empfangsbyte = Usidr      ' Empfangsbyte aus USI-Datenregister lesen

  If Empfangsbyte = 1 Then Portb.4 = 1    ' Empfangsbyte = 1 --> LED an
  If Empfangsbyte = 2 Then Portb.4 = 0    ' Empfangsbyte = 2 --> LED aus

  Waitms 100

Loop

End

------------------------------------------------------------------------

Was mache ich falsch?


Grüße,
The SphereX

von m-obi (Gast)


Lesenswert?

In Bascom mach ich selber nichts. Aber solltest du nicht Bei dem Slave 
die Ausgänge als Eingänge un die Eingänge als Ausgänge machen? Du hast 
es doch sogar als Kommentar hinten gemacht.

The SphereX schrieb:
> Config Portb.2 = Output                     ' USCK ----> SCK (Slave)
> Config Portb.1 = Output                     ' DO   ----> SDI (Slave)
> Config Portb.0 = Input                      ' DI   ----> SDO (Slave)

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


Lesenswert?

Es ist keine gute Idee, zum Kennenlernen der SPI Schnittstelle einen 
Master und einen Slave selber zu machen. Besser nimmt man einen 
funktionierden Slave und spricht den an. Denn das wird man später zu 99% 
auch tun. Dann muss man nämlich das Datenblatt des Slaves lesen und den 
Master dazu passend programmieren. Man kann sich nicht den Slave so 
hinbiegen, dass es irgendwann läuft.


Zum SPI allgemein: das sind nur 2 gekoppelte Schieberegister. Siehe 
http://www.lothar-miller.de/s9y/archives/15-SPI.html

: Bearbeitet durch Moderator
von The SphereX (Gast)


Lesenswert?

@ m-obi

" ... Aber solltest du nicht Bei dem Slave die Ausgänge als Eingänge un 
die Eingänge als Ausgänge machen? ... "

Ich habe mich an der Bascom-Hilfe zum Thema "Universal Serial Interface" 
orientiert. Dort ist die Port-Konfiguration für den Slave so vorgegeben.

http://avrhelp.mcselec.com/index.html?using_usi_universal_serial_int.htm

@ Lothar Miller

" ... Es ist keine gute Idee, zum Kennenlernen der SPI Schnittstelle 
einen Master und einen Slave selber zu machen. Besser nimmt man einen 
funktionierden Slave und spricht den an. ... "

Ich dachte eigentlich gerade, daß meine Vorgehensweise logischer ist, 
als gleich mit dem in der späteren Anwendung vorgesehenen nRF24L01+ als 
Slave zu experiementieren. Denn wenn ich schon eine "einfache" µC --> µC 
Kommunikation nicht hinbekomme, wird das für mich als Anfänger ungleich 
kompliziertere Ansprechen des Funkmoduls natürlich erst recht nicht 
funktionieren. Hier kommen nämlich noch zahlreiche weitere Fehlerquellen 
hinzu, weshalb ich zunächst mal sicherstellen wollte, daß ich SPI (USI 
bei ATTinys) verstanden habe und dieses ordentlich läuft.

Tja, und genau das tut es leider nach wie vor nicht :-( !!!

Ich habe den Slave entsprechend der Bascom-Hilfe nochmals modifiziert, 
ohne Erfolg.

----------------------------------------------------------------------
' SLAVE

$regfile = "attiny45.dat"
$crystal = 128000
$hwstack = 36
$swstack = 8
$framesize = 24

Dim Empfangsbyte As Byte
Dim Usi_data_ready As Bit

Config Portb.2 = Output               ' USCK ----> SCK (Slave)
Config Portb.1 = Output               ' DO   ----> SDI (Slave)
Config Portb.0 = Input                ' DI   ----> SDO (Slave)
Portb.0 = 1
Config Portb.4 = Output

Portb.4 = 1
Waitms 200
Portb.4 = 0

Usicr = Bits(usiwm0 , Usics1 , Usioie)

On Usi_ovf Usi_overflow_int
Enable Usi_ovf
Enable Interrupts

Do

  If Usi_data_ready = 1 Then
    Reset Usi_data_ready
    If Empfangsbyte = 1 Then Portb.4 = 1
    If Empfangsbyte = 2 Then Portb.4 = 0
  End If

Loop

End

Usi_overflow_int:

Set Usi_data_ready
Empfangsbyte = Usidr
Usisr = &B01_000000     'Reset Overflow Flag and reset 4-Bit USI counter

Return

------------------------------------------------------------------------

Dann ist auch immer die Rede von "Slave Select" als Leitung, über die 
der Master dem Slave den Beginn einer Übertragung signalisiert. Diese 
Funktion ist bei dem USI der Tinys aber gar nicht vorgesehen und kann 
laut Hilfe offensichtlich in diesem Fall auch weggelassen werden: "... 
We do not use Slave Select in this example ... ". Das verwirrt mich 
etwas. Ist es nun notwendig, den Übertragungsstart zu signalisieren, 
oder nicht?

Außerdem verstehe ich nicht so ganz, wie es sich mit der 
Clock-Einstellung verhält. Im Bascom-Beispiel wird diese für den Master 
überhaupt nicht definiert, für den Slave dann allerdings schon: " ... 
Clock Source: External, positive edge ; External, both edges ... " ?

Naja, und dann sollte nach meinem Verständnis während der Übertragung 
doch eigentlich ein Pegel am USCK-Pin (Clock) messbar sein, oder liege 
ich da falsch? Denn dort messe ich konstant 0 V.

Grüße,
The SphereX

von Mathias O. (m-obi)


Lesenswert?

Aber eine Verbindung von Ausgang zu Ausgang oder von Eingang zu Eingang 
macht doch nun wirklich keinen Sinn. Dort steht doch auch z.B. DO 
----> SDI (Slave), also sollte es doch beim Slave ein input sein, oder 
was soll dass I bedeuten in SDI? Am Besten verwendet man auch die 
Bezeichnungen MISO (Master In Slave Out) und MOSI (Master Out Slave In), 
da sieht man genau wie was sein muss. Und SCK sollte beim Slave ein 
Einagang sein, da du ja den Takt vom Master bekommst.

von The SphereX (Gast)


Lesenswert?

Da hast Du absolut recht! Logisch betrachtet macht diese Konfiguration 
keinen Sinn. Dann gehe ich mal davon aus, daß es sich bei dem 
Bascom-Beispiel um einen Schreibfehler handelt.

Allerdings habe ich es mittlerweile natürlich auch schon mit der logisch 
korrekten Beschaltung probiert. Aber auch da funktioniert die 
Datenübertragung nicht. Wenn die 0 V am USCK-Pin des Master während der 
Übertragung aber wie gesagt tatsächlich bedeuten, daß kein 
Synchronisationstakt generiert wird, kann's ja auch nicht funktionieren. 
Nur warum erzeugt der Master den Takt nicht mit:

While Usisr.usioif = 0 : Set Usicr.usitc : Wend

nach dem Befüllen des Datenregisters?


Grüße,
The SphereX

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


Lesenswert?

The SphereX schrieb:
> Ich dachte eigentlich gerade, daß meine Vorgehensweise logischer ist
Ist sie nicht. Denn wenn du beim Sender und beim Empfänger den gleichen 
Fehler ins Programm schreibst, dann kann es sein, dass die Übertragung 
gerade deshalb trotzdem klappt. Ein echter Slave verzeiht da nichts und 
du musst das richtige/passende Timing (CPOL+CPHA) verwenden...

Mach zum Test deines Masters einfach mal eine Brücke vom MOSI zum MISO. 
Dann musst du die gesendeten Daten gleich wieder empfangen.

: Bearbeitet durch Moderator
von The SphereX (Gast)


Lesenswert?

Ich hab's trotzdem erst mal mit den zwei Tinys durchgezogen ;-). Und 
nachdem ich die Port-Konfiguration nachmals geändert und auch die 
Verkabelung unidirektional ausgelegt habe

> MASTER USCK (Out) ---> SLAVE USCK (In)
> MASTER DO (MISO) ---> SLAVE DI (MOSI)

funktioniert's jetzt auch :-). Danke für Eure Hinweise!

Grüße,
The SphereX

von Mathias O. (m-obi)


Lesenswert?

Wenn dann so
> MASTER USCK (Out) ---> SLAVE USCK (In)
> MASTER DO (MOSI) ---> SLAVE DI (MOSI)
Nicht MISO, dass ist Master In Slave Out.

von The SphereX (Gast)


Angehängte Dateien:

Lesenswert?

Nee, nee, ich glaube, da liegst Du falsch ;-) !

MISO = DO
MOSI = DI


Grüße,
The SphereX

von Mathias O. (m-obi)


Lesenswert?

Findest du bei deinem den Fehler?
> MASTER DO (MISO) ---> SLAVE DI (MOSI)
  ^      ^   ^^

MISO sollte schon zu MISO und MOSI zu MOSI.

von The SphereX (Gast)


Angehängte Dateien:

Lesenswert?

Ja, ist schon klar, und vom Logischen her hast Du ja recht. Aber ich 
beziehe mich hier auf die PIN-Beschriftung laut Atmel, für mein Beispiel 
speziell die des ATTiny45. Danach ist beim "Universal Serial Interface" 
der Tinys eben:

> PB1 (MASTER) = DO (Data Out) = MISO

und

> PB0 (SLAVE) = DI (Data In) = MOSI

Folglich ist die Verbindung MASTER ---> SLAVE hier nun mal MISO ---> 
MOSI, auch wenn's logisch keinen Sinn macht.

Um Verwirrungen zu vermeiden hätte Atmel im Datenblatt vielleicht 
konsequenterweise die Begriffe MISO und MOSI komplett weglassen müssen, 
wenn man bei USI sowieso andere Bezeichnungen (DO, DI) gewählt hat.

Folgende Seite:

http://gizmosnack.blogspot.de/2013/04/tutorial-nrf24l01-and-avr.html

beschäftigt sich z. B. sehr ausführlich mit dem Thema "nRF24L01 und AVR 
µC". Auch hier wird extra noch mal hervorgehoben, daß man entgegen der 
logischen Vorgehensweise, MISO vom µC mit MOSI vom nRF24L01 Funkmodul 
verbinden muß, damit die Datenübertragung funktioniert.

" ... To get the USI to SPI up and running I found out that I had to 
connect the MOSI pin from the nRF to the MISO pin on the AVR and set it 
as output. Atmega88: PB3, ATtiny26: PB1, ATtiny85: PB1 ... "

Grüße,
The SphereX

von Peter D. (peda)


Lesenswert?

Laut
Figure 32. nRF24L01+ schematic for RF layouts with single ended 50Ω RF 
output
benötigt er 6 Steuersignale. Einem MC mit max 6 IOs zu nehmen dürfte 
daher sinnlos sein.

von The SphereX (Gast)


Lesenswert?

Von den 6 ist der IRQ allerdings optional, d. h. für die 
Datenübertragung nicht erforderlich. Da waren's nur noch 5. Aber selbst 
wenn: Wofür gibt es denn Deinen super Fastboot ;-) :-) .... Reset-Pin 
als I/O konfiguriert, und fertig is'.

Grüße,
The SphereX

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.