Forum: Mikrocontroller und Digitale Elektronik SPI Atmega16M1


von AVRe (Gast)


Lesenswert?

Hallo,

ich habe Problem mit SPI. Es hat vor ein paar Tagen noch funktioniert, 
nun geht aber nichts mehr. Wenn ich 8Bit senden will, wird nichts 
gesendet (Mit LogicAna und Oszi getestet) und der MCU bleibt in der 
while schleife.

Hier der Code:
1
void SPI_INIT(void) {
2
  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0);      // SPI ENABLE, Master
3
  DDRB = (1 << DDB1) | (1 << DDB2) | (1 << DDB7);     // CLK, MOSI und MISO als Ausgang
4
}
5
6
7
8
uint8_t SPI_Transfer(uint8_t sByte)
9
{
10
   SPDR = sByte;
11
   while(!(SPSR & (1<<SPIF)));
12
   return SPDR;
13
}


Zuerst habe ich versucht es wieder mit gesamtem Code zum laufen zu 
bekommen. Dann hab ich alles außer der SPI_INIT() und einem aufruf in 
der while(1) von SPI_Transfer(0x01); versucht. (Aktueller Stand)

1
#include ....
2
3
4
int main(void) {
5
6
SPI_INIT();
7
8
while(1) {
9
  PORTC &= ~(1 << PC5);
10
  SPI_Transfer(0b00000101);
11
  PORTC |=  1 << PC5;
12
}
13
  return(0);
14
}

Erkennt jemand einen Fehler in der SPI_INIT? die Transfer Funktion 
sollte so auf jeden fall in Ordnung sein... (ist kopiert)

Kann es sein, dass beim compilieren irgendwas weg optimiert wird? 
Aktuell nutze ich als Parameter -Os (gcc version 5.3.0 (GCC)) unter Arch 
Linux und als IDE CodeBlocks die aktuelle Version.

Hab das ganze auch auf einem andern Atmega64M1 laufen lassen, selbe 
Ergebnis.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

AVRe schrieb:
> PORTC &= ~(1 << PC5);

 Als Ausgang gesetzt ?
 DDRC |= (1<<PC5);

 Normal ist doch PortB.4, also:
 DDRB |= (1<<PB4);
 und dann:
 PORTB &= ~(1 << PB4);

 Auch:
1
   DDRB = (1 << DDB1) | (1 << DDB2) | (1 << DDB7);     // CLK, MOSI und MISO als Ausgang

Sollte sein:
1
   DDRB = (1<<DDB4) | (1 << DDB5) | (1 << DDB7);     // SS, CLK, MOSI als Ausgang

von Rudolph (Gast)


Lesenswert?

Marc V. schrieb:
>> PORTC &= ~(1 << PC5);
>
>  Als Ausgang gesetzt ?
>  DDRC |= (1<<PC5);
>
>  Normal ist doch PortB.4, also:
>  DDRB |= (1<<PB4);
>  und dann:
>  PORTB &= ~(1 << PB4);

Normal vielleicht nicht in dem Sinne, dass man den SS Pin auch wirklich 
als Chip-Select benutzen muss.
Aber der sollte schon tunlichst auf Ausgang stehen, egal welchen Pin man 
für das Chip-Select benutzt.

MISO und SCK werden sowieso automatisch konfiguriert wenn man den SPI 
als Master benutzt.
MOSI kann man als Ausgang setzen, muss man aber nicht.

von AVRe (Gast)


Lesenswert?

Marc V. schrieb:
> Auch:   DDRB = (1 << DDB1) | (1 << DDB2) | (1 << DDB7);     // CLK,
> MOSI und MISO als Ausgang
>
> Sollte sein:   DDRB = (1<<DDB4) | (1 << DDB5) | (1 << DDB7);     // SS,
> CLK, MOSI als Ausgang

Ich glaube du bist beim falschen MCU. Es geht um den M1 und nicht den 
ohne :)


Ich habe nun:
1
                // SCK          MOSI        MISO
2
  DDRB = (1 << DDB7) | (1 << DDB1) | (1 << PB0);
3
  DDRD = (1 << DDD3); // SS

Funktioniert aber weiterhin nicht...

von Rudolph R. (rudolph)


Lesenswert?

Wenn PC5 als Chip-Select verwendet werden soll fehlt da auch noch:
DDRC |= (1 << PC5);

Boah, und beim drüber schauen über die Pins fällt mir wieder mal die 
unsägliche Belegung von dem Mega16M1 auf.
Ich mag das Ding ja als kleinen Controller für CAN und/oder LIN und da 
stecken auch unheimlich viele Neuerungen in dem kleinen Gehäuse.

Aber das Pinout? Ich frage mich echt, warum der Kunde der die Dinger 
haben wollte denen das nicht um die Ohren gehauen hat.

von S. Landolt (Gast)


Lesenswert?

Warum soll MISO auf Ausgang gesetzt werden?
Auch dachte ich, dass SS auf D3 liegt.

von holger (Gast)


Lesenswert?

>void SPI_INIT(void) {
>  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0);      // SPI ENABLE, Master
>  DDRB = (1 << DDB1) | (1 << DDB2) | (1 << DDB7);     // CLK, MOSI und >MISO als 
Ausgang
>}

Vertausche die beiden Zeilen mal:
1
void SPI_INIT(void) {
2
  DDRB = (1 << DDB1) | (1 << DDB2) | (1 << DDB7);     // CLK, MOSI und MISO als Ausgang
3
  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0);      // SPI ENABLE, Master
4
}

von holger (Gast)


Lesenswert?

>Vertausche die beiden Zeilen mal:

Ne, bringt so nix;) Was ich meine ist setze SS auf Ausgang
bevor das SPI Modul enabled wird.

von AVRe (Gast)


Lesenswert?

Du meinst so:
1
void SPI_INIT(void) {
2
3
  DDRD = (1 << DDD3); // SS
4
5
                // SCK          MOSI        MISO
6
  DDRB = (1 << DDB7) | (1 << DDB1) | (1 << PB0);
7
8
SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0);      // SPI ENABLE, Master
9
}

Funktioniert leider weiterhin nicht...

von holger (Gast)


Lesenswert?

>Funktioniert leider weiterhin nicht...

Dann schaltet irgendwas den SS Pin irgendwo im Programm
wieder auf Eingang oder du flasht die ganze Zeit schon eine
falsche HEX Datei.

von Frcikelfritze (Gast)


Lesenswert?

AVRe schrieb:
> Funktioniert leider weiterhin nicht...

SPI Enable (SPIEN) Fuse korrekt gesetzt?

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.