Forum: Mikrocontroller und Digitale Elektronik Code-Rätsel: SPI in Bascom und C mit Atmega8


von Samuel B. (ui999)


Lesenswert?

Hallo zusammen,

ich steuere mit meinem Atmega8 einen Trinamic TMC429 über SPI an. Alles 
funktioniert wunderbar mit meinem kleinen Bascom-Programm:
1
$regfile = "M8def.dat"
2
$crystal = 16000000
3
4
Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = High , Phase = 1 , Clockrate = 16 , Noss = 1
5
6
Config Portb.2 = Output   'SS as Output
7
8
Dim Re1 As Byte
9
Dim Re2 As Byte
10
Dim Re3 As Byte
11
Dim Re4 As Byte
12
13
Spiinit
14
15
Portb.2 = 0
16
Re1 = Spimove(126)
17
Re2 = Spimove(1)
18
Re3 = Spimove(7)
19
Re4 = Spimove(33)
20
Portb.2 = 1


Ich möchte nun das Ganze nach C übersetzen. Mein C-Code sieht so aus:
1
#include <avr/io.h>   
2
3
unsigned char spi_tranceiver (unsigned char data)
4
{
5
    SPDR = data;
6
    while(!(SPSR)&(1<<SPIF));
7
    return(SPDR);
8
}
9
10
11
int main (void)
12
{            
13
  DDRB |= (1<<DDB2)|(1<<DDB3)|(1<<DDB5);    // SS, MOSI and SCK as outputs
14
  DDRB &= ~(1<<DDB4);                     // MISO as input
15
16
  SPCR |= (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<CPOL)|(1<<CPHA);
17
18
  PORTB &= ~(1<<PB2);
19
  spi_tranceiver(126);
20
  spi_tranceiver(1);
21
  spi_tranceiver(7);
22
  spi_tranceiver(33);
23
  PORTB = (1<<PB2); 
24
}

In C scheint die SPI-Übertragung nicht zu funktionieren, da sich die 
angeschlossenen Schrittmotoren nicht rühren. Vielleicht kann mir jemand 
von euch auf die Sprünge helfen. Wo liegt der entscheidende Unterschied 
zum Bascom-Programm?

von Easylife (Gast)


Lesenswert?

PORTB = (1<<PB2);

sollte eher

PORTB |= (1<<PB2);

heissen. Daran wird es aber vermutlich nicht liegen.
Hast du ein Speicher-Oszilloskop zur Verfügung?
Dann würde ich an deiner Stelle damit mal die Kommunikation 
(SS/MOSI/SCK) beider Programme mitschneiden und vergleichen.

von Rudolph (Gast)


Lesenswert?

Samuel B. schrieb:

> spi_tranceiver(33);
>   PORTB = (1<<PB2);
> }

Bist Du sicher, dass an dieser Stelle das Programm aufhören soll?
Damit geht der Controller alle paar Dutzend µs durch den Reset.

von Rudolph (Gast)


Lesenswert?

Rudolph schrieb:
> alle paar Dutzend µs

Hmm, der SPI läuft mit 8 MHz? Dann wären das so 4µs für die vier 
Transfers, also so alle <5µs ein Reset.

von Peter II (Gast)


Lesenswert?

Rudolph schrieb:
> Bist Du sicher, dass an dieser Stelle das Programm aufhören soll?
> Damit geht der Controller alle paar Dutzend µs durch den Reset.

warum sollte er in den Reset gehen?

hinter der main baut der linker eine Endlosschleife ein, es passiert als 
nichts danach.

von Paul B. (paul_baumann)


Lesenswert?

Dann laß doch das C-Zeug sein, wenn es mit Bascom läuft.
Man muß doch kein Masochist sein.

MfG Paul

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Paul Baumann schrieb:
> Dann laß doch das C-Zeug sein, wenn es mit Bascom läuft.

.... sagte der Strauß und steckte den Kopf tief in den Sand.

;-)

von Samuel B. (ui999)


Lesenswert?

Vielen Dank Leute für die Antworten.

Ich habe gerade den Fehler selbst gefunden, eine Klammer in
1
while(!(SPSR)&(1<<SPIF));

war verrutscht. Es muss
1
while(!(SPSR&(1<<SPIF)));

lauten.

von Micael (Gast)


Lesenswert?

C is nix für Leute die mit Basic rumspielen.

von Karl H. (kbuchegg)


Lesenswert?

Micael schrieb:
> C is nix für Leute die mit Basic rumspielen.

C ist vor allen Dingen nix für Leute, die meinen man müsse alle 
Möglichkeiten ausnutzen, die einem die dichte Schreibweise von C bietet.

Mit ein paar Leerzeichen, auch wenn sie syntaktisch nicht notwendig 
sind, wird so mancher Fehler auch schon aus der Ferne sichtbar.

So geschrieben
1
   while( !(SPSR) & (1<<SPIF) )
2
     ;

wär wahrscheinlich früher aufgefallen, dass das ! den falschen Bezug 
hat.

Aber: irgendwann lernts jeder, dass Schreibweisen einen Einfluss auf die 
Fehlerhäufigkeit haben.
Genauso wie es die meisten früher oder später lernen, dass ein 'return' 
kein Funktionsaufruf ist, und daher die Klammerung des Rückgabewertes 
unnötig ist
1
   return(i);
1
   return i;
Zweiteres ist sogar trotz weniger Tippaufwand dann sogar noch einfacher 
zu lesen.
Oder schreibst du auch
1
   i = (j);
und klammerst die rechte Seite einer Zuweisung auf jeden Fall immer ein?
Nichts anderes beim return. Dei Syntax ist
1
   return Expression
und die Expression ist genau dieselbe Expression, die überall in C an 
den verschiedensten Stellen vorkommt und dort nirgends generell 
eingeklammet wird. Nur beim return ist irgendwie alles anders, wohl weil 
K&R in ihrem Buch das so vorgemacht haben.

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.