SPI am ATMEGA644 - Master gibt nix aus

Gast #3035813
Lesenswert?

Hi Community

Ich wollte hier mal anfragen, ob mir evtl. jemand weiterhelfen kann..
Folgendes: Ich möchte gerne Daten per SPI über MOSI und SCK ausgeben an 
einem ATMEGA644.

Ich habe dazu im Datenblatt den Beispielcode gefunden, aber irgendwie 
tut sich da nichts.

Hier mein Programm:
1
/**************** INCLUDES ***************************************/
2
#include <avr/io.h>          //I/O library
3
#include "lcd-routines.h"    //LCD-Routine
4
#include <avr/interrupt.h>   //interrupt library
5
#include <stdint.h>          //Datentypen
6
#include <util/delay.h>      //delay library
7
/****************************************************************/
8

9
/**************** DEFINES ***************************************/
10
#ifndef F_CPU
11
#define F_CPU 20000000  //Frequenz -> 20MHZ
12
#endif 
13
/****************************************************************/
14

15
#define BLANK 0x10
16
#define VPRG  0x01
17
#define XLAT  0x08
18
#define GSCLK 0x40
19

20
#define MOSI  0x20
21
#define SCK   0x80
22
#define SPI  PORTB
23

24
#define DRIVER PORTB
25
#define TEST   PORTB
26
#define ON     0x01
27
#define OFF    0x00
28

29

30
int main(void)
31
{
32
    
33
  lcd_init();
34
  SPI_MasterInit();
35
  
36
  DDRC = 0xFF;
37
  DDRD = 0xFF;
38
  PORTC = 0x00;
39
  
40
  lcd_clear();
41
    lcd_setcursor(0,1);
42
  lcd_data(' '); 
43
  lcd_setcursor(3,1);
44
  lcd_string("Debug-Display");
45
  
46
  DRIVER = (1 << XLAT) | (1 << BLANK) | (1 << VPRG) | (1 << GSCLK);
47

48
  
49
  for(;;)
50
    {
51

52
    SPI_MasterTransmit(12);
53
  _delay_ms(19);
54
  
55
    }
56
}
57

58

59
void SPI_MasterInit(void)
60
{
61
   /* Set MOSI and SCK output, all others input */
62
   SPI = (1<<MOSI)|(1<<SCK);
63
   /* Enable SPI, Master, set clock rate fck/16 */
64
   SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
65
}
66

67
void SPI_MasterTransmit(char cData)
68
{
69
   /* Start transmission */
70
   SPDR = cData;
71
   /* Wait for transmission complete */
72
   while(!(SPSR & (1<<SPIF)));
73
}

Mit einem DSO kann ich leider nicht mal ein ruckeln am MOSI oder am SCK 
Pin feststellen, der Controller funktioniert aber sonst (Display 
angeängt als Test).

Kann mir evtl. jemand einen Tipp geben, woran das liegen könnte?

Gruss und Danke fürs lesen :)
Gast #3035826
Lesenswert?

Karl Heinz Buchegger schrieb:
> Du musst den SS Pin auf Ausgang programmieren.

Wow, danke für die schnelle Antwort :)
1
void SPI_MasterInit(void)
2
{
3
   /* Set MOSI and SCK and SS output, all others input */
4
   SPI = (1<<MOSI)|(1<<SCK)|(1<<SS);
5
   /* Enable SPI, Master, set clock rate fck/16 */
6
   SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
7
  
8
}

Tut sich leider immer noch nix :(

SPI = DDRB und MOSI, SCK und SS sind die richtigen Pins (PB4, PB5 und 
PB7)

Fehlt sonst noch was?
#3035838
Lesenswert?

SPIAnfänger schrieb:
> Karl Heinz Buchegger schrieb:
>> Du musst den SS Pin auf Ausgang programmieren.
>
> Wow, danke für die schnelle Antwort :)
>

>    /* Set MOSI and SCK and SS output, all others input */
>    SPI = (1<<MOSI)|(1<<SCK)|(1<<SS);

#define SPI  PORTB

Damit setzt du die Pins auf 1, wenn sie auf Ausgang wären.
Aber wo ist deine Programmierung des DDRB, um den Pin überhaupt mal auf 
Ausgang zu setzen!
#3035842
Lesenswert?

Karl Heinz Buchegger schrieb:
> SPIAnfänger schrieb:
>> Karl Heinz Buchegger schrieb:
>>> Du musst den SS Pin auf Ausgang programmieren.
>>
>> Wow, danke für die schnelle Antwort :)
>>
>
>>    /* Set MOSI and SCK and SS output, all others input */
>>    SPI = (1<<MOSI)|(1<<SCK)|(1<<SS);
>
> #define SPI  PORTB
>
> Damit setzt du die Pins auf 1, wenn sie auf Ausgang wären.
> Aber wo ist deine Programmierung des DDRB, um den Pin überhaupt mal auf
> Ausgang zu setzen!

Kann es sein, dass du dich da vertan hast und du eigentlich

#define SPI   DDRB

haben wolltest?
Gast #3035851
Lesenswert?

Karl Heinz Buchegger schrieb:
> #define SPI   DDRB
>
> haben wolltest?

Ja, das habe ich in der Tat, habe das gerade gemerkt, als du geschrieben 
hast, dass ich SS als Ausgang setzen muss.

Ist also bereits bereinigt.

Hier nochmal der ganze Code, damit es keine Missverständnisse mehr gibt:
1
/**************** INCLUDES ***************************************/
2
#include <avr/io.h>          //I/O library
3
#include "lcd-routines.h"    //LCD-Routine
4
#include <avr/interrupt.h>   //interrupt library
5
#include <stdint.h>          //Datentypen
6
#include <util/delay.h>      //delay library
7
/****************************************************************/
8

9
/**************** DEFINES ***************************************/
10
#ifndef F_CPU
11
#define F_CPU 20000000  //Frequenz -> 20MHZ
12
#endif 
13
/****************************************************************/
14

15
#define BLANK 0x10
16
#define VPRG  0x01
17
#define XLAT  0x08
18
#define GSCLK 0x40
19

20
#define MOSI  0x20
21
#define SCK   0x80
22
#define SPI   DDRB
23
#define SS    0x10
24

25
#define DRIVER PORTB
26
#define TEST   PORTB
27
#define ON     0x01
28
#define OFF    0x00
29

30
int main(void)
31
{
32
    
33
  lcd_init();
34
  SPI_MasterInit();
35
  
36
  DDRC = 0xFF;
37
  DDRD = 0xFF;
38
  PORTC = 0x00;
39
  
40
  lcd_clear();
41
    lcd_setcursor(0,1);
42
  lcd_data(' '); 
43
  lcd_setcursor(3,1);
44
  lcd_string("Debug-Display");
45
  
46
  DRIVER = (1 << XLAT) | (1 << BLANK) | (1 << VPRG) | (1 << GSCLK);
47

48
  
49
  for(;;)
50
    {
51

52
    SPI_MasterTransmit(12);
53
  _delay_ms(20);
54
  
55
    }
56
}
57

58

59
void SPI_MasterInit(void)
60
{
61
   /* Set MOSI, SCK and SS output, all others input */
62
   SPI = (1<<MOSI)|(1<<SCK)|(1<<SS);
63
   /* Enable SPI, Master, set clock rate fck/16 */
64
   SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0); 
65
}
66

67
void SPI_MasterTransmit(char cData)
68
{
69
   /* Start transmission */
70
   SPDR = cData;
71
   /* Wait for transmission complete */
72
   while(!(SPSR & (1<<SPIF)));
73
}
Gast #3035867
Lesenswert?

Spess53 schrieb:
> Was meinst du, was bei 8 Bit herauskommt, wenn man eine 1 32 oder 128
> mal nach links schiebt?

Oh, peinlich :S

DDRB = 0xB0 hat Abhilfe gebracht.
Die korrekte Schreibweise lese ich noch im Tut. auf der Seite nach, bin 
da immer ein wenig zerstreut.

Danke für eure Hilfe!
Gast #3036026
Lesenswert?

Wäre es möglich, dass die SCK Rate beim ATMEGA644 entgegen dem 
Datenblatt NICHT die fosc/2 schafft?

Bei:

SPCR = (1<<SPE)|(1<<MSTR);

Habe ich (wie im Datenblatt beschrieben -> siehe Anhang) einen Vorteiler 
von 4. Will ich nun aber

SPCR = (1<<SPE)|(1<<MSTR)| (1 << SPI2X);

Habe ich einen Vorteiler von 16?

Wo liegt mein Denkfehler?
Angehängte Dateien:
Gast #3036064
Lesenswert?

Ach so.. das konnte ich jetzt irgendwie nicht rauslesen.
Habe mich allerdings schon gewundert, warum nur die Bits SPR1 und SPR0 
in der Beschreibung erwähnt werden.

Ein bisschen undurchsichtig, finde ich.

Danke nochmals für eure Hilfe, jetzt läuft alles wie ich wollte!
8 Bit in 800ns, perfekt.
#3036092
Lesenswert?

SPIAnfänger schrieb:
> Ach so.. das konnte ich jetzt irgendwie nicht rauslesen.
> Habe mich allerdings schon gewundert, warum nur die Bits SPR1 und SPR0
> in der Beschreibung erwähnt werden.
>
> Ein bisschen undurchsichtig, finde ich.

Du darfst in dieser Beziehung NIE nach den Tabellen gehen. Egal ob SPI 
oder Timer oder ADC oder UART oder ...


Die Tabellen sind immer nur die logische Zusammenfassung von 
Configurationsbits. Aber das bedeutet nicht, dass sie auch im selben 
Register beheimatet sind.
Aus den Tabellen entnimmst du nur die Information, welche Bits du 
brauchst und dann gehst du alle Register durch, bis du dasjenige hast, 
in welchem das Bit beheimatet ist. Wenn du es in einem Register nicht 
findest, dann ist es eben in einem anderen. Aber so viele 
Konfigurationsregister gibt es ja bei einer Komponente nicht. Und die 
sind im Datenblatt dann ja auch beim Modul alle aufgeführt.


> Die korrekte Schreibweise lese ich noch im Tut.

Das schreibt sich eigentlich ganz einfach

#define MOSI  PB5
#define SCK   PB7
#define SS    PB4

also einfach die Pinnummern aus dem Datenblatt. Dann passt es auch mit

   SPI = (1<<MOSI)|(1<<SCK)|(1<<SS);
Gast #3036103
Lesenswert?

Karl Heinz Buchegger schrieb:
> Das schreibt sich eigentlich ganz einfach
>
> #define MOSI  PB5
> #define SCK   PB7
> #define SS    PB4

Ah, klasse, danke für den Tipp!
Meiner Schreibweise nach hätte es dann wohl so aussehen müssen?

SPI = MOSI + SCK + SS;

Spricht etwas gegen diese Schreibweise?

Karl Heinz Buchegger schrieb:
> Die Tabellen sind immer nur die logische Zusammenfassung von
> Configurationsbits. Aber das bedeutet nicht, dass sie auch im selben
> Register beheimatet sind.

Das wusste ich wirklich nicht. Habe ich bis jetzt noch nie so erlebt 
(bei Timer & ADC, UART habe ich noch nicht ausprobiert).

Werde mir das aber merken, gibts wieder eine Frage weniger im Forum :)
#3036119
Lesenswert?

SPIAnfänger schrieb:
> Karl Heinz Buchegger schrieb:
>> Das schreibt sich eigentlich ganz einfach
>>
>> #define MOSI  PB5
>> #define SCK   PB7
>> #define SS    PB4
>
> Ah, klasse, danke für den Tipp!
> Meiner Schreibweise nach hätte es dann wohl so aussehen müssen?
>
> SPI = MOSI + SCK + SS;
>
> Spricht etwas gegen diese Schreibweise?

Im Prinzip nicht.
Es scheint so, als ob das die auf einem MSP gebräuchlichere Schreibweise 
ist, während die andere die eher auf AVR gebräuchlichere Schreibweise 
ist.

Wo du jetzt genau den Teil 1<< hinschiebst bleibt sich ja egal
1
#define XYZ   PB5
2
   Register |= ( 1 << XYZ )

und
1
#define XYZ  (1<<PB5)
2
   Register |= XYZ

laufen ja aufs gleiche hinaus.

Nur eines würde ich nicht tun

#define XYZ   0x20

denn: warum willst du dir selber ausrechnen, welches Bitmuster du 
brauchst um den Pin 5 auf 1 zu setzen. Lass das doch den Compiler 
machen. Der macht dabei keine Fehler :-)
Gast #3036127
Lesenswert?

Karl Heinz Buchegger schrieb:
> Im Prinzip nicht.
> Es scheint so, als ob das die auf einem MSP gebräuchlichere Schreibweise
> ist, während die andere die eher auf AVR gebräuchlichere Schreibweise
> ist.

Naja, gebräuchlich ist, was einem am leichtesten fällt, oder :)?

Karl Heinz Buchegger schrieb:
> Nur eines würde ich nicht tun
>
> #define XYZ   0x20
>
> denn: warum willst du dir selber ausrechnen, welches Bitmuster du
> brauchst um den Pin 5 auf 1 zu setzen. Lass das doch den Compiler
> machen. Der macht dabei keine Fehler :-)

Ja, da hast du natürlich recht. Bin mich irgendwie gewöhnt immer mit 
Ausmaskierungen zu arbeiten, weiss gar nicht recht woher das kommt.

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