Forum: Mikrocontroller und Digitale Elektronik Atmega8 und ISP Kommunikation


von Lukas B. (lukasb)


Lesenswert?

Hallo Leute!

Bin neu hier und auch in sachen Mikroprozessoren.

Nachdem ich jetzt ein paar Tage mit dem uC rumexperimentiert habe, habe 
ich mir eine (vermeindlich !!) einfache Aufgabe gestellt.

Da ich viele Bauteile die ich in Zukunft verwenden will ISP unterstüzen 
wollte ich zum EInstieg 2 uP miteinander "kommunizieren" lassen, soll 
heißen:
Master schickt ein Byte an Slave, fertig!

Gesagt, getan schaltung sieht wie folgt aus:

2 Atmega8 mit 4,5 V Spannung (3x1,5V Batterie) und 8Mhz Quartz (also 2 
mal) dran.

am Master PD2 auf 4,5V (Master / Slace select, siehe unten)

SCK <--> SCK
MISO <--> MOSI
MOSI <--> MISO

und am Slave
SS <--> GND

Da ich nicht immer 2 Programme flashen will, habe ich master und slave 
betrieb über einen Input pin (PD2) gewählt.


an PD0 und PD1 hängen bei beiden uC jeweils eine LED zum debuggen.

Hier mein Programm:
(in gdi_test.h ist nur F_CPU definiert (8000000))
1
#include <avr/io.h>
2
#include "gdi_test.h"
3
#include <util/delay.h>
4
5
6
7
int Master(void){
8
  PORTD |= (1 << PD0); //PD0 -> Einschalten
9
10
11
  /* Set MOSI and SCK output, all others input */
12
  DDRB = (1<<PB3)|(1<<PB5);
13
  /* Enable SPI, Master, set clock rate fck/16 */
14
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
15
16
    int x;
17
  x =0;
18
  while (1){
19
    /* Start transmission */
20
    SPDR = 1;
21
    /* Wait for transmission complete */
22
    while(!(SPSR & (1<<SPIF)))
23
    ;
24
25
26
    if (x == 1){
27
      x = 0;
28
      PORTD |= (1 << PD1); //PD0 -> Einschalten
29
    }
30
    else{
31
      x = 1;
32
      PORTD &= ~(1 << PD1); //PD0 -> Ausschalten
33
    }
34
35
    _delay_ms(1000);
36
37
  }
38
39
  return 0;
40
}
41
42
43
int Slave(void){
44
  PORTD &= ~(1 << PD0); //PD0 -> Ausschalten
45
46
  /* Set MISO output, all others input */
47
  DDRB = (1 << PB4);
48
49
  /* Enable SPI */
50
  SPCR = (1<<SPE);
51
52
53
  int x;
54
  x = 1;
55
  while (1){
56
57
    if (x == 1){
58
      x = 0;
59
      PORTD |= (1 << PD0); //PD0 -> Einschalten
60
    }
61
    else{
62
      x = 1;
63
      PORTD &= ~(1 << PD0); //PD0 -> Ausschalten
64
    }
65
66
67
68
    while(!(SPSR & (1<<SPIF)))
69
    ;
70
71
    int test;
72
    test = SPDR;
73
74
    if ( test == 1){
75
      PORTD |= (1 << PD1); //PD1 -> Einschalten
76
    }
77
    else
78
    {
79
      PORTD &= ~(1 << PD1); //PD1 -> Ausschalten
80
    }
81
82
83
84
85
86
  }
87
  
88
89
90
91
92
93
  return 0;
94
}
95
96
97
98
99
100
int main (void){
101
102
  DDRD |= (1 << PD0); // -> Ausgang
103
  DDRD |= (1 << PD1); // -> Ausgang
104
  DDRD &= ~(1 << PD2); // -> Eingang
105
106
  
107
  PORTD &= ~(1 << PD0); // -> Ausschalten
108
  PORTD &= ~(1 << PD1); // -> Ausschalten
109
110
  
111
  if (PIND & (1 << PD2)){
112
    //port PD2 ist geschaltet -> master
113
    Master();
114
  }
115
  else
116
  {
117
    Slave();
118
  }
119
120
}



So und jetzt mein Problem:
Problem 1:
Der Master "hängt" nach dem 3 Zyklus der übertragung. (PD0 Alias LED1) 
hört auf zu blinken.

Problem 2:
Der Client empfängt nur manchmal (sehr sporadisch) irgendwelche Daten 
und wenn er etwas empfängt, dann nicht das richtige. (in diesem Fall 
keine "1", habs aber auch schon mit anderen zahlen probiert)

Leider habe ich (noch) kein Oszi. hier, kann also nicht sagen was jetzt 
tatsächlich beim Master an MISO rauskommt.


Vermutlich ist es ein Anfängerfehler. Habe schon das Forum durchsucht 
nur leider scheint keiner ein ähnliches problem zu haben...

Was mach ich falsch.

Liebe Grüße
und danke schonmal!

Lukas B.

von Jean P. (fubu1000)


Lesenswert?

Hallo,
habe dein Programm zwar nur überflogen, aber Pin PB2 muß als Ausgang 
gesetzt werden beim MAster Betrieb. Davon einmal abgesehen würde ich 
alle deine "int" durch "unsigned char" ersetzen.

Gruß

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

SS mußt du mein ich doch per "Hand" ansteuren da du damit dem Slave 
bekannt gibts das das byte "fertig" ist...

von Christian L. (lorio)


Lesenswert?

Musst du nicht

MOSI <-> MOSI
MISO <-> MISO

verbinden?
Schließlich heit das doch Master Out, Slave In.

Gruß
Christian

von Matthias L. (Gast)


Lesenswert?

>Pin PB2 muß als Ausgang gesetzt werden beim MAster Betrieb.

Das ist sicherlich \SS.

>SS mußt du mein ich doch per "Hand" ansteuren da du damit dem Slave
>bekannt gibts das das byte "fertig" ist...


Am besten beide \SS verbinden. Beim Master ein LOW ausgeben während der 
übertragung.


>SCK <--> SCK
>MISO <--> MOSI
>MOSI <--> MISO

Das ist falsch.
MISO = MasterIn  SlaveOut
MOSI = MasterOut SlaveIn

Somit muss folgendes verschaltet werden:
Master                     Slave
MASTER_IN_slave_out         master_in_SLAVE_OUT
MASTER_OUT_slave_in         master_out_SLAVE_IN

Also: MISO an MISO und MOSI an MOSI.

Sonst gibts Murks.


PS: Alles im Datenblatt beschrieben!

von Lukas B. (lukasb)


Lesenswert?

hey dankeschön!


RTFM ist wohl manchmal echt angebracht. ;-)

aber ich habe die ganze zeit alles überprüft und immer wieder 
nachgelesen. habe nur nie in frage gestellt das MISO an MOSI gehört -> 
ist wohl als anfängerfehler abzutun.

tut jetzt wunderbar!

danke nochmal!

von Lukas B. (lukasb)


Lesenswert?

ach eine frage noch am rande:

(vermutlich steht es zwischen den zeilen auch in der manual, aber 
vielleicht kanns mir ja einer kurz und knapp beantworten)

da steht "full duplex" drin. aber wie kann die SPI übertragung full 
duplex sein, wenn ich zum lesen und schreiben jeweils das gleich byte 
benutze?

von Gast (Gast)


Lesenswert?

# Halbduplex (HX), auch Semiduplex genannt bedeutet wechselseitiger 
Betrieb. Hierbei können Informationen in beide Richtungen fließen, 
allerdings nicht gleichzeitig, z. B. Amateurfunk.
# Vollduplex (DX, manchmal auch FDX) ist der gleichzeitige Betrieb. Es 
lässt die Übertragung der Informationen in beide Richtungen zu gleicher 
Zeit zu, z. B. Telefonie.

Siehe: http://de.wikipedia.org/wiki/Duplex_(Nachrichtentechnik)

von Stefan E. (sternst)


Lesenswert?

Lukas Baumann wrote:

> da steht "full duplex" drin. aber wie kann die SPI übertragung full
> duplex sein, wenn ich zum lesen und schreiben jeweils das gleich byte
> benutze?

Du meinst vermutlich mit "Byte" eher "Register". Es werden zwei 
verschiedene Register sein, die über die selbe Adresse angesprochen 
werden. Beim Lesen von der Adresse halt das eine Register, und beim 
Schreiben auf die Adresse das andere.

von lukas b. (Gast)


Lesenswert?

alles klar, danke

von Martin (Gast)


Lesenswert?

Hallo Lukas,

kannst du bitte deine "gdi_test.h" posten??

Gruß
Martin

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.