Forum: Mikrocontroller und Digitale Elektronik Atmega328 SPI SPIF wird nicht gesetzt


von Philipp H. (philipp_ho)


Lesenswert?

Hallo zusammen,

ich habe folgendes Problem: Ich möchte eine simple SPI Verbindung mit 
einem Atmega328 (Arduino UNI) testen. Zunächste einfach nur Master 
richtig initialisieren und auf Funktion testen. Byte in SPDR schreiben 
und warten bis die Flag gesetzt wird, LED an. Aber aus irgendeinem Grund 
wird die Flag nicht gesetzt. SS ist Output (anscheinend häufiger 
Fehler).
1
#include <stdint.h>
2
#include <stdlib.h>
3
#include <stdbool.h>
4
#include <avr/io.h>
5
6
#define SET_REG_BIT(a,b)  a = a | (1<<b)
7
#define DEL_REG_BIT(a,b)  a = a & ~(1<<b)
8
#define FLIP_REG_BIT(a,b)  a = a ^ (1<<b)
9
#define CHECK_REG_BIT(a,b)  (a = (a & (1<<b))>>b)
10
11
12
13
14
15
int main(void)
16
{
17
        //LED Pin -> Output
18
  SET_REG_BIT(DDRB, DDB0);
19
  //Set PB2(SS) to Output
20
  SET_REG_BIT(DDRB, DDB2);
21
  //Set PB5(SCK) to Output
22
  SET_REG_BIT(DDRB, DDB5);
23
  //Set PB3(MOSI) to Output
24
  SET_REG_BIT(DDRB, DDB3);
25
  //Enable SPI
26
  SET_REG_BIT(SPCR, SPE);
27
  //Set SPI to Master Mode
28
  SET_REG_BIT(SPCR, MSTR);
29
  //Set Clock Rate fck/16
30
  SET_REG_BIT(SPCR, SPR0);
31
32
  while(1)
33
  {
34
    //Pull SS LOW
35
    DEL_REG_BIT(PORTB, PORTB2);
36
    //Write Data to SPI Data Register
37
    SPDR = 0xFF;
38
    //Wait for SPI Flag = 1
39
    while(!(SPSR & (1<<SPIF)));
40
    //Activate LED
41
    SET_REG_BIT(PORTB, PORTB0);
42
    //Pull SS HIGH
43
    SET_REG_BIT(PORTB, PORTB2);
44
  }
45
}

von S. Landolt (Gast)


Lesenswert?

Vielleicht mag SPI es nicht, häppchenweise eingeschaltet zu werden. Ich 
würde zumindest SPE erst nach MSTR (und SPR0) setzen.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

füge bitte einmal am Ende der Initialisierung, vor while, sei() ein.

von S. Landolt (Gast)


Lesenswert?

> ... sei() ...
Es gibt doch gar keinen Interrupt!?

von jo mei (Gast)


Lesenswert?

Philipp H. schrieb:
> Aber aus irgendeinem Grund wird die Flag nicht gesetzt.

SPI Enable Fuse gesetzt?

Zeige dein Projekt damit wir die Einstellungen kennen unter
denen du das Programm laufen lassen willst.

Es heisst übrigens allgemein das Flag, oder "die Flagge",
das sagt aber keine Schwein.

von S. Landolt (Gast)


Lesenswert?

Es ist so, wie ich eingangs schrieb. Wenn MSTR erst nach SPE gesetzt 
wird, gerät SPI in den Slave-mode, SS (PB2) steht zu diesem Zeitpunkt ja 
auf low.

von S. Landolt (Gast)


Lesenswert?

> SPI Enable Fuse gesetzt?

SPIEN betrifft ausschließlich die Programmierung: "SPIEN Enable Serial 
Program and Data Downloading". Außerdem ist ein Abschalten nur mit einem 
HV-Programmiergerät möglich: "The SPIEN Fuse is not accessible in serial 
programming mode".

von Philipp H. (philipp_ho)


Lesenswert?

S. Landolt schrieb:
> Es ist so, wie ich eingangs schrieb. Wenn MSTR erst nach SPE gesetzt
> wird, gerät SPI in den Slave-mode, SS (PB2) steht zu diesem Zeitpunkt ja
> auf low.

Danke! Das war das Problem! Ist aber aus dem Datenblatt auch nicht 
unbedingt ersichtlich oder?

"If SS is configured as an output, the pin is a general output pin which 
does not affect the SPI
system. Typically, the pin will be driving the SS pin of the SPI Slave.
If SS is configured as an input, it must be held high to ensure Master 
SPI operation. If the SS pin
is driven low by peripheral circuitry when the SPI is configured as a 
Master with the SS pin
defined as an input, the SPI system interprets this as another master 
selecting the SPI as a
slave and starting to send data to it."

Klingt für mich als ob es kein Problem darstellen sollte wenn SS zuvor 
als Output gesetzt wurde. Wie dem auch sei, vielen Dank! :)

von S. Landolt (Gast)


Lesenswert?

Das Datenblattzitat bezieht sich im wesentlichen auf einen SPI-Master; 
bei der ursprünglich gewählten Reihenfolge der SPCR-bits startet SPI 
jedoch als Slave, dabei ist offenbar unerheblich, ob der SS-pin als Ein- 
oder Ausgang definiert ist. SS steht auf low, folglich geht der 
SPI-Slave direkt auf Empfang.
  (stelle ich mir zumindest so vor, ohne es näher untersucht zu haben)

von Veit D. (devil-elec)


Lesenswert?

Hallo,

habe das auch nochmal nachvollzogen. SS wurde immer als Erstes 
konfiguriert.  Alle SS/CS Pins setze ich schon aus Gewohnheit als Erstes 
auf Ausgang und High Pegel. Entscheidend ist wirklich dass das SPE Bit 
als Letztes gesetzt wird falls man alle Bits einzeln in das Register 
schreibt. Interessante Erkenntnis. Danke.

von S. Landolt (Gast)


Lesenswert?

> Entscheidend ist wirklich dass das SPE Bit als
> Letztes gesetzt wird

Das sieht hier anders aus: entscheidend ist der Zustand von SS beim 
Setzen von SPE; ich kann dieses durchaus als Erstes setzen, wenn nur SS 
zu diesem Zeitpunkt high ist.

Mit aller Zurückhaltung möchte ich behaupten, dass das beim Test nicht 
galt:

> Alle SS/CS Pins setze ich schon aus Gewohnheit als Erstes
> auf Ausgang und High Pegel.

von Oliver S. (oliverso)


Lesenswert?

Das ganze Problem wäre gar nicht aufgetreten, wenn du diese bescheuerten 
Bit-Setz-Makros nicht benutzt hättest.

Was ist denn an
1
DDRB = (1<<DDB0) | (1<<DDB2) | (1<<DDB3) | (1<<DDB5);
2
SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0);

so furchtbar kompliziert?

Oliver

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

Nun ja, mir gefallen sie auch nicht, aber ist Geschmackssache - warum 
nicht?

von Oliver S. (oliverso)


Lesenswert?

Weil man sich, wie dieser Thread hier ja zeigt, damit unnötige 
Möglichkeiten einbaut, sich selber ins Knie zu schiessen.

Oliver

von S. Landolt (Gast)


Lesenswert?

Schon - andererseits war das Hauptproblem ja unzureichende Kenntnis der 
SPI-Funktion.
  (mich persönlich stört eher die viele Schreibarbeit; und dass das 
Programm unnötig groß wird, stößt wohl nur Assemblerprogrammierern auf)

von Veit D. (devil-elec)


Lesenswert?

Hallo,

ähm ne. Ich wollte zum Ausdruck bringen, dass es nicht egal ist wann das 
SPE Bit gesetzt wird. Ich hatte wie gesagt für meinen Test den SS Pin 
gleich am Anfang auf Ausgang und High Pegel gesetzt. Danach habe ich nur 
noch mit der Reihenfolge der Bits im SPCR Register gespielt. Alle 
einzeln wie der TO. Master funktioniert nur und gibt Daten raus wenn das 
SPE Bit als Letztes gesetzt wird. Also so wie deine Vermutung war, S. 
Landolt. Testobjekt war mein ATmega2560.

Ob einzeln oder in einem Rutsch kommt auch immer darauf was man machen 
möchte. Zum Bsp. beim Timer habe ich immer 3 Grundfunktionen. 
Konfiguration des Timern. Starten und Stoppen des Timers. Wer SPI 
zwischen Master und Slave umschalten möchte, muss das auch irgendwie 
sinnvoll aufdröseln.

von Peter D. (peda)


Lesenswert?

Veit D. schrieb:
> Master funktioniert nur und gibt Daten raus wenn das
> SPE Bit als Letztes gesetzt wird.

Nein, das stimmt nicht. Man kann MSTR setzen, nachdem SPE gesetzt 
wurde.
Ich würde trotzdem immer die Bits in einem Rutsch setzen. Bei manchen 
IO-Registern haben die Bits verschiedene Bedeutung beim Lesen/Schreiben, 
d.h. ein Lesen/AND/OR/Schreiben kann zu Überraschungen führen.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

habe das nochmal durchgespielt. Man sollte das in Ruhe machen. Hatte 
mich oben etwas vertan, hatte das SS High setzen zum Test rausgenommen 
und vergessen wieder reinzunehmen. Sorry. Also nochmal.  :-)
Wenn der SS Pin Ausgang und High ist, dann spielt die Bit Reihenfolge 
keine Rolle. Wenn SS Ausgang und Low ist, dann muss SPE als Letztes 
gesetzt werden. Bedeutet der SS Pegel spielt eine entscheidende Rolle, 
wie S. Landolt schon geschrieben hatte. Da man eigentlich SS und alle 
anderen SS/CS Pins immer als Erstes konfiguriert, kommt man nicht in 
diese Verlegenheit.  :-)

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.